From 2626a21094494b52220a723385b7a30a13b6b30b Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 22 Jun 2023 06:31:17 +0000 Subject: [PATCH 0001/1066] skip the BuildKit tests in the rootless integration Signed-off-by: Kay Yan --- .github/workflows/test.yml | 2 +- Dockerfile.d/test-integration-rootless.sh | 10 +++++----- cmd/nerdctl/container_run_test.go | 1 + cmd/nerdctl/image_encrypt_linux_test.go | 1 + cmd/nerdctl/image_push_linux_test.go | 7 +++++++ 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fb243e08431..2e8bc1c9a6d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -149,7 +149,7 @@ jobs: - name: "Prepare (network driver=slirp4netns, port driver=builtin)" run: DOCKER_BUILDKIT=1 docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . - name: "Test (network driver=slirp4netns, port driver=builtin)" - run: docker run -t --rm --privileged ${TEST_TARGET} + run: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=1 ${TEST_TARGET} cross: runs-on: ubuntu-22.04 diff --git a/Dockerfile.d/test-integration-rootless.sh b/Dockerfile.d/test-integration-rootless.sh index 6231f34f4d6..00975410f7f 100755 --- a/Dockerfile.d/test-integration-rootless.sh +++ b/Dockerfile.d/test-integration-rootless.sh @@ -21,9 +21,9 @@ if [[ "$(id -u)" = "0" ]]; then nerdctl apparmor load fi - : "${WORKAROUND_CIRRUS:=}" - if [[ "$WORKAROUND_CIRRUS" = "1" ]]; then - touch /workaround-cirrus + : "${WORKAROUND_ISSUE_622:=}" + if [[ "$WORKAROUND_ISSUE_622" = "1" ]]; then + touch /workaround-issue-622 fi # Switch to the rootless user via SSH @@ -35,8 +35,8 @@ else containerd-rootless-setuptool.sh nsenter -- sh -euc 'echo "options use-vc" >>/etc/resolv.conf' fi - if [[ -e /workaround-cirrus ]]; then - echo "WORKAROUND_CIRRUS: Not enabling BuildKit (https://github.com/containerd/nerdctl/issues/622)" >&2 + if [[ -e /workaround-issue-622 ]]; then + echo "WORKAROUND_ISSUE_622: Not enabling BuildKit (https://github.com/containerd/nerdctl/issues/622)" >&2 else CONTAINERD_NAMESPACE="nerdctl-test" containerd-rootless-setuptool.sh install-buildkit-containerd fi diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index 1bf584a2be3..7e8bfd77a46 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -357,6 +357,7 @@ func TestRunWithJournaldLogDriverAndLogOpt(t *testing.T) { } func TestRunWithLogBinary(t *testing.T) { + testutil.RequiresBuild(t) if runtime.GOOS == "windows" { t.Skip("buildkit is not enabled on windows, this feature may work on windows.") } diff --git a/cmd/nerdctl/image_encrypt_linux_test.go b/cmd/nerdctl/image_encrypt_linux_test.go index 9236a5ca33a..873d08b212a 100644 --- a/cmd/nerdctl/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image_encrypt_linux_test.go @@ -107,6 +107,7 @@ func rmiAll(base *testutil.Base) { } func TestImageEncryptJWE(t *testing.T) { + testutil.RequiresBuild(t) testutil.DockerIncompatible(t) keyPair := newJWEKeyPair(t) defer keyPair.cleanup() diff --git a/cmd/nerdctl/image_push_linux_test.go b/cmd/nerdctl/image_push_linux_test.go index bfe8cb02bcf..ccf5673fed6 100644 --- a/cmd/nerdctl/image_push_linux_test.go +++ b/cmd/nerdctl/image_push_linux_test.go @@ -28,6 +28,7 @@ import ( ) func TestPushPlainHTTPFails(t *testing.T) { + testutil.RequiresBuild(t) base := testutil.NewBase(t) reg := testregistry.NewPlainHTTP(base, 5000) defer reg.Cleanup() @@ -46,6 +47,7 @@ func TestPushPlainHTTPFails(t *testing.T) { } func TestPushPlainHTTPLocalhost(t *testing.T) { + testutil.RequiresBuild(t) base := testutil.NewBase(t) reg := testregistry.NewPlainHTTP(base, 5000) defer reg.Cleanup() @@ -62,6 +64,7 @@ func TestPushPlainHTTPLocalhost(t *testing.T) { } func TestPushPlainHTTPInsecure(t *testing.T) { + testutil.RequiresBuild(t) // Skip docker, because "dockerd --insecure-registries" requires restarting the daemon testutil.DockerIncompatible(t) @@ -79,6 +82,7 @@ func TestPushPlainHTTPInsecure(t *testing.T) { } func TestPushPlainHttpInsecureWithDefaultPort(t *testing.T) { + testutil.RequiresBuild(t) // Skip docker, because "dockerd --insecure-registries" requires restarting the daemon testutil.DockerIncompatible(t) @@ -96,6 +100,7 @@ func TestPushPlainHttpInsecureWithDefaultPort(t *testing.T) { } func TestPushInsecureWithLogin(t *testing.T) { + testutil.RequiresBuild(t) // Skip docker, because "dockerd --insecure-registries" requires restarting the daemon testutil.DockerIncompatible(t) @@ -116,6 +121,7 @@ func TestPushInsecureWithLogin(t *testing.T) { } func TestPushWithHostsDir(t *testing.T) { + testutil.RequiresBuild(t) // Skip docker, because Docker doesn't have `--hosts-dir` option, and we don't want to contaminate the global /etc/docker/certs.d during this test testutil.DockerIncompatible(t) @@ -135,6 +141,7 @@ func TestPushWithHostsDir(t *testing.T) { } func TestPushNonDistributableArtifacts(t *testing.T) { + testutil.RequiresBuild(t) // Skip docker, because "dockerd --insecure-registries" requires restarting the daemon // Skip docker, because "--allow-nondistributable-artifacts" is a daemon-only option and requires restarting the daemon testutil.DockerIncompatible(t) From 5724e7e42d55091b760e6925cb0a1f094308245c Mon Sep 17 00:00:00 2001 From: Ziwen Ning Date: Thu, 15 Jun 2023 01:52:29 -0700 Subject: [PATCH 0002/1066] refactor: container stats command Signed-off-by: Ziwen Ning --- cmd/nerdctl/container_stats.go | 431 +---------------- pkg/api/types/container_types.go | 16 + pkg/cmd/container/stats.go | 432 ++++++++++++++++++ .../cmd/container/stats_freebsd.go | 2 +- .../cmd/container/stats_linux.go | 2 +- .../cmd/container/stats_windows.go | 2 +- 6 files changed, 475 insertions(+), 410 deletions(-) create mode 100644 pkg/cmd/container/stats.go rename cmd/nerdctl/container_stats_freebsd.go => pkg/cmd/container/stats_freebsd.go (98%) rename cmd/nerdctl/container_stats_linux.go => pkg/cmd/container/stats_linux.go (99%) rename cmd/nerdctl/container_stats_windows.go => pkg/cmd/container/stats_windows.go (98%) diff --git a/cmd/nerdctl/container_stats.go b/cmd/nerdctl/container_stats.go index 63fc5b37515..9d47f34c172 100644 --- a/cmd/nerdctl/container_stats.go +++ b/cmd/nerdctl/container_stats.go @@ -17,32 +17,10 @@ package main import ( - "bytes" - "context" - "errors" - "fmt" - "strings" - "sync" - "text/tabwriter" - "text/template" - "time" - "github.com/containerd/containerd" - eventstypes "github.com/containerd/containerd/api/events" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/events" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/containerinspector" - "github.com/containerd/nerdctl/pkg/eventutil" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/statsutil" - "github.com/containerd/typeurl/v2" - "github.com/sirupsen/logrus" + "github.com/containerd/nerdctl/pkg/cmd/container" "github.com/spf13/cobra" ) @@ -68,417 +46,56 @@ func addStatsFlags(cmd *cobra.Command) { cmd.Flags().Bool("no-trunc", false, "Do not truncate output") } -type stats struct { - mu sync.Mutex - cs []*statsutil.Stats -} - -// add is from https://github.com/docker/cli/blob/3fb4fb83dfb5db0c0753a8316f21aea54dab32c5/cli/command/container/stats_helpers.go#L26-L34 -func (s *stats) add(cs *statsutil.Stats) bool { - s.mu.Lock() - defer s.mu.Unlock() - if _, exists := s.isKnownContainer(cs.Container); !exists { - s.cs = append(s.cs, cs) - return true - } - return false -} - -// remove is from https://github.com/docker/cli/blob/3fb4fb83dfb5db0c0753a8316f21aea54dab32c5/cli/command/container/stats_helpers.go#L36-L42 -func (s *stats) remove(id string) { - s.mu.Lock() - if i, exists := s.isKnownContainer(id); exists { - s.cs = append(s.cs[:i], s.cs[i+1:]...) - } - s.mu.Unlock() -} - -// isKnownContainer is from https://github.com/docker/cli/blob/3fb4fb83dfb5db0c0753a8316f21aea54dab32c5/cli/command/container/stats_helpers.go#L44-L51 -func (s *stats) isKnownContainer(cid string) (int, bool) { - for i, c := range s.cs { - if c.Container == cid { - return i, true - } - } - return -1, false -} - -func statsAction(cmd *cobra.Command, args []string) error { - - // NOTE: rootless container does not rely on cgroupv1. - // more details about possible ways to resolve this concern: #223 +func processStatsCommandFlags(cmd *cobra.Command) (types.ContainerStatsOptions, error) { globalOptions, err := processRootCmdFlags(cmd) if err != nil { - return err + return types.ContainerStatsOptions{}, err } - 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(args) == 0 - closeChan := make(chan error) all, err := cmd.Flags().GetBool("all") if err != nil { - return err + return types.ContainerStatsOptions{}, err } noStream, err := cmd.Flags().GetBool("no-stream") if err != nil { - return err + return types.ContainerStatsOptions{}, err } format, err := cmd.Flags().GetString("format") if err != nil { - return err - } - var w = cmd.OutOrStdout() - var tmpl *template.Template - switch format { - case "", "table": - w = tabwriter.NewWriter(cmd.OutOrStdout(), 10, 1, 3, ' ', 0) - case "raw": - return errors.New("unsupported format: \"raw\"") - default: - tmpl, err = formatter.ParseTemplate(format) - if err != nil { - return err - } + return types.ContainerStatsOptions{}, err } noTrunc, err := cmd.Flags().GetBool("no-trunc") if err != nil { - return err - } + return types.ContainerStatsOptions{}, err + } + + return types.ContainerStatsOptions{ + Stdout: cmd.OutOrStdout(), + Stderr: cmd.ErrOrStderr(), + GOptions: globalOptions, + All: all, + Format: format, + NoStream: noStream, + NoTrunc: noTrunc, + }, nil +} - // waitFirst is a WaitGroup to wait first stat data's reach for each container - waitFirst := &sync.WaitGroup{} - cStats := stats{} - client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) +func statsAction(cmd *cobra.Command, args []string) error { + options, err := processStatsCommandFlags(cmd) if err != nil { return err } - defer cancel() - - monitorContainerEvents := func(started chan<- struct{}, c chan *events.Envelope) { - eventsClient := client.EventService() - eventsCh, errCh := eventsClient.Subscribe(ctx) - - // Whether we successfully subscribed to eventsCh or not, we can now - // unblock the main goroutine. - close(started) - - for { - select { - case event := <-eventsCh: - c <- event - case err = <-errCh: - closeChan <- err - return - } - } - - } - - // getContainerList get all existing containers (only used when calling `nerdctl stats` without arguments). - getContainerList := func() { - containers, err := client.Containers(ctx) - if err != nil { - closeChan <- err - } - - for _, c := range containers { - cStatus := formatter.ContainerStatus(ctx, c) - if !all { - if !strings.HasPrefix(cStatus, "Up") { - continue - } - } - s := statsutil.NewStats(c.ID()) - if cStats.add(s) { - waitFirst.Add(1) - go collect(cmd, globalOptions, s, waitFirst, c.ID(), !noStream) - } - } - } - if showAll { - started := make(chan struct{}) - var ( - datacc *eventstypes.ContainerCreate - datacd *eventstypes.ContainerDelete - ) - - eh := eventutil.InitEventHandler() - eh.Handle("/containers/create", func(e events.Envelope) { - if e.Event != nil { - anydata, err := typeurl.UnmarshalAny(e.Event) - if err != nil { - // just skip - return - } - switch v := anydata.(type) { - case *eventstypes.ContainerCreate: - datacc = v - default: - // just skip - return - } - } - s := statsutil.NewStats(datacc.ID) - if cStats.add(s) { - waitFirst.Add(1) - go collect(cmd, globalOptions, s, waitFirst, datacc.ID, !noStream) - } - }) - - eh.Handle("/containers/delete", func(e events.Envelope) { - if e.Event != nil { - anydata, err := typeurl.UnmarshalAny(e.Event) - if err != nil { - // just skip - return - } - switch v := anydata.(type) { - case *eventstypes.ContainerDelete: - datacd = v - default: - // just skip - return - } - } - cStats.remove(datacd.ID) - }) - - eventChan := make(chan *events.Envelope) - - go eh.Watch(eventChan) - go monitorContainerEvents(started, eventChan) - - defer close(eventChan) - <-started - - // Start a goroutine to retrieve the initial list of containers stats. - getContainerList() - - // make sure each container get at least one valid stat data - waitFirst.Wait() - - } else { - walker := &containerwalker.ContainerWalker{ - Client: client, - OnFound: func(ctx context.Context, found containerwalker.Found) error { - s := statsutil.NewStats(found.Container.ID()) - if cStats.add(s) { - waitFirst.Add(1) - go collect(cmd, globalOptions, s, waitFirst, found.Container.ID(), !noStream) - } - return nil - }, - } - - if err := walker.WalkAll(ctx, args, false); err != nil { - return err - } - - // make sure each container get at least one valid stat data - waitFirst.Wait() - - } - - cleanScreen := func() { - if !noStream { - fmt.Fprint(cmd.OutOrStdout(), "\033[2J") - fmt.Fprint(cmd.OutOrStdout(), "\033[H") - } - } - - ticker := time.NewTicker(500 * time.Millisecond) - defer ticker.Stop() - - // firstTick is for creating distant CPU readings. - // firstTick stats are not displayed. - var firstTick = true - for range ticker.C { - cleanScreen() - ccstats := []statsutil.StatsEntry{} - cStats.mu.Lock() - for _, c := range cStats.cs { - if err := c.GetError(); err != nil { - fmt.Fprintf(cmd.ErrOrStderr(), "unable to get stat entry: %s\n", err) - } - ccstats = append(ccstats, c.GetStatistics()) - } - cStats.mu.Unlock() - - if !firstTick { - // print header for every tick - if format == "" || format == "table" { - fmt.Fprintln(w, "CONTAINER ID\tNAME\tCPU %\tMEM USAGE / LIMIT\tMEM %\tNET I/O\tBLOCK I/O\tPIDS") - } - } - - for _, c := range ccstats { - if c.ID == "" { - continue - } - rc := statsutil.RenderEntry(&c, noTrunc) - if !firstTick { - if tmpl != nil { - var b bytes.Buffer - if err := tmpl.Execute(&b, rc); err != nil { - break - } - if _, err = fmt.Fprintln(cmd.OutOrStdout(), b.String()); err != nil { - break - } - } else { - if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", - rc.ID, - rc.Name, - rc.CPUPerc, - rc.MemUsage, - rc.MemPerc, - rc.NetIO, - rc.BlockIO, - rc.PIDs, - ); err != nil { - break - } - } - } - } - if f, ok := w.(formatter.Flusher); ok { - f.Flush() - } - - if len(cStats.cs) == 0 && !showAll { - break - } - if noStream && !firstTick { - break - } - select { - case err, ok := <-closeChan: - if ok { - if err != nil { - return err - } - } - default: - // just skip - } - firstTick = false - } - - return err -} - -func collect(cmd *cobra.Command, globalOptions types.GlobalCommandOptions, s *statsutil.Stats, waitFirst *sync.WaitGroup, id string, noStream bool) { - logrus.Debugf("collecting stats for %s", s.Container) - var ( - getFirst = true - u = make(chan error, 1) - ) - - defer func() { - // if error happens and we get nothing of stats, release wait group whatever - if getFirst { - getFirst = false - waitFirst.Done() - } - }() - client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), options.GOptions.Namespace, options.GOptions.Address) if err != nil { - s.SetError(err) - return + return err } defer cancel() - container, err := client.LoadContainer(ctx, id) - if err != nil { - s.SetError(err) - return - } - - go func() { - previousStats := new(statsutil.ContainerStats) - firstSet := true - for { - //task is in the for loop to avoid nil task just after Container creation - task, err := container.Task(ctx, nil) - if err != nil { - u <- err - continue - } - - //labels is in the for loop to avoid nil labels just after Container creation - clabels, err := container.Labels(ctx) - if err != nil { - u <- err - continue - } - metric, err := task.Metrics(ctx) - if err != nil { - u <- err - continue - } - anydata, err := typeurl.UnmarshalAny(metric.Data) - if err != nil { - u <- err - continue - } - - netNS, err := containerinspector.InspectNetNS(ctx, int(task.Pid())) - if err != nil { - u <- err - continue - } - - // when (firstSet == true), we only set container stats without rendering stat entry - statsEntry, err := setContainerStatsAndRenderStatsEntry(previousStats, firstSet, anydata, int(task.Pid()), netNS.Interfaces) - if err != nil { - u <- err - continue - } - statsEntry.Name = clabels[labels.Name] - statsEntry.ID = container.ID() - - if firstSet { - firstSet = false - } else { - s.SetStatistics(statsEntry) - } - u <- nil - //sleep to create distant CPU readings - time.Sleep(500 * time.Millisecond) - } - }() - for { - select { - case <-time.After(6 * time.Second): - // zero out the values if we have not received an update within - // the specified duration. - s.SetErrorAndReset(errors.New("timeout waiting for stats")) - // if this is the first stat you get, release WaitGroup - if getFirst { - getFirst = false - waitFirst.Done() - } - case err := <-u: - if err != nil { - if !errdefs.IsNotFound(err) { - s.SetError(err) - continue - } - } - // if this is the first stat you get, release WaitGroup - if getFirst { - getFirst = false - waitFirst.Done() - } - } - } + return container.Stats(ctx, client, args, options) } func statsShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index 7c1109284b1..6cef4be0502 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -420,3 +420,19 @@ type ContainerCpOptions struct { // Follow symbolic links in SRC_PATH FollowSymLink bool } + +// ContainerStatsOptions specifies options for `nerdctl stats`. +type ContainerStatsOptions struct { + Stdout io.Writer + Stderr io.Writer + // GOptions is the global options. + GOptions GlobalCommandOptions + // Show all containers (default shows just running). + All bool + // Pretty-print images using a Go template, e.g., {{json .}}. + Format string + // Disable streaming stats and only pull the first result. + NoStream bool + // Do not truncate output. + NoTrunc bool +} diff --git a/pkg/cmd/container/stats.go b/pkg/cmd/container/stats.go new file mode 100644 index 00000000000..bdc09ed99a2 --- /dev/null +++ b/pkg/cmd/container/stats.go @@ -0,0 +1,432 @@ +/* + 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 container + +import ( + "bytes" + "context" + "errors" + "fmt" + "strings" + "sync" + "text/tabwriter" + "text/template" + "time" + + "github.com/containerd/containerd" + eventstypes "github.com/containerd/containerd/api/events" + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/events" + "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/pkg/clientutil" + "github.com/containerd/nerdctl/pkg/containerinspector" + "github.com/containerd/nerdctl/pkg/eventutil" + "github.com/containerd/nerdctl/pkg/formatter" + "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/pkg/infoutil" + "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/pkg/statsutil" + "github.com/containerd/typeurl/v2" + "github.com/sirupsen/logrus" +) + +type stats struct { + mu sync.Mutex + cs []*statsutil.Stats +} + +// add is from https://github.com/docker/cli/blob/3fb4fb83dfb5db0c0753a8316f21aea54dab32c5/cli/command/container/stats_helpers.go#L26-L34 +func (s *stats) add(cs *statsutil.Stats) bool { + s.mu.Lock() + defer s.mu.Unlock() + if _, exists := s.isKnownContainer(cs.Container); !exists { + s.cs = append(s.cs, cs) + return true + } + return false +} + +// remove is from https://github.com/docker/cli/blob/3fb4fb83dfb5db0c0753a8316f21aea54dab32c5/cli/command/container/stats_helpers.go#L36-L42 +func (s *stats) remove(id string) { + s.mu.Lock() + if i, exists := s.isKnownContainer(id); exists { + s.cs = append(s.cs[:i], s.cs[i+1:]...) + } + s.mu.Unlock() +} + +// isKnownContainer is from https://github.com/docker/cli/blob/3fb4fb83dfb5db0c0753a8316f21aea54dab32c5/cli/command/container/stats_helpers.go#L44-L51 +func (s *stats) isKnownContainer(cid string) (int, bool) { + for i, c := range s.cs { + if c.Container == cid { + return i, true + } + } + return -1, false +} + +// 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 { + // 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 + closeChan := make(chan error) + + var err error + var w = options.Stdout + var tmpl *template.Template + switch options.Format { + case "", "table": + w = tabwriter.NewWriter(options.Stdout, 10, 1, 3, ' ', 0) + case "raw": + return errors.New("unsupported format: \"raw\"") + default: + tmpl, err = formatter.ParseTemplate(options.Format) + if err != nil { + return err + } + } + + // waitFirst is a WaitGroup to wait first stat data's reach for each container + waitFirst := &sync.WaitGroup{} + cStats := stats{} + + monitorContainerEvents := func(started chan<- struct{}, c chan *events.Envelope) { + eventsClient := client.EventService() + eventsCh, errCh := eventsClient.Subscribe(ctx) + + // Whether we successfully subscribed to eventsCh or not, we can now + // unblock the main goroutine. + close(started) + + for { + select { + case event := <-eventsCh: + c <- event + case err = <-errCh: + closeChan <- err + return + } + } + + } + + // getContainerList get all existing containers (only used when calling `nerdctl stats` without arguments). + getContainerList := func() { + containers, err := client.Containers(ctx) + if err != nil { + closeChan <- err + } + + for _, c := range containers { + cStatus := formatter.ContainerStatus(ctx, c) + if !options.All { + if !strings.HasPrefix(cStatus, "Up") { + continue + } + } + s := statsutil.NewStats(c.ID()) + if cStats.add(s) { + waitFirst.Add(1) + go collect(ctx, options.GOptions, s, waitFirst, c.ID(), !options.NoStream) + } + } + } + + if showAll { + started := make(chan struct{}) + var ( + datacc *eventstypes.ContainerCreate + datacd *eventstypes.ContainerDelete + ) + + eh := eventutil.InitEventHandler() + eh.Handle("/containers/create", func(e events.Envelope) { + if e.Event != nil { + anydata, err := typeurl.UnmarshalAny(e.Event) + if err != nil { + // just skip + return + } + switch v := anydata.(type) { + case *eventstypes.ContainerCreate: + datacc = v + default: + // just skip + return + } + } + s := statsutil.NewStats(datacc.ID) + if cStats.add(s) { + waitFirst.Add(1) + go collect(ctx, options.GOptions, s, waitFirst, datacc.ID, !options.NoStream) + } + }) + + eh.Handle("/containers/delete", func(e events.Envelope) { + if e.Event != nil { + anydata, err := typeurl.UnmarshalAny(e.Event) + if err != nil { + // just skip + return + } + switch v := anydata.(type) { + case *eventstypes.ContainerDelete: + datacd = v + default: + // just skip + return + } + } + cStats.remove(datacd.ID) + }) + + eventChan := make(chan *events.Envelope) + + go eh.Watch(eventChan) + go monitorContainerEvents(started, eventChan) + + defer close(eventChan) + <-started + + // Start a goroutine to retrieve the initial list of containers stats. + getContainerList() + + // make sure each container get at least one valid stat data + waitFirst.Wait() + + } else { + walker := &containerwalker.ContainerWalker{ + Client: client, + OnFound: func(ctx context.Context, found containerwalker.Found) error { + s := statsutil.NewStats(found.Container.ID()) + if cStats.add(s) { + waitFirst.Add(1) + go collect(ctx, options.GOptions, s, waitFirst, found.Container.ID(), !options.NoStream) + } + return nil + }, + } + + if err := walker.WalkAll(ctx, containerIds, false); err != nil { + return err + } + + // make sure each container get at least one valid stat data + waitFirst.Wait() + + } + + cleanScreen := func() { + if !options.NoStream { + fmt.Fprint(options.Stdout, "\033[2J") + fmt.Fprint(options.Stdout, "\033[H") + } + } + + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + + // firstTick is for creating distant CPU readings. + // firstTick stats are not displayed. + var firstTick = true + for range ticker.C { + cleanScreen() + ccstats := []statsutil.StatsEntry{} + cStats.mu.Lock() + for _, c := range cStats.cs { + if err := c.GetError(); err != nil { + fmt.Fprintf(options.Stderr, "unable to get stat entry: %s\n", err) + } + ccstats = append(ccstats, c.GetStatistics()) + } + cStats.mu.Unlock() + + if !firstTick { + // print header for every tick + if options.Format == "" || options.Format == "table" { + fmt.Fprintln(w, "CONTAINER ID\tNAME\tCPU %\tMEM USAGE / LIMIT\tMEM %\tNET I/O\tBLOCK I/O\tPIDS") + } + } + + for _, c := range ccstats { + if c.ID == "" { + continue + } + rc := statsutil.RenderEntry(&c, options.NoTrunc) + if !firstTick { + if tmpl != nil { + var b bytes.Buffer + if err := tmpl.Execute(&b, rc); err != nil { + break + } + if _, err = fmt.Fprintln(options.Stdout, b.String()); err != nil { + break + } + } else { + if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", + rc.ID, + rc.Name, + rc.CPUPerc, + rc.MemUsage, + rc.MemPerc, + rc.NetIO, + rc.BlockIO, + rc.PIDs, + ); err != nil { + break + } + } + } + } + if f, ok := w.(formatter.Flusher); ok { + f.Flush() + } + + if len(cStats.cs) == 0 && !showAll { + break + } + if options.NoStream && !firstTick { + break + } + select { + case err, ok := <-closeChan: + if ok { + if err != nil { + return err + } + } + default: + // just skip + } + firstTick = false + } + + return err +} + +func collect(ctx context.Context, globalOptions types.GlobalCommandOptions, s *statsutil.Stats, waitFirst *sync.WaitGroup, id string, noStream bool) { + logrus.Debugf("collecting stats for %s", s.Container) + var ( + getFirst = true + u = make(chan error, 1) + ) + + defer func() { + // if error happens and we get nothing of stats, release wait group whatever + if getFirst { + getFirst = false + waitFirst.Done() + } + }() + client, ctx, cancel, err := clientutil.NewClient(ctx, globalOptions.Namespace, globalOptions.Address) + if err != nil { + s.SetError(err) + return + } + defer cancel() + container, err := client.LoadContainer(ctx, id) + if err != nil { + s.SetError(err) + return + } + + go func() { + previousStats := new(statsutil.ContainerStats) + firstSet := true + for { + //task is in the for loop to avoid nil task just after Container creation + task, err := container.Task(ctx, nil) + if err != nil { + u <- err + continue + } + + //labels is in the for loop to avoid nil labels just after Container creation + clabels, err := container.Labels(ctx) + if err != nil { + u <- err + continue + } + + metric, err := task.Metrics(ctx) + if err != nil { + u <- err + continue + } + anydata, err := typeurl.UnmarshalAny(metric.Data) + if err != nil { + u <- err + continue + } + + netNS, err := containerinspector.InspectNetNS(ctx, int(task.Pid())) + if err != nil { + u <- err + continue + } + + // when (firstSet == true), we only set container stats without rendering stat entry + statsEntry, err := setContainerStatsAndRenderStatsEntry(previousStats, firstSet, anydata, int(task.Pid()), netNS.Interfaces) + if err != nil { + u <- err + continue + } + statsEntry.Name = clabels[labels.Name] + statsEntry.ID = container.ID() + + if firstSet { + firstSet = false + } else { + s.SetStatistics(statsEntry) + } + u <- nil + //sleep to create distant CPU readings + time.Sleep(500 * time.Millisecond) + } + }() + for { + select { + case <-time.After(6 * time.Second): + // zero out the values if we have not received an update within + // the specified duration. + s.SetErrorAndReset(errors.New("timeout waiting for stats")) + // if this is the first stat you get, release WaitGroup + if getFirst { + getFirst = false + waitFirst.Done() + } + case err := <-u: + if err != nil { + if !errdefs.IsNotFound(err) { + s.SetError(err) + continue + } + } + // if this is the first stat you get, release WaitGroup + if getFirst { + getFirst = false + waitFirst.Done() + } + } + } +} diff --git a/cmd/nerdctl/container_stats_freebsd.go b/pkg/cmd/container/stats_freebsd.go similarity index 98% rename from cmd/nerdctl/container_stats_freebsd.go rename to pkg/cmd/container/stats_freebsd.go index a6460b3218a..e2dbea58ea6 100644 --- a/cmd/nerdctl/container_stats_freebsd.go +++ b/pkg/cmd/container/stats_freebsd.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/containerd/nerdctl/pkg/inspecttypes/native" diff --git a/cmd/nerdctl/container_stats_linux.go b/pkg/cmd/container/stats_linux.go similarity index 99% rename from cmd/nerdctl/container_stats_linux.go rename to pkg/cmd/container/stats_linux.go index a8d29deec3f..49d9eb488db 100644 --- a/cmd/nerdctl/container_stats_linux.go +++ b/pkg/cmd/container/stats_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "errors" diff --git a/cmd/nerdctl/container_stats_windows.go b/pkg/cmd/container/stats_windows.go similarity index 98% rename from cmd/nerdctl/container_stats_windows.go rename to pkg/cmd/container/stats_windows.go index a6460b3218a..e2dbea58ea6 100644 --- a/cmd/nerdctl/container_stats_windows.go +++ b/pkg/cmd/container/stats_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/containerd/nerdctl/pkg/inspecttypes/native" From 788cca48092868a471fd4445020a3c0d9aec6b96 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Sat, 24 Jun 2023 04:29:23 +0000 Subject: [PATCH 0003/1066] fix the restart policy in kill Signed-off-by: Kay Yan --- pkg/cmd/container/kill.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index 5652dbf9031..a4c3ecd388e 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/pkg/containerutil" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/moby/sys/signal" "github.com/sirupsen/logrus" @@ -64,7 +65,15 @@ func Kill(ctx context.Context, client *containerd.Client, reqs []string, options return walker.WalkAll(ctx, reqs, true) } -func killContainer(ctx context.Context, container containerd.Container, signal syscall.Signal) error { +func killContainer(ctx context.Context, container containerd.Container, signal syscall.Signal) (err error) { + defer func() { + if err != nil { + containerutil.UpdateErrorLabel(ctx, container, err) + } + }() + if err := containerutil.UpdateExplicitlyStoppedLabel(ctx, container, true); err != nil { + return err + } task, err := container.Task(ctx, cio.Load) if err != nil { return err From dcf01dec370315aa6396bea1e7189f94b5fd55dc Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Mon, 26 Jun 2023 14:42:31 +0000 Subject: [PATCH 0004/1066] Optimize for itoa operations Signed-off-by: Austin Vazquez --- cmd/nerdctl/container_run_log_driver_syslog_test.go | 3 ++- pkg/ipfs/registry.go | 3 ++- pkg/logging/json_logger.go | 2 +- pkg/statsutil/stats.go | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/container_run_log_driver_syslog_test.go b/cmd/nerdctl/container_run_log_driver_syslog_test.go index 678006362b9..a46f8f8936b 100644 --- a/cmd/nerdctl/container_run_log_driver_syslog_test.go +++ b/cmd/nerdctl/container_run_log_driver_syslog_test.go @@ -20,6 +20,7 @@ import ( "fmt" "os" "runtime" + "strconv" "strings" "testing" "time" @@ -53,7 +54,7 @@ func runSyslogTest(t *testing.T, networks []string, syslogFacilities map[string] for rFK, rFV := range syslogFacilities { fPriV := rFV // test both string and number facility - for _, fPriK := range []string{rFK, fmt.Sprintf("%d", int(fPriV)>>3)} { + for _, fPriK := range []string{rFK, strconv.Itoa(int(fPriV) >> 3)} { for fmtK, fmtValidFunc := range fmtValidFuncs { fmtKT := "empty" if fmtK != "" { diff --git a/pkg/ipfs/registry.go b/pkg/ipfs/registry.go index 6dfc9687879..a80bfb8fdfa 100644 --- a/pkg/ipfs/registry.go +++ b/pkg/ipfs/registry.go @@ -25,6 +25,7 @@ import ( "io" "net/http" "regexp" + "strconv" "strings" "time" @@ -84,7 +85,7 @@ func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } w.Header().Set("Content-Type", mediaType) - w.Header().Set("Content-Length", fmt.Sprintf("%d", size)) + w.Header().Set("Content-Length", strconv.FormatInt(size, 10)) if r.Method == "GET" { http.ServeContent(w, r, "", time.Now(), content) logrus.WithField("CID", cid).Debugf("served file") diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index 61f84e2db34..5e61c615d93 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -204,7 +204,7 @@ func viewLogsJSONFileThroughTailExec(lvopts LogViewOptions, jsonLogFilePath stri if lvopts.Tail == 0 { args = append(args, "+0") } else { - args = append(args, fmt.Sprintf("%d", lvopts.Tail)) + args = append(args, strconv.FormatUint(uint64(lvopts.Tail), 10)) } if lvopts.Follow { diff --git a/pkg/statsutil/stats.go b/pkg/statsutil/stats.go index 41d86f667eb..05436b84f45 100644 --- a/pkg/statsutil/stats.go +++ b/pkg/statsutil/stats.go @@ -18,6 +18,7 @@ package statsutil import ( "fmt" + "strconv" "sync" "time" @@ -205,5 +206,5 @@ func (s *StatsEntry) PIDs() string { if s.IsInvalid { return "--" } - return fmt.Sprintf("%d", s.PidsCurrent) + return strconv.FormatUint(s.PidsCurrent, 10) } From 8d5868875bac032369eddeee91e625023da02ac4 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Sat, 24 Jun 2023 04:06:23 +0000 Subject: [PATCH 0005/1066] update docs stargz for docker version Signed-off-by: Kay Yan --- docs/stargz.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/stargz.md b/docs/stargz.md index b54efb4bac4..5a54fe17906 100644 --- a/docs/stargz.md +++ b/docs/stargz.md @@ -175,9 +175,9 @@ You can use zstd compression with lazy pulling support (a.k.a zstd:chunked) inst - [Faster](https://github.com/facebook/zstd/tree/v1.5.2#benchmarks) compression/decompression. - Cons - Old tools might not support. And unsupported by some tools yet. - - zstd support by OCI Image Specification is still under rc (2022/11). will be added to [v1.1.0](https://github.com/opencontainers/image-spec/commit/1a29e8675a64a5cdd2d93b6fa879a82d9a4d926a). - - zstd support unreleased [by Docker](https://github.com/moby/moby/pull/41759/commits/e187eb2bb5f0c3f899fe643e95d1af8c57e89a73) (will be added to v22.06). - - [containerd >= v1.5](https://github.com/containerd/containerd/releases/tag/v1.5.0) supports zstd. + - zstd supported by OCI Image Specification is still under rc (2022/11). will be added to [v1.1.0](https://github.com/opencontainers/image-spec/commit/1a29e8675a64a5cdd2d93b6fa879a82d9a4d926a). + - zstd supported by [docker >=v23.0.0](https://github.com/moby/moby/releases/tag/v23.0.0). + - zstd supported by [containerd >= v1.5](https://github.com/containerd/containerd/releases/tag/v1.5.0). - `min-chunk-size`, `external-toc` (described in Tips 1) are unsupported yet. ```console From 11d80f274257c064924f40bd007756110d863a16 Mon Sep 17 00:00:00 2001 From: Ziwen Ning Date: Tue, 27 Jun 2023 01:46:54 -0700 Subject: [PATCH 0006/1066] refactor: extract the printing logic out of pkg for container list Signed-off-by: Ziwen Ning --- cmd/nerdctl/container_list.go | 152 ++++++++++++++++++++++++++----- pkg/api/types/container_types.go | 5 - pkg/cmd/container/list.go | 128 +++++--------------------- pkg/cmd/container/list_util.go | 4 +- 4 files changed, 154 insertions(+), 135 deletions(-) diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container_list.go index 8c8ad9011dc..0f7d9460ac1 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container_list.go @@ -17,9 +17,17 @@ package main import ( + "bytes" + "errors" + "fmt" + "io" + "text/tabwriter" + "text/template" + "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/pkg/formatter" "github.com/spf13/cobra" ) @@ -49,23 +57,23 @@ func newPsCommand() *cobra.Command { return psCommand } -func processContainerListOptions(cmd *cobra.Command) (types.ContainerListOptions, error) { +func processOptions(cmd *cobra.Command) (types.ContainerListOptions, FormattingAndPrintingOptions, error) { globalOptions, err := processRootCmdFlags(cmd) if err != nil { - return types.ContainerListOptions{}, err + return types.ContainerListOptions{}, FormattingAndPrintingOptions{}, err } all, err := cmd.Flags().GetBool("all") if err != nil { - return types.ContainerListOptions{}, err + return types.ContainerListOptions{}, FormattingAndPrintingOptions{}, err } latest, err := cmd.Flags().GetBool("latest") if err != nil { - return types.ContainerListOptions{}, err + return types.ContainerListOptions{}, FormattingAndPrintingOptions{}, err } lastN, err := cmd.Flags().GetInt("last") if err != nil { - return types.ContainerListOptions{}, err + return types.ContainerListOptions{}, FormattingAndPrintingOptions{}, err } if lastN == -1 && latest { lastN = 1 @@ -73,56 +81,154 @@ func processContainerListOptions(cmd *cobra.Command) (types.ContainerListOptions filters, err := cmd.Flags().GetStringSlice("filter") if err != nil { - return types.ContainerListOptions{}, err + return types.ContainerListOptions{}, FormattingAndPrintingOptions{}, err } noTrunc, err := cmd.Flags().GetBool("no-trunc") if err != nil { - return types.ContainerListOptions{}, err + return types.ContainerListOptions{}, FormattingAndPrintingOptions{}, err } trunc := !noTrunc quiet, err := cmd.Flags().GetBool("quiet") if err != nil { - return types.ContainerListOptions{}, err + return types.ContainerListOptions{}, FormattingAndPrintingOptions{}, err } format, err := cmd.Flags().GetString("format") if err != nil { - return types.ContainerListOptions{}, err + return types.ContainerListOptions{}, FormattingAndPrintingOptions{}, err } size := false if !quiet { size, err = cmd.Flags().GetBool("size") if err != nil { - return types.ContainerListOptions{}, err + return types.ContainerListOptions{}, FormattingAndPrintingOptions{}, err } } return types.ContainerListOptions{ - Stdout: cmd.OutOrStdout(), - GOptions: globalOptions, - All: all, - LastN: lastN, - Truncate: trunc, - Quiet: quiet, - Size: size, - Format: format, - Filters: filters, - }, nil + GOptions: globalOptions, + All: all, + LastN: lastN, + Truncate: trunc, + Size: size || (format == "wide" && !quiet), + Filters: filters, + }, FormattingAndPrintingOptions{ + Stdout: cmd.OutOrStdout(), + Quiet: quiet, + Format: format, + Size: size, + }, nil } func psAction(cmd *cobra.Command, args []string) error { - options, err := processContainerListOptions(cmd) + clOpts, fpOpts, err := processOptions(cmd) if err != nil { return err } - client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), options.GOptions.Namespace, options.GOptions.Address) + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), clOpts.GOptions.Namespace, clOpts.GOptions.Address) if err != nil { return err } defer cancel() - return container.List(ctx, client, options) + containers, err := container.List(ctx, client, clOpts) + if err != nil { + return err + } + + return formatAndPrintContainerInfo(containers, fpOpts) +} + +// FormattingAndPrintingOptions specifies options for formatting and printing of `nerdctl (container) list`. +type FormattingAndPrintingOptions struct { + Stdout io.Writer + // Only display container IDs. + Quiet bool + // Format the output using the given Go template (e.g., '{{json .}}', 'table', 'wide'). + Format string + // Display total file sizes. + Size bool +} + +func formatAndPrintContainerInfo(containers []container.ListItem, options FormattingAndPrintingOptions) error { + w := options.Stdout + var ( + wide bool + tmpl *template.Template + ) + switch options.Format { + case "", "table": + w = tabwriter.NewWriter(w, 4, 8, 4, ' ', 0) + if !options.Quiet { + printHeader := "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES" + if options.Size { + printHeader += "\tSIZE" + } + fmt.Fprintln(w, printHeader) + } + case "raw": + return errors.New("unsupported format: \"raw\"") + case "wide": + w = tabwriter.NewWriter(w, 4, 8, 4, ' ', 0) + if !options.Quiet { + fmt.Fprintln(w, "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES\tRUNTIME\tPLATFORM\tSIZE") + wide = true + } + default: + if options.Quiet { + return errors.New("format and quiet must not be specified together") + } + var err error + tmpl, err = formatter.ParseTemplate(options.Format) + if err != nil { + return err + } + } + + for _, c := range containers { + if tmpl != nil { + var b bytes.Buffer + if err := tmpl.Execute(&b, c); err != nil { + return err + } + if _, err := fmt.Fprintf(w, b.String()+"\n"); err != nil { + return err + } + } else if options.Quiet { + if _, err := fmt.Fprintf(w, "%s\n", c.ID); err != nil { + return err + } + } else { + format := "%s\t%s\t%s\t%s\t%s\t%s\t%s" + args := []interface{}{ + c.ID, + c.Image, + c.Command, + formatter.TimeSinceInHuman(c.CreatedAt), + c.Status, + c.Ports, + c.Names[0], + } + if wide { + format += "\t%s\t%s\t%s\n" + args = append(args, c.Runtime, c.Platform, c.Size) + } else if options.Size { + format += "\t%s\n" + args = append(args, c.Size) + } else { + format += "\n" + } + if _, err := fmt.Fprintf(w, format, args...); err != nil { + return err + } + } + + } + if f, ok := w.(formatter.Flusher); ok { + return f.Flush() + } + return nil } diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index a107f16cac1..ee6b4b30ef5 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -391,7 +391,6 @@ type ContainerExecOptions struct { // ContainerListOptions specifies options for `nerdctl (container) list`. type ContainerListOptions struct { - Stdout io.Writer // GOptions is the global options. GOptions GlobalCommandOptions // Show all containers (default shows just running). @@ -401,12 +400,8 @@ type ContainerListOptions struct { LastN int // Truncate output (e.g., container ID, command of the container main process, etc.) or not. Truncate bool - // Only display container IDs. - Quiet bool // Display total file sizes. Size bool - // Format the output using the given Go template (e.g., '{{json .}}', 'table', 'wide'). - Format string // Filters matches containers based on given conditions. Filters []string } diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index 0db83bc60fb..259edbd7bc9 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -17,15 +17,11 @@ package container import ( - "bytes" "context" "encoding/json" - "errors" "fmt" "sort" "strings" - "text/tabwriter" - "text/template" "time" "github.com/containerd/containerd" @@ -41,12 +37,12 @@ import ( ) // List prints containers according to `options`. -func List(ctx context.Context, client *containerd.Client, options types.ContainerListOptions) error { +func List(ctx context.Context, client *containerd.Client, options types.ContainerListOptions) ([]ListItem, error) { containers, err := filterContainers(ctx, client, options.Filters, options.LastN, options.All) if err != nil { - return err + return nil, err } - return printContainers(ctx, client, containers, options) + return prepareContainers(ctx, client, containers, options) } // filterContainers returns containers matching the filters. @@ -90,147 +86,69 @@ func filterContainers(ctx context.Context, client *containerd.Client, filters [] return upContainers, nil } -type containerPrintable struct { +type ListItem struct { Command string - CreatedAt string + CreatedAt time.Time ID string Image string Platform string // nerdctl extension - Names string + Names []string Ports string Status string Runtime string // nerdctl extension Size string - Labels string + Labels map[string]string // TODO: "LocalVolumes", "Mounts", "Networks", "RunningFor", "State" } -func printContainers(ctx context.Context, client *containerd.Client, containers []containerd.Container, options types.ContainerListOptions) error { - w := options.Stdout - var ( - wide bool - tmpl *template.Template - ) - switch options.Format { - case "", "table": - w = tabwriter.NewWriter(w, 4, 8, 4, ' ', 0) - if !options.Quiet { - printHeader := "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES" - if options.Size { - printHeader += "\tSIZE" - } - fmt.Fprintln(w, printHeader) - } - case "raw": - return errors.New("unsupported format: \"raw\"") - case "wide": - w = tabwriter.NewWriter(w, 4, 8, 4, ' ', 0) - if !options.Quiet { - fmt.Fprintln(w, "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES\tRUNTIME\tPLATFORM\tSIZE") - wide = true - } - default: - if options.Quiet { - return errors.New("format and quiet must not be specified together") - } - var err error - tmpl, err = formatter.ParseTemplate(options.Format) - if err != nil { - return err - } - } - - for _, c := range containers { +func prepareContainers(ctx context.Context, client *containerd.Client, containers []containerd.Container, options types.ContainerListOptions) ([]ListItem, error) { + listItems := make([]ListItem, len(containers)) + for i, c := range containers { info, err := c.Info(ctx, containerd.WithoutRefreshedMetadata) if err != nil { if errdefs.IsNotFound(err) { logrus.Warn(err) continue } - return err + return nil, err } - spec, err := c.Spec(ctx) if err != nil { if errdefs.IsNotFound(err) { logrus.Warn(err) continue } - return err + return nil, err } - - imageName := info.Image id := c.ID() if options.Truncate && len(id) > 12 { id = id[:12] } - - p := containerPrintable{ + li := ListItem{ Command: formatter.InspectContainerCommand(spec, options.Truncate, true), - CreatedAt: info.CreatedAt.Round(time.Second).Local().String(), // format like "2021-08-07 02:19:45 +0900 JST" + CreatedAt: info.CreatedAt, ID: id, - Image: imageName, + Image: info.Image, Platform: info.Labels[labels.Platform], - Names: getPrintableContainerName(info.Labels), + Names: []string{getContainerName(info.Labels)}, Ports: formatter.FormatPorts(info.Labels), Status: formatter.ContainerStatus(ctx, c), Runtime: info.Runtime.Name, - Labels: formatter.FormatLabels(info.Labels), + Labels: info.Labels, } - - if options.Size || wide { + if options.Size { containerSize, err := getContainerSize(ctx, client, c, info) if err != nil { - return err - } - p.Size = containerSize - } - - if tmpl != nil { - var b bytes.Buffer - if err := tmpl.Execute(&b, p); err != nil { - return err - } - if _, err = fmt.Fprintf(w, b.String()+"\n"); err != nil { - return err - } - } else if options.Quiet { - if _, err := fmt.Fprintf(w, "%s\n", id); err != nil { - return err - } - } else { - format := "%s\t%s\t%s\t%s\t%s\t%s\t%s" - args := []interface{}{ - p.ID, - p.Image, - p.Command, - formatter.TimeSinceInHuman(info.CreatedAt), - p.Status, - p.Ports, - p.Names, - } - if wide { - format += "\t%s\t%s\t%s\n" - args = append(args, p.Runtime, p.Platform, p.Size) - } else if options.Size { - format += "\t%s\n" - args = append(args, p.Size) - } else { - format += "\n" - } - if _, err := fmt.Fprintf(w, format, args...); err != nil { - return err + return nil, err } + li.Size = containerSize } - - } - if f, ok := w.(formatter.Flusher); ok { - return f.Flush() + listItems[i] = li } - return nil + return listItems, nil } -func getPrintableContainerName(containerLabels map[string]string) string { +func getContainerName(containerLabels map[string]string) string { if name, ok := containerLabels[labels.Name]; ok { return name } diff --git a/pkg/cmd/container/list_util.go b/pkg/cmd/container/list_util.go index 9a1aac22b37..a2041e0a71c 100644 --- a/pkg/cmd/container/list_util.go +++ b/pkg/cmd/container/list_util.go @@ -288,7 +288,7 @@ func (cl *containerFilterContext) matchesNameFilter(info containers.Container) b if len(cl.nameFilterFuncs) == 0 { return true } - cName := getPrintableContainerName(info.Labels) + cName := getContainerName(info.Labels) for _, nameFilterFunc := range cl.nameFilterFuncs { if !nameFilterFunc(cName) { continue @@ -367,7 +367,7 @@ func idOrNameFilter(ctx context.Context, containers []containerd.Container, valu if err != nil { return nil, err } - if strings.HasPrefix(info.ID, value) || strings.Contains(getPrintableContainerName(info.Labels), value) { + if strings.HasPrefix(info.ID, value) || strings.Contains(getContainerName(info.Labels), value) { return &info, nil } } From a5fac7a88b478fba644f4ce99cc2aecf8d057ab5 Mon Sep 17 00:00:00 2001 From: Eric Chan Date: Tue, 30 May 2023 08:40:10 +0800 Subject: [PATCH 0007/1066] Fix the rule of port allocate when executing -p multiple times for one command Signed-off-by: Eric Chan --- pkg/portutil/port_allocate_linux.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/portutil/port_allocate_linux.go b/pkg/portutil/port_allocate_linux.go index c3c6ca25e52..75ae344a58d 100644 --- a/pkg/portutil/port_allocate_linux.go +++ b/pkg/portutil/port_allocate_linux.go @@ -25,8 +25,11 @@ import ( const ( // This port range is compatible with Docker, FYI https://github.com/moby/moby/blob/eb9e42a09ee123af1d95bf7d46dd738258fa2109/libnetwork/portallocator/portallocator_unix.go#L7-L12 + allocateEnd = 60999 +) + +var ( allocateStart = 49153 - allocateEnd = 60999 ) func filter(ss []procnet.NetworkDetail, filterFunc func(detail procnet.NetworkDetail) bool) (ret []procnet.NetworkDetail) { @@ -96,6 +99,7 @@ func portAllocate(protocol string, ip string, count uint64) (uint64, uint64, err } } if needReturn { + allocateStart = int(start + count) return start, start + count - 1, nil } start += count From ec6734e6c3d2562e9c9b446afb0ea9a8bd94d666 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jun 2023 22:16:13 +0000 Subject: [PATCH 0008/1066] build(deps): bump github.com/containerd/cgroups/v3 from 3.0.1 to 3.0.2 Bumps [github.com/containerd/cgroups/v3](https://github.com/containerd/cgroups) from 3.0.1 to 3.0.2. - [Release notes](https://github.com/containerd/cgroups/releases) - [Commits](https://github.com/containerd/cgroups/compare/v3.0.1...v3.0.2) --- updated-dependencies: - dependency-name: github.com/containerd/cgroups/v3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0bc85eb2f89..d60ef5298a6 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Microsoft/hcsshim v0.10.0-rc.8 github.com/compose-spec/compose-go v1.14.0 github.com/containerd/accelerated-container-image v0.6.7 - github.com/containerd/cgroups/v3 v3.0.1 + github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.7.2 github.com/containerd/continuity v0.4.1 diff --git a/go.sum b/go.sum index 5eeffc995b1..ab359bd0538 100644 --- a/go.sum +++ b/go.sum @@ -191,8 +191,8 @@ github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f2 github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= 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.1 h1:4hfGvu8rfGIwVIDd+nLzn/B9ZXx4BcCjzt5ToenJRaE= -github.com/containerd/cgroups/v3 v3.0.1/go.mod h1:/vtwk1VXrtoa5AaZLkypuOJgA/6DyPMZHJPGQNtlHnw= +github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= +github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= From d1b6f425b77286d03aeb6bb5d0513e71f825b596 Mon Sep 17 00:00:00 2001 From: Ziwen Ning Date: Mon, 6 Feb 2023 01:15:09 -0800 Subject: [PATCH 0009/1066] feat: add --volumes-from support in run command Signed-off-by: Ziwen Ning --- cmd/nerdctl/container_create.go | 4 ++ cmd/nerdctl/container_run.go | 2 + cmd/nerdctl/container_run_mount_linux_test.go | 53 +++++++++++++++++++ docs/command-reference.md | 3 +- pkg/api/types/container_types.go | 2 + pkg/cmd/container/create.go | 17 ++++++ pkg/cmd/container/list.go | 41 -------------- pkg/cmd/container/list_util.go | 7 +-- pkg/cmd/container/run_mount.go | 49 +++++++++++++++++ pkg/containerutil/containerutil.go | 49 +++++++++++++++++ pkg/strutil/strutil.go | 13 +++++ pkg/strutil/strutil_test.go | 11 ++++ 12 files changed, 206 insertions(+), 45 deletions(-) diff --git a/cmd/nerdctl/container_create.go b/cmd/nerdctl/container_create.go index 27280f28c99..788429086fd 100644 --- a/cmd/nerdctl/container_create.go +++ b/cmd/nerdctl/container_create.go @@ -282,6 +282,10 @@ func processContainerCreateOptions(cmd *cobra.Command) (opt types.ContainerCreat if err != nil { return } + opt.VolumesFrom, err = cmd.Flags().GetStringArray("volumes-from") + if err != nil { + return + } // #endregion // #region for rootfs flags diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index fde5e6e023f..df6e4521806 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -199,6 +199,8 @@ func setCreateFlags(cmd *cobra.Command) { // tmpfs needs to be StringArray, not StringSlice, to prevent "/foo:size=64m,exec" from being split to {"/foo:size=64m", "exec"} cmd.Flags().StringArray("tmpfs", nil, "Mount a tmpfs directory") cmd.Flags().StringArray("mount", nil, "Attach a filesystem mount to the container") + // volumes-from needs to be StringArray, not StringSlice, to prevent "id1,id2" from being split to {"id1", "id2"} (compatible with Docker) + cmd.Flags().StringArray("volumes-from", nil, "Mount volumes from the specified container(s)") // #endregion // rootfs flags diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container_run_mount_linux_test.go index 352080de0be..b2eb09c3034 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container_run_mount_linux_test.go @@ -631,3 +631,56 @@ func isRootfsShareableMount() bool { return false } + +func TestRunVolumesFrom(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + tID := testutil.Identifier(t) + rwDir, err := os.MkdirTemp(t.TempDir(), "rw") + if err != nil { + t.Fatal(err) + } + roDir, err := os.MkdirTemp(t.TempDir(), "ro") + if err != nil { + t.Fatal(err) + } + rwVolName := tID + "-rw" + roVolName := tID + "-ro" + for _, v := range []string{rwVolName, roVolName} { + defer base.Cmd("volume", "rm", "-f", v).Run() + base.Cmd("volume", "create", v).AssertOK() + } + + fromContainerName := tID + "-from" + toContainerName := tID + "-to" + defer base.Cmd("rm", "-f", fromContainerName).AssertOK() + defer base.Cmd("rm", "-f", toContainerName).AssertOK() + base.Cmd("run", + "-d", + "--name", fromContainerName, + "-v", fmt.Sprintf("%s:/mnt1", rwDir), + "-v", fmt.Sprintf("%s:/mnt2:ro", roDir), + "-v", fmt.Sprintf("%s:/mnt3", rwVolName), + "-v", fmt.Sprintf("%s:/mnt4:ro", roVolName), + testutil.AlpineImage, + "top", + ).AssertOK() + base.Cmd("run", + "-d", + "--name", toContainerName, + "--volumes-from", fromContainerName, + testutil.AlpineImage, + "top", + ).AssertOK() + base.Cmd("exec", toContainerName, "sh", "-exc", "echo -n str1 > /mnt1/file1").AssertOK() + base.Cmd("exec", toContainerName, "sh", "-exc", "echo -n str2 > /mnt2/file2").AssertFail() + base.Cmd("exec", toContainerName, "sh", "-exc", "echo -n str3 > /mnt3/file3").AssertOK() + base.Cmd("exec", toContainerName, "sh", "-exc", "echo -n str4 > /mnt4/file4").AssertFail() + base.Cmd("rm", "-f", toContainerName).AssertOK() + base.Cmd("run", + "--rm", + "--volumes-from", fromContainerName, + testutil.AlpineImage, + "cat", "/mnt1/file1", "/mnt3/file3", + ).AssertOutExactly("str1str3") +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 0e9c7c644d8..74484e9bb97 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -267,6 +267,7 @@ Volume flags: Defaults to `1777` or world-writable. - Options specific to `volume`: - unimplemented options: `volume-nocopy`, `volume-label`, `volume-driver`, `volume-opt` +- :whale: `--volumes-from`: Mount volumes from the specified container(s), e.g. "--volumes-from my-container". Rootfs flags: @@ -374,7 +375,7 @@ Unimplemented `docker run` flags: `--attach`, `--blkio-weight-device`, `--cpu-rt-*`, `--device-*`, `--disable-content-trust`, `--domainname`, `--expose`, `--health-*`, `--ip6`, `--isolation`, `--no-healthcheck`, `--link*`, `--mac-address`, `--publish-all`, `--sig-proxy`, `--storage-opt`, - `--userns`, `--volume-driver`, `--volumes-from` + `--userns`, `--volume-driver` ### :whale: :blue_square: nerdctl exec diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index 0df37e3fc64..0e5b5437ae8 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -185,6 +185,8 @@ type ContainerCreateOptions struct { Tmpfs []string // Mount specifies a list of mounts to mount Mount []string + // VolumesFrom specifies a list of specified containers to mount from + VolumesFrom []string // #endregion // #region for rootfs flags diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 558b798ac4b..2038f291f7a 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -613,6 +613,23 @@ func dockercompatMounts(mountPoints []*mountutil.Processed) []dockercompat.Mount return result } +func processeds(mountPoints []dockercompat.MountPoint) []*mountutil.Processed { + result := make([]*mountutil.Processed, len(mountPoints)) + for i := range mountPoints { + mp := mountPoints[i] + result[i] = &mountutil.Processed{ + Type: mp.Type, + Name: mp.Name, + Mount: specs.Mount{ + Source: mp.Source, + Destination: mp.Destination, + }, + Mode: mp.Mode, + } + } + return result +} + func propagateContainerdLabelsToOCIAnnotations() oci.SpecOpts { return func(ctx context.Context, oc oci.Client, c *containers.Container, s *oci.Spec) error { return oci.WithAnnotations(c.Labels)(ctx, oc, c, s) diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index 259edbd7bc9..f8a8eb5e03a 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -166,47 +166,6 @@ func getContainerName(containerLabels map[string]string) string { return "" } -type containerVolume struct { - Type string - Name string - Source string - Destination string - Mode string - RW bool - Propagation string -} - -func getContainerVolumes(containerLabels map[string]string) []*containerVolume { - var vols []*containerVolume - volLabels := []string{labels.AnonymousVolumes, labels.Mounts} - for _, volLabel := range volLabels { - names, ok := containerLabels[volLabel] - if !ok { - continue - } - var ( - volumes []*containerVolume - err error - ) - if volLabel == labels.Mounts { - err = json.Unmarshal([]byte(names), &volumes) - } - if volLabel == labels.AnonymousVolumes { - var anonymous []string - err = json.Unmarshal([]byte(names), &anonymous) - for _, anony := range anonymous { - volumes = append(volumes, &containerVolume{Name: anony}) - } - - } - if err != nil { - logrus.Warn(err) - } - vols = append(vols, volumes...) - } - return vols -} - func getContainerNetworks(containerLables map[string]string) []string { var networks []string if names, ok := containerLables[labels.Networks]; ok { diff --git a/pkg/cmd/container/list_util.go b/pkg/cmd/container/list_util.go index a2041e0a71c..abe482b71c7 100644 --- a/pkg/cmd/container/list_util.go +++ b/pkg/cmd/container/list_util.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" + "github.com/containerd/nerdctl/pkg/containerutil" "github.com/sirupsen/logrus" ) @@ -44,7 +45,7 @@ type containerFilterContext struct { sinceFilterFuncs []func(t time.Time) bool statusFilterFuncs []func(containerd.ProcessStatus) bool labelFilterFuncs []func(map[string]string) bool - volumeFilterFuncs []func([]*containerVolume) bool + volumeFilterFuncs []func([]*containerutil.ContainerVolume) bool networkFilterFuncs []func([]string) bool } @@ -187,7 +188,7 @@ func (cl *containerFilterContext) foldLabelFilter(_ context.Context, filter, val } func (cl *containerFilterContext) foldVolumeFilter(_ context.Context, filter, value string) error { - cl.volumeFilterFuncs = append(cl.volumeFilterFuncs, func(vols []*containerVolume) bool { + cl.volumeFilterFuncs = append(cl.volumeFilterFuncs, func(vols []*containerutil.ContainerVolume) bool { for _, vol := range vols { if (vol.Source != "" && vol.Source == value) || (vol.Destination != "" && vol.Destination == value) || @@ -337,7 +338,7 @@ func (cl *containerFilterContext) matchesVolumeFilter(info containers.Container) if len(cl.volumeFilterFuncs) == 0 { return true } - vols := getContainerVolumes(info.Labels) + vols := containerutil.GetContainerVolumes(info.Labels) for _, volumeFilterFunc := range cl.volumeFilterFuncs { if !volumeFilterFunc(vols) { continue diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index 9bfd6540399..3051818c9a5 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -18,6 +18,7 @@ package container import ( "context" + "encoding/json" "fmt" "os" "path/filepath" @@ -36,6 +37,8 @@ import ( "github.com/containerd/nerdctl/pkg/cmd/volume" "github.com/containerd/nerdctl/pkg/idgen" "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/mountutil" "github.com/containerd/nerdctl/pkg/mountutil/volumestore" "github.com/containerd/nerdctl/pkg/strutil" @@ -292,6 +295,52 @@ func generateMountOpts(ctx context.Context, client *containerd.Client, ensuredIm } opts = append(opts, withMounts(userMounts)) + + containers, err := client.Containers(ctx) + if err != nil { + return nil, nil, nil, err + } + + vfSet := strutil.SliceToSet(options.VolumesFrom) + var vfMountPoints []dockercompat.MountPoint + var vfAnonVolumes []string + + for _, c := range containers { + ls, err := c.Labels(ctx) + if err != nil { + return nil, nil, nil, err + } + _, idMatch := vfSet[c.ID()] + nameMatch := false + if name, found := ls[labels.Name]; found { + _, nameMatch = vfSet[name] + } + + if idMatch || nameMatch { + if av, found := ls[labels.AnonymousVolumes]; found { + err = json.Unmarshal([]byte(av), &vfAnonVolumes) + if err != nil { + return nil, nil, nil, err + } + } + if m, found := ls[labels.Mounts]; found { + err = json.Unmarshal([]byte(m), &vfMountPoints) + if err != nil { + return nil, nil, nil, err + } + } + + ps := processeds(vfMountPoints) + s, err := c.Spec(ctx) + if err != nil { + return nil, nil, nil, err + } + opts = append(opts, withMounts(s.Mounts)) + anonVolumes = append(anonVolumes, vfAnonVolumes...) + mountPoints = append(mountPoints, ps...) + } + } + return opts, anonVolumes, mountPoints, nil } diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 2e695f02bfd..425223fb9df 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -18,6 +18,7 @@ package containerutil import ( "context" + "encoding/json" "errors" "fmt" "io" @@ -498,3 +499,51 @@ func ContainerStateDirPath(ns, dataStore, id string) (string, error) { } return filepath.Join(dataStore, "containers", ns, id), nil } + +// ContainerVolume is a struct representing a volume in a container. +type ContainerVolume struct { + Type string + Name string + Source string + Destination string + Mode string + RW bool + Propagation string +} + +// GetContainerVolumes is a function that returns a slice of containerVolume pointers. +// It accepts a map of container labels as input, where key is the label name and value is its associated value. +// The function iterates over the predefined volume labels (AnonymousVolumes and Mounts) +// and for each, it checks if the labels exists in the provided container labels. +// If yes, it decodes the label value from JSON format and appends the volumes to the result. +// In case of error during decoding, it logs the error and continues to the next label. +func GetContainerVolumes(containerLabels map[string]string) []*ContainerVolume { + var vols []*ContainerVolume + volLabels := []string{labels.AnonymousVolumes, labels.Mounts} + for _, volLabel := range volLabels { + names, ok := containerLabels[volLabel] + if !ok { + continue + } + var ( + volumes []*ContainerVolume + err error + ) + if volLabel == labels.Mounts { + err = json.Unmarshal([]byte(names), &volumes) + } + if volLabel == labels.AnonymousVolumes { + var anonymous []string + err = json.Unmarshal([]byte(names), &anonymous) + for _, anony := range anonymous { + volumes = append(volumes, &ContainerVolume{Name: anony}) + } + + } + if err != nil { + logrus.Warn(err) + } + vols = append(vols, volumes...) + } + return vols +} diff --git a/pkg/strutil/strutil.go b/pkg/strutil/strutil.go index c47aaa9bceb..233853a8068 100644 --- a/pkg/strutil/strutil.go +++ b/pkg/strutil/strutil.go @@ -81,6 +81,19 @@ func DedupeStrSlice(in []string) []string { return res } +// SliceToSet converts a slice of strings into a set. +// In Go, a set is often represented as a map with keys as the set elements and values as boolean. +// This function iterates over the slice, adding each string as a key in the map. +// The corresponding map value is set to true, serving as a placeholder. +// The resulting map can be used to quickly check the presence of an element in the set. +func SliceToSet(in []string) map[string]bool { + set := make(map[string]bool) + for _, s := range in { + set[s] = true + } + return set +} + // ParseCSVMap parses a string like "foo=x,bar=y" into a map func ParseCSVMap(s string) (map[string]string, error) { csvR := csv.NewReader(strings.NewReader(s)) diff --git a/pkg/strutil/strutil_test.go b/pkg/strutil/strutil_test.go index 9bcae5624a1..4be59519962 100644 --- a/pkg/strutil/strutil_test.go +++ b/pkg/strutil/strutil_test.go @@ -34,6 +34,17 @@ func TestDedupeStrSlice(t *testing.T) { } +func TestSliceToSet(t *testing.T) { + assert.DeepEqual(t, + map[string]bool{"apple": true, "banana": true, "chocolate": true}, + SliceToSet([]string{"apple", "banana", "apple", "chocolate"})) + + assert.DeepEqual(t, + map[string]bool{"apple": true, "banana": true, "chocolate": true}, + SliceToSet([]string{"apple", "apple", "banana", "chocolate", "apple"})) + +} + func TestTrimStrSliceRight(t *testing.T) { assert.DeepEqual(t, []string{"foo", "bar", "baz"}, From ded47f35b86b98060ab0c7f93d43cc819971da70 Mon Sep 17 00:00:00 2001 From: York Yao Date: Fri, 30 Jun 2023 11:45:31 -0700 Subject: [PATCH 0010/1066] Remove warning msg when inspect containers without task Signed-off-by: York Yao --- pkg/containerinspector/containerinspector.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/containerinspector/containerinspector.go b/pkg/containerinspector/containerinspector.go index 8f00eb5bf85..8d760c77ebd 100644 --- a/pkg/containerinspector/containerinspector.go +++ b/pkg/containerinspector/containerinspector.go @@ -20,6 +20,7 @@ import ( "context" "github.com/containerd/containerd" + "github.com/containerd/containerd/errdefs" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/containerd/typeurl/v2" "github.com/sirupsen/logrus" @@ -42,7 +43,9 @@ func Inspect(ctx context.Context, container containerd.Container) (*native.Conta } task, err := container.Task(ctx, nil) if err != nil { - logrus.WithError(err).WithField("id", id).Warnf("failed to inspect Task") + if !errdefs.IsNotFound(err) { + logrus.WithError(err).WithField("id", id).Warnf("failed to inspect Task") + } return n, nil } n.Process = &native.Process{ From 7a3b64dd76a7a70a7ff5fea27b144a44c3e354ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 22:30:07 +0000 Subject: [PATCH 0011/1066] build(deps): bump gotest.tools/v3 from 3.4.0 to 3.5.0 Bumps [gotest.tools/v3](https://github.com/gotestyourself/gotest.tools) from 3.4.0 to 3.5.0. - [Release notes](https://github.com/gotestyourself/gotest.tools/releases) - [Commits](https://github.com/gotestyourself/gotest.tools/compare/v3.4.0...v3.5.0) --- updated-dependencies: - dependency-name: gotest.tools/v3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d60ef5298a6..915c77812fc 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,7 @@ require ( golang.org/x/term v0.9.0 golang.org/x/text v0.10.0 gopkg.in/yaml.v3 v3.0.1 - gotest.tools/v3 v3.4.0 + gotest.tools/v3 v3.5.0 ) require ( diff --git a/go.sum b/go.sum index ab359bd0538..3170d5fdc34 100644 --- a/go.sum +++ b/go.sum @@ -1583,8 +1583,8 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= -gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= +gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 7f275a6f4bffcef1c2a83eb94510c886b9731344 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Jun 2023 22:30:12 +0000 Subject: [PATCH 0012/1066] build(deps): bump github.com/opencontainers/image-spec Bumps [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec) from 1.1.0-rc3 to 1.1.0-rc4. - [Release notes](https://github.com/opencontainers/image-spec/releases) - [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md) - [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0-rc3...v1.1.0-rc4) --- updated-dependencies: - dependency-name: github.com/opencontainers/image-spec dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d60ef5298a6..9824e2b6ad0 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/moby/sys/signal v0.7.0 github.com/moby/term v0.5.0 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.1.0-rc3 + github.com/opencontainers/image-spec v1.1.0-rc4 github.com/opencontainers/runtime-spec v1.1.0-rc.3 github.com/pelletier/go-toml v1.9.5 github.com/rootless-containers/bypass4netns v0.3.0 diff --git a/go.sum b/go.sum index ab359bd0538..8d41203accf 100644 --- a/go.sum +++ b/go.sum @@ -798,8 +798,8 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= -github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= +github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= From 0e72a0155da5dc47dfc150a795ae2b406e95d471 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 4 Jul 2023 07:24:45 +0000 Subject: [PATCH 0013/1066] update-compose Signed-off-by: Kay Yan --- go.mod | 4 ++-- go.sum | 10 +++++----- pkg/composer/serviceparser/build_test.go | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 773017b81c8..46cb3cbbc08 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.10.0-rc.8 - github.com/compose-spec/compose-go v1.14.0 + github.com/compose-spec/compose-go v1.15.1 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 @@ -85,7 +85,7 @@ require ( github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/imdario/mergo v0.3.15 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.16.6 github.com/klauspost/cpuid/v2 v2.1.1 // indirect diff --git a/go.sum b/go.sum index 2535a045c8a..e7ed4bdc938 100644 --- a/go.sum +++ b/go.sum @@ -170,8 +170,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/compose-spec/compose-go v1.14.0 h1:/+tQxBEPIrfsi87Qh7/VjMzcJN3BRNER/RO71ku+u6E= -github.com/compose-spec/compose-go v1.14.0/go.mod h1:m0o4G6MQDHjjz9rY7No9FpnNi+9sKic262rzrwuCqic= +github.com/compose-spec/compose-go v1.15.1 h1:0yaEt6/66dLN0bNWYDTj0CDx626uCdQ9ipJVIJx8O8M= +github.com/compose-spec/compose-go v1.15.1/go.mod h1:3yngGBGfls6FHGQsg4B1z6gz8ej9SOvmAJtxCwgbcnc= github.com/containerd/accelerated-container-image v0.6.7 h1:QDO12lgUubiUq0ogMzcL6CdSxkzFOX7vVaSIXAJ9EaM= github.com/containerd/accelerated-container-image v0.6.7/go.mod h1:a7MYTlNhR4+GGpXD7wuNSgxrwC2wE2rgUfCvef+FQzg= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= @@ -609,8 +609,8 @@ github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= @@ -957,7 +957,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= diff --git a/pkg/composer/serviceparser/build_test.go b/pkg/composer/serviceparser/build_test.go index a789810a0d1..d0411054a94 100644 --- a/pkg/composer/serviceparser/build_test.go +++ b/pkg/composer/serviceparser/build_test.go @@ -85,7 +85,7 @@ secrets: assert.Equal(t, project.RelativePath("barctx"), lastOf(bar.Build.BuildArgs)) assert.Assert(t, in(bar.Build.BuildArgs, "--target=bartgt")) assert.Assert(t, in(bar.Build.BuildArgs, "--label=bar=baz")) - secretPath := project.RelativePath("barctx") + secretPath := project.WorkingDir assert.Assert(t, in(bar.Build.BuildArgs, "--secret=id=tgt_secret,src="+secretPath+"/test_secret1")) assert.Assert(t, in(bar.Build.BuildArgs, "--secret=id=simple_secret,src="+secretPath+"/test_secret2")) assert.Assert(t, in(bar.Build.BuildArgs, "--secret=id=absolute_secret,src=/tmp/absolute_secret")) From 6cb50aa0dd601acd43f2eb3b0d454f74ae08b743 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 22:22:41 +0000 Subject: [PATCH 0014/1066] build(deps): bump golang.org/x/text from 0.10.0 to 0.11.0 Bumps [golang.org/x/text](https://github.com/golang/text) from 0.10.0 to 0.11.0. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.10.0...v0.11.0) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 46cb3cbbc08..543621a7c4d 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( golang.org/x/sync v0.3.0 golang.org/x/sys v0.9.0 golang.org/x/term v0.9.0 - golang.org/x/text v0.10.0 + golang.org/x/text v0.11.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.0 ) diff --git a/go.sum b/go.sum index e7ed4bdc938..f354c0868b9 100644 --- a/go.sum +++ b/go.sum @@ -1334,8 +1334,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From e9303fa95126b2cf994826355afa61fa632861a8 Mon Sep 17 00:00:00 2001 From: Mark Yen Date: Thu, 6 Jul 2023 16:55:04 -0700 Subject: [PATCH 0015/1066] Fix incorrect usage of fmt.Fprintf() In quite a few places, we take the pattern of b := fmt.Printf(..., b.String() + "\n") This means we end up passing arbitrary strings as a printf-style formatting string, leading to issues whenever there is a literal `%` in the output. As in #2209, convert to fmt.Fprintln() as appropriate so that we emit the rendered template as-is. Signed-off-by: Mark Yen --- cmd/nerdctl/container_list.go | 2 +- cmd/nerdctl/image_history.go | 2 +- cmd/nerdctl/version.go | 2 +- pkg/cmd/apparmor/list_linux.go | 2 +- pkg/cmd/image/list.go | 2 +- pkg/cmd/network/list.go | 2 +- pkg/cmd/volume/list.go | 2 +- pkg/formatter/common.go | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container_list.go index 0f7d9460ac1..c227548bf93 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container_list.go @@ -194,7 +194,7 @@ func formatAndPrintContainerInfo(containers []container.ListItem, options Format if err := tmpl.Execute(&b, c); err != nil { return err } - if _, err := fmt.Fprintf(w, b.String()+"\n"); err != nil { + if _, err := fmt.Fprintln(w, b.String()); err != nil { return err } } else if options.Quiet { diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index 2550b19ab66..890573044ef 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -219,7 +219,7 @@ func (x *historyPrinter) printHistory(p historyPrintable) error { if err := x.tmpl.Execute(&b, p); err != nil { return err } - if _, err := fmt.Fprintf(x.w, b.String()+"\n"); err != nil { + if _, err := fmt.Fprintln(x.w, b.String()); err != nil { return err } } else if x.quiet { diff --git a/cmd/nerdctl/version.go b/cmd/nerdctl/version.go index d74444a2e4b..ac9c4d6097d 100644 --- a/cmd/nerdctl/version.go +++ b/cmd/nerdctl/version.go @@ -72,7 +72,7 @@ func versionAction(cmd *cobra.Command, args []string) error { if err := tmpl.Execute(&b, v); err != nil { return err } - if _, err := fmt.Fprintf(w, b.String()+"\n"); err != nil { + if _, err := fmt.Fprintln(w, b.String()); err != nil { return err } } else { diff --git a/pkg/cmd/apparmor/list_linux.go b/pkg/cmd/apparmor/list_linux.go index c7a03b3798b..ca4b8c7e632 100644 --- a/pkg/cmd/apparmor/list_linux.go +++ b/pkg/cmd/apparmor/list_linux.go @@ -63,7 +63,7 @@ func List(options types.ApparmorListOptions) error { if err := tmpl.Execute(&b, f); err != nil { return err } - if _, err = fmt.Fprintf(w, b.String()+"\n"); err != nil { + if _, err = fmt.Fprintln(w, b.String()); err != nil { return err } } else if quiet { diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 247757b2374..279e7074c4f 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -264,7 +264,7 @@ func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images. if err := x.tmpl.Execute(&b, p); err != nil { return err } - if _, err = fmt.Fprintf(x.w, b.String()+"\n"); err != nil { + if _, err = fmt.Fprintln(x.w, b.String()); err != nil { return err } } else if x.quiet { diff --git a/pkg/cmd/network/list.go b/pkg/cmd/network/list.go index 3e0cfc54030..e7f7f952b13 100644 --- a/pkg/cmd/network/list.go +++ b/pkg/cmd/network/list.go @@ -105,7 +105,7 @@ func List(ctx context.Context, options types.NetworkListOptions) error { if err := tmpl.Execute(&b, p); err != nil { return err } - if _, err = fmt.Fprintf(w, b.String()+"\n"); err != nil { + if _, err = fmt.Fprintln(w, b.String()); err != nil { return err } } else if quiet { diff --git a/pkg/cmd/volume/list.go b/pkg/cmd/volume/list.go index a026af5642c..9de1a62efcd 100644 --- a/pkg/cmd/volume/list.go +++ b/pkg/cmd/volume/list.go @@ -134,7 +134,7 @@ func lsPrintOutput(vols map[string]native.Volume, options types.VolumeListOption if err := tmpl.Execute(&b, p); err != nil { return err } - if _, err := fmt.Fprintf(w, b.String()+"\n"); err != nil { + if _, err := fmt.Fprintln(w, b.String()); err != nil { return err } } else if options.Quiet { diff --git a/pkg/formatter/common.go b/pkg/formatter/common.go index 8915f0dc3ec..60d550dc44e 100644 --- a/pkg/formatter/common.go +++ b/pkg/formatter/common.go @@ -65,7 +65,7 @@ func FormatSlice(format string, writer io.Writer, x []interface{}) error { } } } - if _, err = fmt.Fprintf(writer, b.String()+"\n"); err != nil { + if _, err = fmt.Fprintln(writer, b.String()); err != nil { return err } } From 1c221fb410e6d1c47abe02d1f87e5ad4575cc54e Mon Sep 17 00:00:00 2001 From: Scott Buckfelder Date: Fri, 7 Jul 2023 13:13:25 +0000 Subject: [PATCH 0016/1066] Add metadata to volume create return Signed-off-by: Scott Buckfelder --- cmd/nerdctl/volume_create.go | 4 +++- pkg/cmd/volume/create.go | 14 ++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume_create.go index 5122e60d465..31cfa6a4214 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume_create.go @@ -57,5 +57,7 @@ func volumeCreateAction(cmd *cobra.Command, args []string) error { if err != nil { return nil } - return volume.Create(args[0], options) + _, err = volume.Create(args[0], options) + + return err } diff --git a/pkg/cmd/volume/create.go b/pkg/cmd/volume/create.go index 791ac514b81..38610d55415 100644 --- a/pkg/cmd/volume/create.go +++ b/pkg/cmd/volume/create.go @@ -21,21 +21,23 @@ import ( "github.com/containerd/containerd/identifiers" "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/containerd/nerdctl/pkg/strutil" ) -func Create(name string, options types.VolumeCreateOptions) error { +func Create(name string, options types.VolumeCreateOptions) (*native.Volume, error) { if err := identifiers.Validate(name); err != nil { - return fmt.Errorf("malformed name %s: %w", name, err) + return nil, fmt.Errorf("malformed name %s: %w", name, err) } volStore, err := Store(options.GOptions.Namespace, options.GOptions.DataRoot, options.GOptions.Address) if err != nil { - return err + return nil, err } labels := strutil.DedupeStrSlice(options.Labels) - if _, err := volStore.Create(name, labels); err != nil { - return err + vol, err := volStore.Create(name, labels) + if err != nil { + return nil, err } fmt.Fprintf(options.Stdout, "%s\n", name) - return nil + return vol, nil } From b993ba0bc003e78f37c0a7da9079cc5f831356c9 Mon Sep 17 00:00:00 2001 From: Kohei Tokunaga Date: Tue, 11 Jul 2023 10:44:28 +0900 Subject: [PATCH 0017/1066] linter: Disable linters and rules not used in containerd Signed-off-by: Kohei Tokunaga --- .golangci.yml | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 0d2fec29133..602ab5c216b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,13 +5,13 @@ run: linters: disable-all: true enable: - - depguard + # - depguard - gofmt - goimports - govet - ineffassign - misspell - - nakedret + # - nakedret - prealloc - typecheck # - asciicheck @@ -134,3 +134,24 @@ linters-settings: - typeUnparen - unnamedResult - unnecessaryBlock + +issues: + exclude-rules: + - linters: + - revive + text: "if-return" + - linters: + - revive + text: "empty-block" + - linters: + - revive + text: "superfluous-else" + - linters: + - revive + text: "unused-parameter" + - linters: + - revive + text: "unreachable-code" + - linters: + - revive + text: "redefines-builtin-id" From af99ea0719d23acc9546f493265cd362056b836f Mon Sep 17 00:00:00 2001 From: Kohei Tokunaga Date: Tue, 11 Jul 2023 10:44:57 +0900 Subject: [PATCH 0018/1066] linter: golangci-lint v1.53.3 Signed-off-by: Kohei Tokunaga --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2e8bc1c9a6d..43d9e7f9138 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,7 +48,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v3.6.0 with: - version: v1.51.1 + version: v1.53.3 args: --verbose - name: yamllint-lint run: yamllint . From 803c8594591540d4dd07644c8493673a6790fe9a Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 11 Jul 2023 06:56:32 +0000 Subject: [PATCH 0019/1066] Fix flaky windows test Signed-off-by: Kay Yan --- hack/configure-windows-ci.ps1 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hack/configure-windows-ci.ps1 b/hack/configure-windows-ci.ps1 index 0d6476e0839..f9d58e4e7e9 100644 --- a/hack/configure-windows-ci.ps1 +++ b/hack/configure-windows-ci.ps1 @@ -3,13 +3,18 @@ $ErrorActionPreference = "Stop" #install build dependencies choco install --limitoutput --no-progress -y git golang +#cleanup containerd +echo "Stopping containerd" +Stop-Service containerd +sc.exe delete containerd + #install containerd $version=$env:ctrdVersion echo "Installing containerd $version" curl.exe -L https://github.com/containerd/containerd/releases/download/v$version/containerd-$version-windows-amd64.tar.gz -o containerd-windows-amd64.tar.gz tar.exe xvf containerd-windows-amd64.tar.gz mkdir -force "$Env:ProgramFiles\containerd" -mv ./bin/* "$Env:ProgramFiles\containerd" +cp ./bin/* "$Env:ProgramFiles\containerd" & $Env:ProgramFiles\containerd\containerd.exe config default | Out-File "$Env:ProgramFiles\containerd\config.toml" -Encoding ascii & $Env:ProgramFiles\containerd\containerd.exe --register-service From da3f7efde75e9f3c0d22d7d6b8ecb903b3475dd0 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Thu, 13 Jul 2023 15:18:18 +0000 Subject: [PATCH 0020/1066] Fix minor typo in volume flags docs Signed-off-by: Austin Vazquez --- docs/command-reference.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/command-reference.md b/docs/command-reference.md index 0e9c7c644d8..f2e2c4e6b98 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -251,12 +251,12 @@ Volume flags: consisting of a `=` tuple. e.g., `-- mount type=bind,source=/src,target=/app,bind-propagation=shared`. - :whale: `type`: Current supported mount types are `bind`, `volume`, `tmpfs`. - The defaul type will be set to `volume` if not specified. - i.e., `--mount src=vol-1,dst=/app,readonly` equals `--mount type=volum,src=vol-1,dst=/app,readonly` + The default type will be set to `volume` if not specified. + i.e., `--mount src=vol-1,dst=/app,readonly` equals `--mount type=volume,src=vol-1,dst=/app,readonly` - Common Options: - :whale: `src`, `source`: Mount source spec for bind and volume. Mandatory for bind. - :whale: `dst`, `destination`, `target`: Mount destination spec. - - :whale: `readonly`, `ro`, `rw`, `rro`: Filesystem permissinos. + - :whale: `readonly`, `ro`, `rw`, `rro`: Filesystem permissions. - Options specific to `bind`: - :whale: `bind-propagation`: `shared`, `slave`, `private`, `rshared`, `rslave`, or `rprivate`(default). - :whale: `bind-nonrecursive`: `true` or `false`(default). If set to true, submounts are not recursively bind-mounted. This option is useful for readonly bind mount. From 40193e5dbd0616607d0dde8bd8ffde8b020421c6 Mon Sep 17 00:00:00 2001 From: Gavin Inglis Date: Thu, 13 Jul 2023 11:52:37 -0700 Subject: [PATCH 0021/1066] update buildkit to v0.12.0 New buildkit release https://github.com/moby/buildkit/releases/tag/v0.12.0 Signed-off-by: Gavin Inglis --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.11.6 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.0 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.11.6 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.0 diff --git a/Dockerfile b/Dockerfile index 074d500360a..4bed75f6ac3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.7 ARG CNI_PLUGINS_VERSION=v1.3.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.11.6 +ARG BUILDKIT_VERSION=v0.12.0 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.14.3 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.11.6 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.11.6 deleted file mode 100644 index ca3b6f2f90d..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.11.6 +++ /dev/null @@ -1,2 +0,0 @@ -3f66f5bfbe509aadf1c21a26acfa472fe4c19046aa00a2d59b99733da867cd76 buildkit-v0.11.6.linux-amd64.tar.gz -82b7452ffea166d3ef445597f9dbe3fa57c4d651e51ca7a9a581199116905524 buildkit-v0.11.6.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.0 new file mode 100644 index 00000000000..ee8f1b2bd41 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.0 @@ -0,0 +1,2 @@ +77db8cb0b88d54a5524548de125f83d909e2a1693791642d50d56639a1632ecf buildkit-v0.12.0.linux-amd64.tar.gz +f6d0d49ff366ad2199e3da2e8622dbe02f46707bdb572612507f5a2d3b84d016 buildkit-v0.12.0.linux-arm64.tar.gz From f8a8295838e59794bdda78dedba6220d0a47ec8a Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 6 Jul 2023 09:08:03 +0000 Subject: [PATCH 0022/1066] fix compose lacking support for replicas = 0 Signed-off-by: Kay Yan --- pkg/composer/serviceparser/serviceparser.go | 2 +- pkg/composer/serviceparser/serviceparser_test.go | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index 785fc97b9f8..69d22d45595 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -216,7 +216,7 @@ func getReplicas(svc types.ServiceConfig) (int, error) { replicas = int(*svc.Deploy.Replicas) } - if replicas < 1 { + if replicas < 0 { return 0, fmt.Errorf("invalid replicas: %d", replicas) } return replicas, nil diff --git a/pkg/composer/serviceparser/serviceparser_test.go b/pkg/composer/serviceparser/serviceparser_test.go index 308e7cb76e4..860edf77280 100644 --- a/pkg/composer/serviceparser/serviceparser_test.go +++ b/pkg/composer/serviceparser/serviceparser_test.go @@ -260,6 +260,10 @@ services: devices: - capabilities: ["utility"] count: all + qux: # replicas=0 + image: nginx:alpine + deploy: + replicas: 0 ` comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() @@ -310,6 +314,16 @@ services: assert.Assert(t, in(c.RunArgs, "--restart=no")) assert.Assert(t, in(c.RunArgs, `--gpus=capabilities=utility,count=-1`)) } + + quxSvc, err := project.GetService("qux") + assert.NilError(t, err) + + qux, err := Parse(project, quxSvc) + assert.NilError(t, err) + + t.Logf("qux: %+v", qux) + assert.Assert(t, len(qux.Containers) == 0) + } func TestParseRelative(t *testing.T) { From ebff85548d8fb523f47dcaf4a7bce91be3aca202 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 16 Jul 2023 13:25:42 +0000 Subject: [PATCH 0023/1066] build(deps): bump github.com/compose-spec/compose-go Bumps [github.com/compose-spec/compose-go](https://github.com/compose-spec/compose-go) from 1.15.1 to 1.16.0. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v1.15.1...v1.16.0) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 543621a7c4d..d50807b6aa7 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.10.0-rc.8 - github.com/compose-spec/compose-go v1.15.1 + github.com/compose-spec/compose-go v1.16.0 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 diff --git a/go.sum b/go.sum index f354c0868b9..e1c0fbd4747 100644 --- a/go.sum +++ b/go.sum @@ -170,8 +170,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/compose-spec/compose-go v1.15.1 h1:0yaEt6/66dLN0bNWYDTj0CDx626uCdQ9ipJVIJx8O8M= -github.com/compose-spec/compose-go v1.15.1/go.mod h1:3yngGBGfls6FHGQsg4B1z6gz8ej9SOvmAJtxCwgbcnc= +github.com/compose-spec/compose-go v1.16.0 h1:HYk4uYWXgArHh6NG+WE4yGYayOXw+hjqJ+eJxpjWWjk= +github.com/compose-spec/compose-go v1.16.0/go.mod h1:3yngGBGfls6FHGQsg4B1z6gz8ej9SOvmAJtxCwgbcnc= github.com/containerd/accelerated-container-image v0.6.7 h1:QDO12lgUubiUq0ogMzcL6CdSxkzFOX7vVaSIXAJ9EaM= github.com/containerd/accelerated-container-image v0.6.7/go.mod h1:a7MYTlNhR4+GGpXD7wuNSgxrwC2wE2rgUfCvef+FQzg= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= From 045cdbe24853e63b2c5c566f2e283cddbe93b100 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 16 Jul 2023 15:15:57 +0000 Subject: [PATCH 0024/1066] build(deps): bump golang.org/x/crypto from 0.10.0 to 0.11.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.10.0 to 0.11.0. - [Commits](https://github.com/golang/crypto/compare/v0.10.0...v0.11.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index d50807b6aa7..79234a234c0 100644 --- a/go.mod +++ b/go.mod @@ -51,11 +51,11 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 - golang.org/x/crypto v0.10.0 + golang.org/x/crypto v0.11.0 golang.org/x/net v0.11.0 golang.org/x/sync v0.3.0 - golang.org/x/sys v0.9.0 - golang.org/x/term v0.9.0 + golang.org/x/sys v0.10.0 + golang.org/x/term v0.10.0 golang.org/x/text v0.11.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.0 diff --git a/go.sum b/go.sum index e1c0fbd4747..fbf4c6d5548 100644 --- a/go.sum +++ b/go.sum @@ -1091,8 +1091,8 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1317,14 +1317,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= -golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From c83da81a410ecb6ca7d151caa3de0364b18c0341 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 16 Jul 2023 16:02:29 +0000 Subject: [PATCH 0025/1066] build(deps): bump github.com/klauspost/compress from 1.16.6 to 1.16.7 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.16.6 to 1.16.7. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.16.6...v1.16.7) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 79234a234c0..5e8e1f3b022 100644 --- a/go.mod +++ b/go.mod @@ -87,7 +87,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.16.6 + github.com/klauspost/compress v1.16.7 github.com/klauspost/cpuid/v2 v2.1.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect diff --git a/go.sum b/go.sum index fbf4c6d5548..8eb7d761f5c 100644 --- a/go.sum +++ b/go.sum @@ -642,8 +642,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk= -github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0= From 4710e608e14d6c5b2bfe1f00690b124a92059612 Mon Sep 17 00:00:00 2001 From: York Yao Date: Mon, 17 Jul 2023 09:42:25 -0700 Subject: [PATCH 0026/1066] Fix subnet overlapping Signed-off-by: York Yao --- pkg/netutil/netutil.go | 2 +- pkg/netutil/netutil_unix.go | 5 +++++ pkg/netutil/netutil_windows.go | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 6b0243eaf4d..b30d11e08fd 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -475,7 +475,7 @@ func (e *CNIEnv) parseSubnet(subnetStr string) (*net.IPNet, error) { return nil, err } if subnetStr == "" { - _, defaultSubnet, _ := net.ParseCIDR(DefaultCIDR) + _, defaultSubnet, _ := net.ParseCIDR(StartingCIDR) subnet, err := subnetutil.GetFreeSubnet(defaultSubnet, usedSubnets) if err != nil { return nil, err diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index 2a221ca8bcf..2f69c2cb595 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -40,6 +40,11 @@ const ( DefaultNetworkName = "bridge" DefaultCIDR = "10.4.0.0/24" DefaultIPAMDriver = "host-local" + + // When creating non-default network without passing in `--subnet` option, + // nerdctl assigns subnet address for the creation starting from `StartingCIDR` + // This prevents subnet address overlapping with `DefaultCIDR` used by the default network + StartingCIDR = "10.4.1.0/24" ) func (n *NetworkConfig) subnets() []*net.IPNet { diff --git a/pkg/netutil/netutil_windows.go b/pkg/netutil/netutil_windows.go index 31d28140fc4..f0531152596 100644 --- a/pkg/netutil/netutil_windows.go +++ b/pkg/netutil/netutil_windows.go @@ -27,6 +27,11 @@ import ( const ( DefaultNetworkName = "nat" DefaultCIDR = "10.4.0.0/24" + + // When creating non-default network without passing in `--subnet` option, + // nerdctl assigns subnet address for the creation starting from `StartingCIDR` + // This prevents subnet address overlapping with `DefaultCIDR` used by the default networkß + StartingCIDR = "10.4.1.0/24" ) func (n *NetworkConfig) subnets() []*net.IPNet { From cb47118a5abb5f54b62bc999cc336b20de6a069e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 22:08:22 +0000 Subject: [PATCH 0027/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 24.0.2+incompatible to 24.0.4+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v24.0.2...v24.0.4) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5e8e1f3b022..37a690854b9 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.3 github.com/docker/cli v24.0.2+incompatible - github.com/docker/docker v24.0.2+incompatible + github.com/docker/docker v24.0.4+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.1.3 diff --git a/go.sum b/go.sum index 8eb7d761f5c..5fb5ababe6b 100644 --- a/go.sum +++ b/go.sum @@ -365,8 +365,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v24.0.2+incompatible h1:eATx+oLz9WdNVkQrr0qjQ8HvRJ4bOOxfzEo8R+dA3cg= -github.com/docker/docker v24.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.4+incompatible h1:s/LVDftw9hjblvqIeTiGYXBCD95nOEEl7qRsRrIOuQI= +github.com/docker/docker v24.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= From 441c40e5fef763504a2a579b0a9a9353a89f8b56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 22:08:40 +0000 Subject: [PATCH 0028/1066] build(deps): bump github.com/Microsoft/hcsshim Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.10.0-rc.8 to 0.10.0-rc.9. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.10.0-rc.8...v0.10.0-rc.9) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 10 ++++++---- go.sum | 22 +++++++++++++--------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 5e8e1f3b022..09a015259fd 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 - github.com/Microsoft/hcsshim v0.10.0-rc.8 + github.com/Microsoft/hcsshim v0.10.0-rc.9 github.com/compose-spec/compose-go v1.16.0 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 @@ -61,6 +61,8 @@ require ( gotest.tools/v3 v3.5.0 ) +require github.com/golang/mock v1.6.0 // indirect + require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 // indirect @@ -114,7 +116,7 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/tinylib/msgp v1.1.6 // indirect - github.com/vbatts/tar-split v0.11.2 // indirect + github.com/vbatts/tar-split v0.11.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -122,8 +124,8 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.14.0 // indirect go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/mod v0.9.0 // indirect - golang.org/x/tools v0.7.0 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/tools v0.8.0 // indirect google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect google.golang.org/grpc v1.54.0 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/go.sum b/go.sum index 8eb7d761f5c..0add3dc45f8 100644 --- a/go.sum +++ b/go.sum @@ -64,6 +64,7 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 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= @@ -90,8 +91,8 @@ github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwT github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim v0.10.0-rc.8 h1:YSZVvlIIDD1UxQpJp0h+dnpLUw+TrY0cx8obKsp3bek= -github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim v0.10.0-rc.9 h1:B4mguSolFL2yOHl0JjQxo0Si2Vwipj/Cbib4pyJ4pKA= +github.com/Microsoft/hcsshim v0.10.0-rc.9/go.mod h1:1g6+xpige+npSTrEkdm8JOZxOjJ9McQiT0JkEpzyZqA= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -490,6 +491,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -909,6 +911,7 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -980,9 +983,9 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= -github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= +github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= +github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= +github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= @@ -1128,8 +1131,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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= @@ -1315,6 +1318,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= @@ -1410,8 +1414,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 4b4170e040b54363fe6902de8ca75a0bc8e335a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 22:08:55 +0000 Subject: [PATCH 0029/1066] build(deps): bump golang.org/x/net from 0.11.0 to 0.12.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.11.0 to 0.12.0. - [Commits](https://github.com/golang/net/compare/v0.11.0...v0.12.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5e8e1f3b022..6199fbd8023 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 golang.org/x/crypto v0.11.0 - golang.org/x/net v0.11.0 + golang.org/x/net v0.12.0 golang.org/x/sync v0.3.0 golang.org/x/sys v0.10.0 golang.org/x/term v0.10.0 diff --git a/go.sum b/go.sum index 8eb7d761f5c..24e012d6f67 100644 --- a/go.sum +++ b/go.sum @@ -1186,8 +1186,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= -golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= From 4e87211de22b973d06b0e589abbfb018a46288e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jul 2023 02:58:40 +0000 Subject: [PATCH 0030/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 24.0.2+incompatible to 24.0.4+incompatible. - [Commits](https://github.com/docker/cli/compare/v24.0.2...v24.0.4) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 37a690854b9..d2b9f38dc1d 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/coreos/go-iptables v0.6.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.3 - github.com/docker/cli v24.0.2+incompatible + github.com/docker/cli v24.0.4+incompatible github.com/docker/docker v24.0.4+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 5fb5ababe6b..2f3d17890f3 100644 --- a/go.sum +++ b/go.sum @@ -359,8 +359,8 @@ 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/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v24.0.2+incompatible h1:QdqR7znue1mtkXIJ+ruQMGQhpw2JzMJLRXp6zpzF6tM= -github.com/docker/cli v24.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.4+incompatible h1:Y3bYF9ekNTm2VFz5U/0BlMdJy73D+Y1iAAZ8l63Ydzw= +github.com/docker/cli v24.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= From 6dd6d8a778fa2c8ab561864bdcc4f318e4c1367b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jul 2023 22:27:11 +0000 Subject: [PATCH 0031/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.9.0 to 0.9.1. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.9.0...v0.9.1) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c4491f9db2f..e7bdc835302 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/containerd/continuity v0.4.1 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.7 - github.com/containerd/nydus-snapshotter v0.9.0 + github.com/containerd/nydus-snapshotter v0.9.1 github.com/containerd/stargz-snapshotter v0.14.3 github.com/containerd/stargz-snapshotter/estargz v0.14.3 github.com/containerd/stargz-snapshotter/ipfs v0.14.3 diff --git a/go.sum b/go.sum index 04e480b902c..713f108813d 100644 --- a/go.sum +++ b/go.sum @@ -262,8 +262,8 @@ github.com/containerd/imgcrypt v1.1.7/go.mod h1:FD8gqIcX5aTotCtOmjeCsi3A1dHmTZpn github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nydus-snapshotter v0.9.0 h1:f0Tr3srVKDlURgLG/Kocy4WQIYsmSoc8ihHxdzfB2S0= -github.com/containerd/nydus-snapshotter v0.9.0/go.mod h1:xEsAzeM0gZEW6POBPOa+1X7EThYsEJNWnO/fhf2moYU= +github.com/containerd/nydus-snapshotter v0.9.1 h1:HAjv+ndu1eLvu8P8Vrm6HLlL5a/Izdhm/evxb6DdzFg= +github.com/containerd/nydus-snapshotter v0.9.1/go.mod h1:xEsAzeM0gZEW6POBPOa+1X7EThYsEJNWnO/fhf2moYU= github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= github.com/containerd/stargz-snapshotter v0.14.3/go.mod h1:j2Ya4JeA5gMZJr8BchSkPjlcCEh++auAxp4nidPI6N0= github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= From b57fcb68d56328d421dbbe5e9fb5a586350d109f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jul 2023 22:27:22 +0000 Subject: [PATCH 0032/1066] build(deps): bump github.com/compose-spec/compose-go Bumps [github.com/compose-spec/compose-go](https://github.com/compose-spec/compose-go) from 1.16.0 to 1.17.0. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v1.16.0...v1.17.0) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 9 ++++++--- go.sum | 10 ++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index c4491f9db2f..09e35a257c9 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.10.0-rc.9 - github.com/compose-spec/compose-go v1.16.0 + github.com/compose-spec/compose-go v1.17.0 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 @@ -61,7 +61,10 @@ require ( gotest.tools/v3 v3.5.0 ) -require github.com/golang/mock v1.6.0 // indirect +require ( + github.com/golang/mock v1.6.0 // indirect + golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect +) require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect @@ -124,7 +127,7 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.14.0 // indirect go.opentelemetry.io/otel/trace v1.14.0 // indirect - golang.org/x/mod v0.10.0 // indirect + golang.org/x/mod v0.11.0 // indirect golang.org/x/tools v0.8.0 // indirect google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect google.golang.org/grpc v1.54.0 // indirect diff --git a/go.sum b/go.sum index 04e480b902c..76a91a9b95e 100644 --- a/go.sum +++ b/go.sum @@ -171,8 +171,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/compose-spec/compose-go v1.16.0 h1:HYk4uYWXgArHh6NG+WE4yGYayOXw+hjqJ+eJxpjWWjk= -github.com/compose-spec/compose-go v1.16.0/go.mod h1:3yngGBGfls6FHGQsg4B1z6gz8ej9SOvmAJtxCwgbcnc= +github.com/compose-spec/compose-go v1.17.0 h1:cvje90CU94dQyTnJoHJYjx9yE4Iggse1XmGcO3Qi5ts= +github.com/compose-spec/compose-go v1.17.0/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= github.com/containerd/accelerated-container-image v0.6.7 h1:QDO12lgUubiUq0ogMzcL6CdSxkzFOX7vVaSIXAJ9EaM= github.com/containerd/accelerated-container-image v0.6.7/go.mod h1:a7MYTlNhR4+GGpXD7wuNSgxrwC2wE2rgUfCvef+FQzg= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= @@ -1106,6 +1106,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1131,8 +1133,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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= From 3bb8fb9d3b68309665219637dcaff58c1088f0e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Jul 2023 22:41:21 +0000 Subject: [PATCH 0033/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.9.1 to 0.10.0. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.9.1...v0.10.0) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e937b5436c6..c2dea8171be 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/containerd/continuity v0.4.1 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.7 - github.com/containerd/nydus-snapshotter v0.9.1 + github.com/containerd/nydus-snapshotter v0.10.0 github.com/containerd/stargz-snapshotter v0.14.3 github.com/containerd/stargz-snapshotter/estargz v0.14.3 github.com/containerd/stargz-snapshotter/ipfs v0.14.3 diff --git a/go.sum b/go.sum index ef940c7cf45..03f55ce3416 100644 --- a/go.sum +++ b/go.sum @@ -262,8 +262,8 @@ github.com/containerd/imgcrypt v1.1.7/go.mod h1:FD8gqIcX5aTotCtOmjeCsi3A1dHmTZpn github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nydus-snapshotter v0.9.1 h1:HAjv+ndu1eLvu8P8Vrm6HLlL5a/Izdhm/evxb6DdzFg= -github.com/containerd/nydus-snapshotter v0.9.1/go.mod h1:xEsAzeM0gZEW6POBPOa+1X7EThYsEJNWnO/fhf2moYU= +github.com/containerd/nydus-snapshotter v0.10.0 h1:aCQoKmksOmZ2C34znlhOCOlYExiw4s/UPPzbIFKQc8U= +github.com/containerd/nydus-snapshotter v0.10.0/go.mod h1:xEsAzeM0gZEW6POBPOa+1X7EThYsEJNWnO/fhf2moYU= github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= github.com/containerd/stargz-snapshotter v0.14.3/go.mod h1:j2Ya4JeA5gMZJr8BchSkPjlcCEh++auAxp4nidPI6N0= github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= From 0d0cbb8be0d74853b71364ca19a50f6bb3e90579 Mon Sep 17 00:00:00 2001 From: Vishwas Siravara Date: Thu, 20 Jul 2023 19:11:24 -0700 Subject: [PATCH 0034/1066] Add functionality to copy files into and out of stopped containers. Signed-off-by: Vishwas Siravara --- cmd/nerdctl/container_cp_linux.go | 51 ++++------ cmd/nerdctl/container_cp_linux_test.go | 131 ++++++++++++++++++++++--- pkg/api/types/container_types.go | 6 +- pkg/cmd/container/cp_linux.go | 36 +++++-- pkg/containerutil/cp_linux.go | 84 ++++++++++++++-- pkg/rootlessutil/rootlessutil_linux.go | 13 +++ 6 files changed, 260 insertions(+), 61 deletions(-) diff --git a/cmd/nerdctl/container_cp_linux.go b/cmd/nerdctl/container_cp_linux.go index dc412ad3257..f3f994794b5 100644 --- a/cmd/nerdctl/container_cp_linux.go +++ b/cmd/nerdctl/container_cp_linux.go @@ -17,20 +17,16 @@ package main import ( - "encoding/json" "fmt" - "os" - "os/exec" - "github.com/containerd/containerd" "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/spf13/cobra" ) func newCpCommand() *cobra.Command { - shortHelp := "Copy files/folders between a running container and the local filesystem." longHelp := shortHelp + ` @@ -65,11 +61,26 @@ func cpAction(cmd *cobra.Command, args []string) error { if err != nil { return err } + if rootlessutil.IsRootless() { + options.GOptions.Address, err = rootlessutil.RootlessContainredSockAddress() + if err != nil { + return err + } + } + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), options.GOptions.Namespace, options.GOptions.Address) + if err != nil { + return err + } + defer cancel() - return container.Cp(cmd.Context(), options) + return container.Cp(ctx, client, options) } func processCpOptions(cmd *cobra.Command, args []string) (types.ContainerCpOptions, error) { + globalOptions, err := processRootCmdFlags(cmd) + if err != nil { + return types.ContainerCpOptions{}, err + } flagL, err := cmd.Flags().GetBool("follow-link") if err != nil { return types.ContainerCpOptions{}, err @@ -105,32 +116,10 @@ func processCpOptions(cmd *cobra.Command, args []string) (types.ContainerCpOptio } else { container = *destSpec.Container } - ctx := cmd.Context() - - // cp works in the host namespace (for inspecting file permissions), so we can't directly use the Go client. - - selfExe, inspectArgs := globalFlags(cmd) - inspectArgs = append(inspectArgs, "container", "inspect", "--mode=native", "--format={{json .Process}}", container) - inspectCmd := exec.CommandContext(ctx, selfExe, inspectArgs...) - inspectCmd.Stderr = os.Stderr - inspectOut, err := inspectCmd.Output() - if err != nil { - return types.ContainerCpOptions{}, fmt.Errorf("failed to execute %v: %w", inspectCmd.Args, err) - } - var proc native.Process - if err := json.Unmarshal(inspectOut, &proc); err != nil { - return types.ContainerCpOptions{}, err - } - if proc.Status.Status != containerd.Running { - return types.ContainerCpOptions{}, fmt.Errorf("expected container status %v, got %v", containerd.Running, proc.Status.Status) - } - if proc.Pid <= 0 { - return types.ContainerCpOptions{}, fmt.Errorf("got non-positive PID %v", proc.Pid) - } - return types.ContainerCpOptions{ + GOptions: globalOptions, Container2Host: container2host, - Pid: proc.Pid, + ContainerReq: container, DestPath: destSpec.Path, SrcPath: srcSpec.Path, FollowSymLink: flagL, diff --git a/cmd/nerdctl/container_cp_linux_test.go b/cmd/nerdctl/container_cp_linux_test.go index 5442ed53b30..c78a0a0519a 100644 --- a/cmd/nerdctl/container_cp_linux_test.go +++ b/cmd/nerdctl/container_cp_linux_test.go @@ -24,6 +24,7 @@ import ( "syscall" "testing" + "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" ) @@ -32,18 +33,27 @@ func TestCopyToContainer(t *testing.T) { t.Parallel() base := testutil.NewBase(t) testContainer := testutil.Identifier(t) + testStoppedContainer := "stopped-container-" + testutil.Identifier(t) base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", "1h").AssertOK() defer base.Cmd("rm", "-f", testContainer).Run() + base.Cmd("run", "-d", "--name", testStoppedContainer, testutil.CommonImage, "sleep", "1h").AssertOK() + defer base.Cmd("rm", "-f", testStoppedContainer).Run() + // Stop container immediately after starting for testing copying into stopped container + base.Cmd("stop", testStoppedContainer).AssertOK() srcUID := os.Geteuid() srcDir := t.TempDir() srcFile := filepath.Join(srcDir, "test-file") srcFileContent := []byte("test-file-content") - err := os.WriteFile(srcFile, srcFileContent, 0644) + err := os.WriteFile(srcFile, srcFileContent, 0o644) assert.NilError(t, err) - assertCat := func(catPath string) { + assertCat := func(catPath string, testContainer string, stopped bool) { + if stopped { + base.Cmd("start", testStoppedContainer).AssertOK() + defer base.Cmd("stop", testStoppedContainer).AssertOK() + } t.Logf("catPath=%q", catPath) base.Cmd("exec", testContainer, "cat", catPath).AssertOutExactly(string(srcFileContent)) base.Cmd("exec", testContainer, "stat", "-c", "%u", catPath).AssertOutExactly(fmt.Sprintf("%d\n", srcUID)) @@ -56,25 +66,47 @@ func TestCopyToContainer(t *testing.T) { destPath := "/dest-no-exist-no-slash" base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() catPath := destPath - assertCat(catPath) + assertCat(catPath, testContainer, false) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() + assertCat(catPath, testStoppedContainer, true) }) t.Run("DEST_PATH does not exist and ends with /", func(t *testing.T) { destPath := "/dest-no-exist-with-slash/" base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertFail() + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertFail() }) t.Run("DEST_PATH exists and is a file", func(t *testing.T) { destPath := "/dest-file-exists" base.Cmd("exec", testContainer, "touch", destPath).AssertOK() base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() catPath := destPath - assertCat(catPath) + assertCat(catPath, testContainer, false) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() + assertCat(catPath, testStoppedContainer, true) }) t.Run("DEST_PATH exists and is a directory", func(t *testing.T) { destPath := "/dest-dir-exists" base.Cmd("exec", testContainer, "mkdir", "-p", destPath).AssertOK() base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() catPath := filepath.Join(destPath, filepath.Base(srcFile)) - assertCat(catPath) + assertCat(catPath, testContainer, false) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("start", testStoppedContainer).AssertOK() + base.Cmd("exec", testStoppedContainer, "mkdir", "-p", destPath).AssertOK() + base.Cmd("stop", testStoppedContainer).AssertOK() + base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() + assertCat(catPath, testStoppedContainer, true) }) }) t.Run("SRC_PATH specifies a directory", func(t *testing.T) { @@ -83,12 +115,24 @@ func TestCopyToContainer(t *testing.T) { destPath := "/dest2-no-exist" base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() catPath := filepath.Join(destPath, filepath.Base(srcFile)) - assertCat(catPath) + assertCat(catPath, testContainer, false) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() + assertCat(catPath, testStoppedContainer, true) }) t.Run("DEST_PATH exists and is a file", func(t *testing.T) { destPath := "/dest2-file-exists" base.Cmd("exec", testContainer, "touch", destPath).AssertOK() base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertFail() + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("start", testStoppedContainer).AssertOK() + base.Cmd("exec", testStoppedContainer, "touch", destPath).AssertOK() + base.Cmd("stop", testStoppedContainer).AssertOK() + base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertFail() }) t.Run("DEST_PATH exists and is a directory", func(t *testing.T) { t.Run("SRC_PATH does not end with `/.`", func(t *testing.T) { @@ -96,7 +140,15 @@ func TestCopyToContainer(t *testing.T) { base.Cmd("exec", testContainer, "mkdir", "-p", destPath).AssertOK() base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() catPath := filepath.Join(destPath, strings.TrimPrefix(srcFile, filepath.Dir(srcDir)+"/")) - assertCat(catPath) + assertCat(catPath, testContainer, false) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("start", testStoppedContainer).AssertOK() + base.Cmd("exec", testStoppedContainer, "mkdir", "-p", destPath).AssertOK() + base.Cmd("stop", testStoppedContainer).AssertOK() + base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() + assertCat(catPath, testStoppedContainer, true) }) t.Run("SRC_PATH does end with `/.`", func(t *testing.T) { srcPath += "/." @@ -105,7 +157,15 @@ func TestCopyToContainer(t *testing.T) { base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() catPath := filepath.Join(destPath, filepath.Base(srcFile)) t.Logf("catPath=%q", catPath) - assertCat(catPath) + assertCat(catPath, testContainer, false) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("start", testStoppedContainer).AssertOK() + base.Cmd("exec", testStoppedContainer, "mkdir", "-p", destPath).AssertOK() + base.Cmd("stop", testStoppedContainer).AssertOK() + base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() + assertCat(catPath, testStoppedContainer, true) }) }) }) @@ -115,10 +175,14 @@ func TestCopyFromContainer(t *testing.T) { t.Parallel() base := testutil.NewBase(t) testContainer := testutil.Identifier(t) + testStoppedContainer := "stopped-container-" + testutil.Identifier(t) base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", "1h").AssertOK() defer base.Cmd("rm", "-f", testContainer).Run() + base.Cmd("run", "-d", "--name", testStoppedContainer, testutil.CommonImage, "sleep", "1h").AssertOK() + defer base.Cmd("rm", "-f", testStoppedContainer).Run() + euid := os.Geteuid() srcUID := 42 srcDir := "/test-dir" @@ -126,6 +190,9 @@ func TestCopyFromContainer(t *testing.T) { srcFileContent := []byte("test-file-content") mkSrcScript := fmt.Sprintf("mkdir -p %q && echo -n %q >%q && chown %d %q", srcDir, srcFileContent, srcFile, srcUID, srcFile) base.Cmd("exec", testContainer, "sh", "-euc", mkSrcScript).AssertOK() + base.Cmd("exec", testStoppedContainer, "sh", "-euc", mkSrcScript).AssertOK() + // Stop container for testing copying out of stopped container + base.Cmd("stop", testStoppedContainer) assertCat := func(catPath string) { t.Logf("catPath=%q", catPath) @@ -148,26 +215,45 @@ func TestCopyFromContainer(t *testing.T) { base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() catPath := destPath assertCat(catPath) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() + assertCat(catPath) }) t.Run("DEST_PATH does not exist and ends with /", func(t *testing.T) { destPath := td + "/dest-no-exist-with-slash/" // Avoid filepath.Join, to forcibly append "/" base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertFail() + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertFail() }) t.Run("DEST_PATH exists and is a file", func(t *testing.T) { destPath := filepath.Join(td, "dest-file-exists") - err := os.WriteFile(destPath, []byte(""), 0644) + err := os.WriteFile(destPath, []byte(""), 0o644) assert.NilError(t, err) base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() catPath := destPath assertCat(catPath) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() + assertCat(catPath) }) t.Run("DEST_PATH exists and is a directory", func(t *testing.T) { destPath := filepath.Join(td, "dest-dir-exists") - err := os.Mkdir(destPath, 0755) + err := os.Mkdir(destPath, 0o755) assert.NilError(t, err) base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() catPath := filepath.Join(destPath, filepath.Base(srcFile)) assertCat(catPath) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() + assertCat(catPath) }) }) t.Run("SRC_PATH specifies a directory", func(t *testing.T) { @@ -177,30 +263,49 @@ func TestCopyFromContainer(t *testing.T) { base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() catPath := filepath.Join(destPath, filepath.Base(srcFile)) assertCat(catPath) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() + assertCat(catPath) }) t.Run("DEST_PATH exists and is a file", func(t *testing.T) { destPath := filepath.Join(td, "dest2-file-exists") - err := os.WriteFile(destPath, []byte(""), 0644) + err := os.WriteFile(destPath, []byte(""), 0o644) assert.NilError(t, err) base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertFail() + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertFail() }) t.Run("DEST_PATH exists and is a directory", func(t *testing.T) { t.Run("SRC_PATH does not end with `/.`", func(t *testing.T) { destPath := filepath.Join(td, "dest2-dir-exists") - err := os.Mkdir(destPath, 0755) + err := os.Mkdir(destPath, 0o755) assert.NilError(t, err) base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() catPath := filepath.Join(destPath, strings.TrimPrefix(srcFile, filepath.Dir(srcDir)+"/")) assertCat(catPath) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() + assertCat(catPath) }) t.Run("SRC_PATH does end with `/.`", func(t *testing.T) { srcPath += "/." destPath := filepath.Join(td, "dest2-dir2-exists") - err := os.Mkdir(destPath, 0755) + err := os.Mkdir(destPath, 0o755) assert.NilError(t, err) base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() catPath := filepath.Join(destPath, filepath.Base(srcFile)) assertCat(catPath) + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() + assertCat(catPath) }) }) }) diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index 0e5b5437ae8..2cd94b48169 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -410,9 +410,11 @@ type ContainerListOptions struct { // ContainerCpOptions specifies options for `nerdctl (container) cp` type ContainerCpOptions struct { + // GOptions is the global options. + GOptions GlobalCommandOptions + // ContainerReq is name, short ID, or long ID of container to copy to/from. + ContainerReq string Container2Host bool - // Process id - Pid int // Destination path to copy file to. DestPath string // Source path to copy file from. diff --git a/pkg/cmd/container/cp_linux.go b/pkg/cmd/container/cp_linux.go index c1d7dcca8ec..a392aacc8e9 100644 --- a/pkg/cmd/container/cp_linux.go +++ b/pkg/cmd/container/cp_linux.go @@ -18,18 +18,38 @@ package container import ( "context" + "fmt" + "github.com/containerd/containerd" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/containerutil" + "github.com/containerd/nerdctl/pkg/idutil/containerwalker" ) // Cp copies files/folders between a running container and the local filesystem. -func Cp(ctx context.Context, options types.ContainerCpOptions) error { - return containerutil.CopyFiles( - ctx, - options.Container2Host, - options.Pid, - options.DestPath, - options.SrcPath, - options.FollowSymLink) +func Cp(ctx context.Context, client *containerd.Client, options types.ContainerCpOptions) error { + walker := &containerwalker.ContainerWalker{ + Client: client, + OnFound: func(ctx context.Context, found containerwalker.Found) error { + if found.MatchCount > 1 { + return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + } + return containerutil.CopyFiles( + ctx, + client, + found.Container, + options.Container2Host, + options.DestPath, + options.SrcPath, + options.GOptions.Snapshotter, + options.FollowSymLink) + }, + } + count, err := walker.Walk(ctx, options.ContainerReq) + + if count < 1 { + err = fmt.Errorf("could not find container: %s, with error: %w", options.ContainerReq, err) + } + + return err } diff --git a/pkg/containerutil/cp_linux.go b/pkg/containerutil/cp_linux.go index 497ab474197..d0aeed9694c 100644 --- a/pkg/containerutil/cp_linux.go +++ b/pkg/containerutil/cp_linux.go @@ -19,12 +19,16 @@ package containerutil import ( "context" "fmt" + "io/fs" "os" "os/exec" "path/filepath" "strconv" "strings" + "github.com/containerd/containerd" + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/mount" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/tarutil" securejoin "github.com/cyphar/filepath-securejoin" @@ -32,16 +36,51 @@ import ( ) // CopyFiles implements `nerdctl cp`. -// // See https://docs.docker.com/engine/reference/commandline/cp/ for the specification. -func CopyFiles(ctx context.Context, container2host bool, pid int, dst, src string, followSymlink bool) error { +func CopyFiles(ctx context.Context, client *containerd.Client, container containerd.Container, container2host bool, dst, src string, snapshotter string, followSymlink bool) error { tarBinary, isGNUTar, err := tarutil.FindTarBinary() if err != nil { return err } logrus.Debugf("Detected tar binary %q (GNU=%v)", tarBinary, isGNUTar) - var srcFull, dstFull string - root := fmt.Sprintf("/proc/%d/root", pid) + var srcFull, dstFull, root string + var cleanup func() + task, err := container.Task(ctx, nil) + if err != nil { + // if the task is simply not found, we should try to mount the snapshot. any other type of error from Task() is fatal here. + // Rootless does not support copying into/out of stopped/created containers as we need to nsenter into the user namespace of the + // pid of the running container with --preserve-credentials to preserve uid/gid mapping and copy files into the container. + + if !errdefs.IsNotFound(err) || rootlessutil.IsRootless() { + return err + } + root, cleanup, err = mountSnapshotForContainer(ctx, client, container, snapshotter) + if cleanup != nil { + defer cleanup() + } + if err != nil { + return err + } + } else { + status, err := task.Status(ctx) + if err != nil { + return err + } + if status.Status == containerd.Running { + root = fmt.Sprintf("/proc/%d/root", task.Pid()) + } else { + if rootlessutil.IsRootless() { + return fmt.Errorf("cannot use cp with stopped containers in rootless mode") + } + root, cleanup, err = mountSnapshotForContainer(ctx, client, container, snapshotter) + if cleanup != nil { + defer cleanup() + } + if err != nil { + return err + } + } + } if container2host { srcFull, err = securejoin.SecureJoin(root, src) dstFull = dst @@ -56,8 +95,9 @@ func CopyFiles(ctx context.Context, container2host bool, pid int, dst, src strin srcIsDir bool dstExists bool dstExistsAsDir bool + st fs.FileInfo ) - st, err := os.Stat(srcFull) + st, err = os.Stat(srcFull) if err != nil { return err } @@ -82,7 +122,7 @@ func CopyFiles(ctx context.Context, container2host bool, pid int, dst, src strin return fmt.Errorf("cannot copy a directory to a file") } if srcIsDir && !dstExists { - if err := os.MkdirAll(dstFull, 0755); err != nil { + if err := os.MkdirAll(dstFull, 0o755); err != nil { return err } } @@ -138,8 +178,9 @@ func CopyFiles(ctx context.Context, container2host bool, pid int, dst, src strin tarX = append(tarX, "--no-same-owner") } tarX = append(tarX, "-f", "-") + if rootlessutil.IsRootless() { - nsenter := []string{"nsenter", "-t", strconv.Itoa(pid), "-U", "--preserve-credentials", "--"} + nsenter := []string{"nsenter", "-t", strconv.Itoa(int(task.Pid())), "-U", "--preserve-credentials", "--"} if container2host { tarC = append(nsenter, tarC...) } else { @@ -177,3 +218,32 @@ func CopyFiles(ctx context.Context, container2host bool, pid int, dst, src strin } return nil } + +func mountSnapshotForContainer(ctx context.Context, client *containerd.Client, container containerd.Container, snapshotter string) (string, func(), error) { + cinfo, err := container.Info(ctx) + if err != nil { + return "", nil, err + } + snapKey := cinfo.SnapshotKey + resp, err := client.SnapshotService(snapshotter).Mounts(ctx, snapKey) + if err != nil { + return "", nil, err + } + tempDir, err := os.MkdirTemp("", "nerdctl-cp-") + if err != nil { + return "", nil, err + } + err = mount.All(resp, tempDir) + if err != nil { + return "", nil, fmt.Errorf("failed to mount snapshot with error %s", err.Error()) + } + cleanup := func() { + err = mount.Unmount(tempDir, 0) + if err != nil { + logrus.Warnf("failed to unmount %s with error %s", tempDir, err.Error()) + return + } + os.RemoveAll(tempDir) + } + return tempDir, cleanup, nil +} diff --git a/pkg/rootlessutil/rootlessutil_linux.go b/pkg/rootlessutil/rootlessutil_linux.go index 76d77cea860..795df9cf750 100644 --- a/pkg/rootlessutil/rootlessutil_linux.go +++ b/pkg/rootlessutil/rootlessutil_linux.go @@ -67,3 +67,16 @@ func NewRootlessKitClient() (client.Client, error) { apiSock := filepath.Join(stateDir, "api.sock") return client.New(apiSock) } + +// RootlessContainredSockAddress returns sock address of rootless containerd based on https://github.com/containerd/nerdctl/blob/main/docs/faq.md#containerd-socket-address +func RootlessContainredSockAddress() (string, error) { + stateDir, err := RootlessKitStateDir() + if err != nil { + return "", err + } + childPid, err := RootlessKitChildPid(stateDir) + if err != nil { + return "", err + } + return filepath.Join(fmt.Sprintf("/proc/%d/root/run/containerd/containerd.sock", childPid)), nil +} From 6caf4fee6702e2858684ca9c70b79b1008d83582 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 23 Jul 2023 02:01:05 +0900 Subject: [PATCH 0035/1066] CI: test-integration-docker-compatibility: enable BuildKit Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 10 ++++++++++ cmd/nerdctl/builder_build_test.go | 15 ++++++++++----- cmd/nerdctl/image_list_test.go | 15 +++++++++------ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 43d9e7f9138..a439188a227 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -181,6 +181,16 @@ jobs: go-version: ${{ env.GO_VERSION }} cache: true check-latest: true + - name: "Enable BuildKit" + run: | + set -eux -o pipefail + sudo apt-get install -y moreutils + cat /etc/docker/daemon.json + jq '.features.buildkit = true' Date: Tue, 11 Jul 2023 22:05:50 +0900 Subject: [PATCH 0036/1066] Refactor codes Signed-off-by: Kohei Tokunaga --- cmd/nerdctl/builder_build.go | 5 +---- cmd/nerdctl/container_update.go | 9 +++------ pkg/cmd/container/create.go | 7 +++---- pkg/cmd/container/run_gpus.go | 4 ++-- pkg/cmd/container/top.go | 5 +---- pkg/composer/config.go | 7 ++----- pkg/composer/create.go | 5 +---- pkg/composer/pipetagger/pipetagger.go | 5 +---- pkg/composer/restart.go | 5 +---- pkg/composer/run.go | 6 +----- pkg/composer/up.go | 6 +----- pkg/composer/up_service.go | 5 +---- pkg/dnsutil/hostsstore/updater.go | 15 +++------------ pkg/imgutil/jobs/jobs.go | 9 ++++----- pkg/logging/cri_logger_test.go | 3 +-- pkg/mountutil/volumestore/volumestore.go | 11 +++-------- pkg/netutil/netutil.go | 20 ++++---------------- pkg/ocihook/ocihook.go | 4 +--- pkg/signutil/cosignutil.go | 6 +----- pkg/signutil/notationutil.go | 6 +----- 20 files changed, 36 insertions(+), 107 deletions(-) diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index 3b68283df9a..9f562be167a 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -206,8 +206,5 @@ func buildAction(cmd *cobra.Command, args []string) error { } defer cancel() - if err := builder.Build(ctx, client, options); err != nil { - return err - } - return nil + return builder.Build(ctx, client, options) } diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index 7bebaf2b56c..50f530e8ed4 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -362,19 +362,16 @@ func updateContainer(ctx context.Context, client *containerd.Client, id string, } return fmt.Errorf("failed to get task:%w", err) } - if err := task.Update(ctx, containerd.WithResources(spec.Linux.Resources)); err != nil { - return err - } - return nil + return task.Update(ctx, containerd.WithResources(spec.Linux.Resources)) } func updateContainerSpec(ctx context.Context, container containerd.Container, spec *runtimespec.Spec) error { if err := container.Update(ctx, func(ctx context.Context, client *containerd.Client, c *containers.Container) error { - any, err := typeurl.MarshalAny(spec) + a, err := typeurl.MarshalAny(spec) if err != nil { return fmt.Errorf("failed to marshal spec %+v:%w", spec, err) } - c.Spec = any + c.Spec = a return nil }); err != nil { return fmt.Errorf("failed to update container spec:%w", err) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 2038f291f7a..88246e3d7b3 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -323,10 +323,9 @@ func generateRootfsOpts(args []string, id string, ensured *imgutil.EnsuredImage, for ind, env := range ensured.ImageConfig.Env { if strings.HasPrefix(env, "PATH=") { break - } else { - if ind == len(ensured.ImageConfig.Env)-1 { - opts = append(opts, oci.WithDefaultPathEnv) - } + } + if ind == len(ensured.ImageConfig.Env)-1 { + opts = append(opts, oci.WithDefaultPathEnv) } } } else { diff --git a/pkg/cmd/container/run_gpus.go b/pkg/cmd/container/run_gpus.go index cd316fcb00c..fdd14455d85 100644 --- a/pkg/cmd/container/run_gpus.go +++ b/pkg/cmd/container/run_gpus.go @@ -72,8 +72,8 @@ func parseGPUOpt(value string) (oci.SpecOpts, error) { } var nvidiaCaps []nvidia.Capability for _, c := range req.Capabilities { - if cap, isNvidiaCap := str2cap[c]; isNvidiaCap { - nvidiaCaps = append(nvidiaCaps, cap) + if cp, isNvidiaCap := str2cap[c]; isNvidiaCap { + nvidiaCaps = append(nvidiaCaps, cp) } } if len(nvidiaCaps) != 0 { diff --git a/pkg/cmd/container/top.go b/pkg/cmd/container/top.go index 5973ef11eba..f1a3f238b6f 100644 --- a/pkg/cmd/container/top.go +++ b/pkg/cmd/container/top.go @@ -61,10 +61,7 @@ func Top(ctx context.Context, client *containerd.Client, containers []string, op if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - if err := containerTop(ctx, opt.Stdout, client, found.Container.ID(), strings.Join(containers[1:], " ")); err != nil { - return err - } - return nil + return containerTop(ctx, opt.Stdout, client, found.Container.ID(), strings.Join(containers[1:], " ")) }, } diff --git a/pkg/composer/config.go b/pkg/composer/config.go index c58f67326ad..24aa5eb845c 100644 --- a/pkg/composer/config.go +++ b/pkg/composer/config.go @@ -59,17 +59,14 @@ func (c *Composer) Config(ctx context.Context, w io.Writer, co ConfigOptions) er if co.Hash != "*" { services = strings.Split(co.Hash, ",") } - if err := c.project.WithServices(services, func(svc types.ServiceConfig) error { + return c.project.WithServices(services, func(svc types.ServiceConfig) error { hash, err := ServiceHash(svc) if err != nil { return err } fmt.Fprintf(w, "%s %s\n", svc.Name, hash) return nil - }); err != nil { - return err - } - return nil + }) } projectYAML, err := yaml.Marshal(c.project) if err != nil { diff --git a/pkg/composer/create.go b/pkg/composer/create.go index a7aff1f5482..7d8773b33d7 100644 --- a/pkg/composer/create.go +++ b/pkg/composer/create.go @@ -144,10 +144,7 @@ func (c *Composer) createService(ctx context.Context, ps *serviceparser.Service, return nil }) } - if err := runEG.Wait(); err != nil { - return err - } - return nil + return runEG.Wait() } // createServiceContainer must be called after ensureServiceImage diff --git a/pkg/composer/pipetagger/pipetagger.go b/pkg/composer/pipetagger/pipetagger.go index b9f485b80cd..9b014354463 100644 --- a/pkg/composer/pipetagger/pipetagger.go +++ b/pkg/composer/pipetagger/pipetagger.go @@ -107,8 +107,5 @@ func (x *PipeTagger) Run() error { ) } } - if err := scanner.Err(); err != nil { - return err - } - return nil + return scanner.Err() } diff --git a/pkg/composer/restart.go b/pkg/composer/restart.go index 1e3ff565b8a..b711925d062 100644 --- a/pkg/composer/restart.go +++ b/pkg/composer/restart.go @@ -43,10 +43,7 @@ func (c *Composer) Restart(ctx context.Context, opt RestartOptions, services []s return err } - if err := c.restartContainers(ctx, containers, opt); err != nil { - return err - } - return nil + return c.restartContainers(ctx, containers, opt) }) } diff --git a/pkg/composer/run.go b/pkg/composer/run.go index 5a6e11f9f5d..0cdba11f8b7 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -202,11 +202,7 @@ func (c *Composer) Run(ctx context.Context, ro RunOptions) error { } } - if err := c.runServices(ctx, parsedServices, ro); err != nil { - return err - } - - return nil + return c.runServices(ctx, parsedServices, ro) } func (c *Composer) runServices(ctx context.Context, parsedServices []*serviceparser.Service, ro RunOptions) error { diff --git a/pkg/composer/up.go b/pkg/composer/up.go index 40eb752d0a1..c76b305df99 100644 --- a/pkg/composer/up.go +++ b/pkg/composer/up.go @@ -102,11 +102,7 @@ func (c *Composer) Up(ctx context.Context, uo UpOptions, services []string) erro } } - if err := c.upServices(ctx, parsedServices, uo); err != nil { - return err - } - - return nil + return c.upServices(ctx, parsedServices, uo) } func validateFileObjectConfig(obj types.FileObjectConfig, shortName, objType string, project *types.Project) error { diff --git a/pkg/composer/up_service.go b/pkg/composer/up_service.go index 5aa5d3417f0..729befffd57 100644 --- a/pkg/composer/up_service.go +++ b/pkg/composer/up_service.go @@ -106,10 +106,7 @@ func (c *Composer) ensureServiceImage(ctx context.Context, ps *serviceparser.Ser } logrus.Infof("Ensuring image %s", ps.Image) - if err := c.EnsureImage(ctx, ps.Image, ps.PullMode, ps.Unparsed.Platform, ps, quiet); err != nil { - return err - } - return nil + return c.EnsureImage(ctx, ps.Image, ps.PullMode, ps.Unparsed.Platform, ps, quiet) } // upServiceContainer must be called after ensureServiceImage diff --git a/pkg/dnsutil/hostsstore/updater.go b/pkg/dnsutil/hostsstore/updater.go index 51dd9768939..fa7dc11341b 100644 --- a/pkg/dnsutil/hostsstore/updater.go +++ b/pkg/dnsutil/hostsstore/updater.go @@ -60,10 +60,7 @@ func (u *updater) update() error { return err } // phase2: write hosts - if err := u.phase2(); err != nil { - return err - } - return nil + return u.phase2() } // phase1: read meta.json @@ -98,10 +95,7 @@ func (u *updater) phase1() error { } return nil } - if err := filepath.Walk(u.hostsD, readMetaWF); err != nil { - return err - } - return nil + return filepath.Walk(u.hostsD, readMetaWF) } // phase2: write hosts @@ -162,10 +156,7 @@ func (u *updater) phase2() error { } return nil } - if err := filepath.Walk(u.hostsD, writeHostsWF); err != nil { - return err - } - return nil + return filepath.Walk(u.hostsD, writeHostsWF) } // createLine returns a line string slice. diff --git a/pkg/imgutil/jobs/jobs.go b/pkg/imgutil/jobs/jobs.go index da5da32c4ef..47def937a19 100644 --- a/pkg/imgutil/jobs/jobs.go +++ b/pkg/imgutil/jobs/jobs.go @@ -101,11 +101,10 @@ outer: if !errdefs.IsNotFound(err) { log.G(ctx).WithError(err).Error("failed to get content info") continue outer - } else { - statuses[key] = StatusInfo{ - Ref: key, - Status: StatusWaiting, - } + } + statuses[key] = StatusInfo{ + Ref: key, + Status: StatusWaiting, } } else if info.CreatedAt.After(start) { statuses[key] = StatusInfo{ diff --git a/pkg/logging/cri_logger_test.go b/pkg/logging/cri_logger_test.go index fff79506ae6..3788a3c706b 100644 --- a/pkg/logging/cri_logger_test.go +++ b/pkg/logging/cri_logger_test.go @@ -157,9 +157,8 @@ func TestParseLog(t *testing.T) { if err != nil { if test.err { continue - } else { - t.Errorf("ParseCRILog err %s ", err.Error()) } + t.Errorf("ParseCRILog err %s ", err.Error()) } if !reflect.DeepEqual(test.msg, logmsg) { diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index cf2d6a1bd1a..f645a167e71 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -107,10 +107,7 @@ func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, err } volFilePath := filepath.Join(volPath, volumeJSONFileName) - if err := os.WriteFile(volFilePath, labelsJSON, 0644); err != nil { - return err - } - return nil + return os.WriteFile(volFilePath, labelsJSON, 0644) } if err := lockutil.WithDirLock(vs.dir, fn); err != nil { @@ -139,11 +136,9 @@ func (vs *volumeStore) Get(name string, size bool) (*native.Volume, error) { volFilePath := filepath.Join(vs.dir, name, volumeJSONFileName) volumeDataBytes, err := os.ReadFile(volFilePath) if err != nil { - if os.IsNotExist(err) { - //volume.json does not exists should not be blocking for inspect operation - } else { + if !os.IsNotExist(err) { return nil, err - } + } // on else, volume.json does not exists should not be blocking for inspect operation } entry := native.Volume{ diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index b30d11e08fd..c2220d4c769 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -127,10 +127,7 @@ func namespaceUsedNetworks(ctx context.Context, containers []containerd.Containe func WithDefaultNetwork() CNIEnvOpt { return func(e *CNIEnv) error { - if err := e.ensureDefaultNetworkConfig(); err != nil { - return err - } - return nil + return e.ensureDefaultNetworkConfig() } } @@ -256,10 +253,7 @@ func (e *CNIEnv) CreateNetwork(opts CreateOptions) (*NetworkConfig, error) { //n if err != nil { return err } - if err := e.writeNetworkConfig(net); err != nil { - return err - } - return nil + return e.writeNetworkConfig(net) } err = lockutil.WithDirLock(e.NetconfPath, fn) if err != nil { @@ -273,10 +267,7 @@ func (e *CNIEnv) RemoveNetwork(net *NetworkConfig) error { if err := os.RemoveAll(net.File); err != nil { return err } - if err := net.clean(); err != nil { - return err - } - return nil + return net.clean() } return lockutil.WithDirLock(e.NetconfPath, fn) } @@ -410,10 +401,7 @@ func (e *CNIEnv) writeNetworkConfig(net *NetworkConfig) error { if _, err := os.Stat(filename); err == nil { return errdefs.ErrAlreadyExists } - if err := os.WriteFile(filename, net.Bytes, 0644); err != nil { - return err - } - return nil + return os.WriteFile(filename, net.Bytes, 0644) } // networkConfigList loads config from dir if dir exists. diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 4d7e3430ba0..d49b12bbfb0 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -315,9 +315,7 @@ func getPortMapOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { if hostIP := net.ParseIP(p.HostIP); hostIP != nil && !hostIP.IsUnspecified() { // loopback address is always bindable in the child namespace, but other addresses are unlikely. if !hostIP.IsLoopback() { - if childIP != nil && childIP.Equal(hostIP) { - // this is fine - } else { + if !(childIP != nil && childIP.Equal(hostIP)) { if portDriverDisallowsLoopbackChildIP { p.HostIP = childIP.String() } else { diff --git a/pkg/signutil/cosignutil.go b/pkg/signutil/cosignutil.go index 80cce2a94d6..0928d4f568a 100644 --- a/pkg/signutil/cosignutil.go +++ b/pkg/signutil/cosignutil.go @@ -57,11 +57,7 @@ func SignCosign(rawRef string, keyRef string) error { return err } - if err := cosignCmd.Wait(); err != nil { - return err - } - - return nil + return cosignCmd.Wait() } // VerifyCosign verifies an image(`rawRef`) with a cosign public key(`keyRef`) diff --git a/pkg/signutil/notationutil.go b/pkg/signutil/notationutil.go index 3af6b7b8593..522ce66f518 100644 --- a/pkg/signutil/notationutil.go +++ b/pkg/signutil/notationutil.go @@ -53,11 +53,7 @@ func SignNotation(rawRef string, keyNameRef string) error { return err } - if err := notationCmd.Wait(); err != nil { - return err - } - - return nil + return notationCmd.Wait() } // VerifyNotation verifies an image(`rawRef`) with the pre-configured notation trust policy From b16125c87f2ad7e84a6c2e13f1d2ba4d7d0a343f Mon Sep 17 00:00:00 2001 From: Kohei Tokunaga Date: Tue, 11 Jul 2023 22:06:05 +0900 Subject: [PATCH 0037/1066] Re-enable revive rules Signed-off-by: Kohei Tokunaga --- .golangci.yml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 602ab5c216b..a902b9f03b7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -137,21 +137,6 @@ linters-settings: issues: exclude-rules: - - linters: - - revive - text: "if-return" - - linters: - - revive - text: "empty-block" - - linters: - - revive - text: "superfluous-else" - linters: - revive text: "unused-parameter" - - linters: - - revive - text: "unreachable-code" - - linters: - - revive - text: "redefines-builtin-id" From ccce1954b65a020e4933ee2e52d9a6e4dd31e0dd Mon Sep 17 00:00:00 2001 From: Vishwas Siravara Date: Sun, 23 Jul 2023 20:16:23 -0700 Subject: [PATCH 0038/1066] Add network flag to nerdctl build Signed-off-by: Vishwas Siravara --- cmd/nerdctl/builder_build.go | 10 +++++- cmd/nerdctl/builder_build_test.go | 46 ++++++++++++++++++++++++++++ cmd/nerdctl/completion_linux_test.go | 2 +- docs/command-reference.md | 3 +- pkg/api/types/builder_types.go | 2 ++ pkg/cmd/builder/build.go | 12 ++++++++ 6 files changed, 72 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index 3b68283df9a..4b45c0e296f 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -56,7 +56,10 @@ If Dockerfile is not present and -f is not specified, it will look for Container buildCommand.Flags().StringArray("cache-from", nil, "External cache sources (eg. user/app:cache, type=local,src=path/to/dir)") buildCommand.Flags().StringArray("cache-to", nil, "Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir)") buildCommand.Flags().Bool("rm", true, "Remove intermediate containers after a successful build") - + buildCommand.Flags().String("network", "default", "Set type of network for build (format:network=default|none|host)") + buildCommand.RegisterFlagCompletionFunc("network", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"default", "host", "none"}, cobra.ShellCompDirectiveNoFileComp + }) // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" buildCommand.Flags().StringSlice("platform", []string{}, "Set target platform for build (e.g., \"amd64\", \"arm64\")") @@ -153,6 +156,10 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu if err != nil { return types.BuilderBuildOptions{}, err } + network, err := cmd.Flags().GetString("network") + if err != nil { + return types.BuilderBuildOptions{}, err + } return types.BuilderBuildOptions{ GOptions: globalOptions, BuildKitHost: buildKitHost, @@ -176,6 +183,7 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu Stdout: cmd.OutOrStdout(), Stderr: cmd.OutOrStderr(), Stdin: cmd.InOrStdin(), + NetworkMode: network, }, nil } diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index e0d1e4cc839..4b7e89f9301 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -454,3 +454,49 @@ CMD ["cat", "/source-date-epoch"] base.Cmd("build", "-t", imageName, "--build-arg", "SOURCE_DATE_EPOCH="+sourceDateEpochArgStr, buildCtx).AssertOK() base.Cmd("run", "--rm", imageName).AssertOutExactly(sourceDateEpochArgStr + "\n") } + +func TestBuildNetwork(t *testing.T) { + testutil.RequiresBuild(t) + base := testutil.NewBase(t) + defer base.Cmd("builder", "prune").AssertOK() + + dockerfile := fmt.Sprintf(`FROM %s +RUN apk add --no-cache curl +RUN curl -I http://google.com + `, testutil.CommonImage) + buildCtx, err := createBuildContext(dockerfile) + assert.NilError(t, err) + defer os.RemoveAll(buildCtx) + + validCases := []struct { + name string + network string + exitCode int + }{ + // When network=none, can't connect to internet, therefore cannot download packages in the dockerfile + // Order is important here, test fails for `-test.target=docker` in CI + {"test_with_no_network", "none", 1}, + {"test_with_empty_network", "", 0}, + {"test_with_default_network", "default", 0}, + } + + for _, tc := range validCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + // --no-cache is intentional here for `-test.target=docker` + base.Cmd("build", buildCtx, "-t", tc.name, "--no-cache", "--network", tc.network).AssertExitCode(tc.exitCode) + if tc.exitCode != 1 { + defer base.Cmd("rmi", tc.name).AssertOK() + } + }) + } +} + +func TestBuildNetworkShellCompletion(t *testing.T) { + testutil.DockerIncompatible(t) + base := testutil.NewBase(t) + const gsc = "__complete" + // Tests with build network + networkName := "default" + base.Cmd(gsc, "build", "--network", "").AssertOutContains(networkName) +} diff --git a/cmd/nerdctl/completion_linux_test.go b/cmd/nerdctl/completion_linux_test.go index ccff901371e..ea0edc4c926 100644 --- a/cmd/nerdctl/completion_linux_test.go +++ b/cmd/nerdctl/completion_linux_test.go @@ -47,7 +47,7 @@ func TestCompletion(t *testing.T) { base.Cmd(gsc, "run", "-it", "").AssertOutContains(testutil.AlpineImage) base.Cmd(gsc, "run", "-it", "--rm", "").AssertOutContains(testutil.AlpineImage) - // Tests with an network + // Tests with a network testNetworkName := "nerdctl-test-completion" defer base.Cmd("network", "rm", testNetworkName).Run() base.Cmd("network", "create", testNetworkName).AssertOK() diff --git a/docs/command-reference.md b/docs/command-reference.md index 565da410f5e..f2c9d5c6a87 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -655,8 +655,9 @@ Flags: - :whale: `--iidfile=FILE`: Write the image ID to the file - :nerd_face: `--ipfs`: Build image with pulling base images from IPFS. See [`ipfs.md`](./ipfs.md) for details. - :whale: `--label`: Set metadata for an image +- :whale: `--network=(default|host|none)`: Set the networking mode for the RUN instructions during build.(compatible with `buildctl build`) -Unimplemented `docker build` flags: `--add-host`, `--network`, `--squash` +Unimplemented `docker build` flags: `--add-host`, `--squash` ### :whale: nerdctl commit diff --git a/pkg/api/types/builder_types.go b/pkg/api/types/builder_types.go index 76e8934089e..c796c3568d3 100644 --- a/pkg/api/types/builder_types.go +++ b/pkg/api/types/builder_types.go @@ -61,6 +61,8 @@ type BuilderBuildOptions struct { Label []string // BuildContext is the build context BuildContext string + // NetworkMode mode for the build context + NetworkMode string } // BuilderPruneOptions specifies options for `nerdctl builder prune`. diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 84c5ff43b28..378cd1267ae 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -358,6 +358,18 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option buildctlArgs = append(buildctlArgs, "--metadata-file="+metaFile) } + if options.NetworkMode != "" { + switch options.NetworkMode { + case "none": + buildctlArgs = append(buildctlArgs, "--opt=force-network-mode="+options.NetworkMode) + case "host": + buildctlArgs = append(buildctlArgs, "--opt=force-network-mode="+options.NetworkMode, "--allow=network.host", "--allow=security.insecure") + case "", "default": + default: + logrus.Debugf("ignoring network build arg %s", options.NetworkMode) + } + } + return buildctlBinary, buildctlArgs, needsLoading, metaFile, tags, cleanup, nil } From 9f0a4581104245f866b496aa38b251896c92073d Mon Sep 17 00:00:00 2001 From: Channing Gaddy Date: Tue, 18 Jul 2023 20:19:06 -0700 Subject: [PATCH 0039/1066] feat: adding support for lazy-pulling with soci in pull and run command Signed-off-by: Channing Gaddy --- Dockerfile | 11 ++- ...est-integration-etc_containerd_config.toml | 12 +++ .../test-integration-soci-snapshotter.service | 15 +++ cmd/nerdctl/container_run_soci_linux_test.go | 95 +++++++++++++++++++ cmd/nerdctl/image_pull_linux_test.go | 55 +++++++++++ go.mod | 13 +-- go.sum | 26 ++--- pkg/imgutil/snapshotter.go | 7 ++ pkg/imgutil/snapshotter_test.go | 23 +++++ pkg/testutil/testutil_linux.go | 3 +- 10 files changed, 240 insertions(+), 20 deletions(-) create mode 100644 Dockerfile.d/test-integration-etc_containerd_config.toml create mode 100644 Dockerfile.d/test-integration-soci-snapshotter.service create mode 100644 cmd/nerdctl/container_run_soci_linux_test.go diff --git a/Dockerfile b/Dockerfile index 4bed75f6ac3..80a0726e485 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,6 +49,7 @@ ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.10.0 ARG NYDUS_VERSION=v2.2.1 +ARG SOCI_SNAPSHOTTER_VERSION=0.3.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.2.1 AS xx @@ -282,13 +283,21 @@ VOLUME /tmp ENV CGO_ENABLED=0 # copy cosign binary for integration test COPY --from=gcr.io/projectsigstore/cosign:v2.0.0@sha256:728944a9542a7235b4358c4ab2bcea855840e9d4b9594febca5c2207f5da7f38 /ko-app/cosign /usr/local/bin/cosign +# installing soci for integration test +ARG SOCI_SNAPSHOTTER_VERSION +RUN fname="soci-snapshotter-${SOCI_SNAPSHOTTER_VERSION}-${TARGETOS:-linux}-${TARGETARCH:-amd64}.tar.gz" && \ + curl -o "${fname}" -fSL "https://github.com/awslabs/soci-snapshotter/releases/download/v${SOCI_SNAPSHOTTER_VERSION}/${fname}" && \ + tar -C /usr/local/bin -xvf "${fname}" soci soci-snapshotter-grpc # enable offline ipfs for integration test COPY ./Dockerfile.d/test-integration-etc_containerd-stargz-grpc_config.toml /etc/containerd-stargz-grpc/config.toml COPY ./Dockerfile.d/test-integration-ipfs-offline.service /usr/local/lib/systemd/system/ COPY ./Dockerfile.d/test-integration-buildkit-nerdctl-test.service /usr/local/lib/systemd/system/ +COPY ./Dockerfile.d/test-integration-soci-snapshotter.service /usr/local/lib/systemd/system/ RUN cp /usr/local/bin/tini /usr/local/bin/tini-custom +# using test integration containerd config +COPY ./Dockerfile.d/test-integration-etc_containerd_config.toml /etc/containerd/config.toml # install ipfs service. avoid using 5001(api)/8080(gateway) which are reserved by tests. -RUN systemctl enable test-integration-ipfs-offline test-integration-buildkit-nerdctl-test && \ +RUN systemctl enable test-integration-ipfs-offline test-integration-buildkit-nerdctl-test test-integration-soci-snapshotter && \ ipfs init && \ ipfs config Addresses.API "/ip4/127.0.0.1/tcp/5888" && \ ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/5889" diff --git a/Dockerfile.d/test-integration-etc_containerd_config.toml b/Dockerfile.d/test-integration-etc_containerd_config.toml new file mode 100644 index 00000000000..d37df58da75 --- /dev/null +++ b/Dockerfile.d/test-integration-etc_containerd_config.toml @@ -0,0 +1,12 @@ +version = 2 + +# Enable stargz snapshotter +[proxy_plugins] + [proxy_plugins.stargz] + type = "snapshot" + address = "/run/containerd-stargz-grpc/containerd-stargz-grpc.sock" + +# Enable soci snapshotter + [proxy_plugins.soci] + type = "snapshot" + address = "/run/soci-snapshotter-grpc/soci-snapshotter-grpc.sock" diff --git a/Dockerfile.d/test-integration-soci-snapshotter.service b/Dockerfile.d/test-integration-soci-snapshotter.service new file mode 100644 index 00000000000..5964702ac6a --- /dev/null +++ b/Dockerfile.d/test-integration-soci-snapshotter.service @@ -0,0 +1,15 @@ +[Unit] +Description=soci snapshotter containerd plugin for integration test +Documentation=https://github.com/awslabs/soci-snapshotter +After=network.target +Before=containerd.service + +[Service] +Type=notify +ExecStartPre=/bin/bash -c 'mkdir -p /var/lib/soci-snapshotter-grpc && mount -t tmpfs none /var/lib/soci-snapshotter-grpc' +ExecStart=/usr/local/bin/soci-snapshotter-grpc +Restart=always +RestartSec=5 + +[Install] +WantedBy=docker-entrypoint.target diff --git a/cmd/nerdctl/container_run_soci_linux_test.go b/cmd/nerdctl/container_run_soci_linux_test.go new file mode 100644 index 00000000000..fe3cda5befa --- /dev/null +++ b/cmd/nerdctl/container_run_soci_linux_test.go @@ -0,0 +1,95 @@ +/* + 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 ( + "os" + "os/exec" + "strings" + "testing" + + "github.com/containerd/nerdctl/pkg/testutil" +) + +func TestRunSoci(t *testing.T) { + testutil.DockerIncompatible(t) + base := testutil.NewBase(t) + requiresSoci(base) + + //counting initial snapshot mounts + initialMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } + + remoteSnapshotsInitialCount := strings.Count(string(initialMounts), "fuse.rawBridge") + + if remoteSnapshotsInitialCount != 0 { + t.Fatalf("initial mounts count isn't zero") + } + + //validating `nerdctl --snapshotter=soci run` and `soci rpull` behave the same using mounts + runOutput := base.Cmd("--snapshotter=soci", "run", "--rm", testutil.FfmpegSociImage).Out() + base.T.Logf("run output: %s", runOutput) + + actualMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } + remoteSnapshotsActualCount := strings.Count(string(actualMounts), "fuse.rawBridge") + base.T.Logf("number of actual mounts: %v", remoteSnapshotsActualCount) + + rmiOutput := base.Cmd("rmi", testutil.FfmpegSociImage).Out() + base.T.Logf("rmi output: %s", rmiOutput) + + sociExecutable, err := exec.LookPath("soci") + if err != nil { + t.Fatalf("SOCI is not installed.") + } + + rpullCmd := exec.Command(sociExecutable, []string{"image", "rpull", testutil.FfmpegSociImage}...) + + rpullCmd.Env = os.Environ() + + err = rpullCmd.Run() + if err != nil { + t.Fatal(err) + } + + expectedMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } + + remoteSnapshotsExpectedCount := strings.Count(string(expectedMounts), "fuse.rawBridge") + base.T.Logf("number of expected mounts: %v", remoteSnapshotsExpectedCount) + + if remoteSnapshotsExpectedCount != remoteSnapshotsActualCount { + t.Fatalf("incorrect number of remote snapshots; expected=%d, actual=%d", + remoteSnapshotsExpectedCount, remoteSnapshotsActualCount) + } +} + +func requiresSoci(base *testutil.Base) { + info := base.Info() + for _, p := range info.Plugins.Storage { + if p == "soci" { + return + } + } + base.T.Skip("test requires soci") +} diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image_pull_linux_test.go index 777e00120f8..2ddf44ba882 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image_pull_linux_test.go @@ -145,3 +145,58 @@ CMD ["echo", "nerdctl-build-test-string"] newKeyPair := newCosignKeyPair(t, "cosign-key-pair-test") base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+newKeyPair.publicKey).AssertFail() } + +func TestPullSoci(t *testing.T) { + testutil.DockerIncompatible(t) + base := testutil.NewBase(t) + requiresSoci(base) + + //counting initial snapshot mounts + initialMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } + + remoteSnapshotsInitialCount := strings.Count(string(initialMounts), "fuse.rawBridge") + + //validating `nerdctl --snapshotter=soci pull` and `soci rpull` behave the same using mounts + pullOutput := base.Cmd("--snapshotter=soci", "pull", testutil.FfmpegSociImage).Out() + base.T.Logf("pull output: %s", pullOutput) + + actualMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } + remoteSnapshotsActualCount := strings.Count(string(actualMounts), "fuse.rawBridge") + base.T.Logf("number of actual mounts: %v", remoteSnapshotsActualCount) + + rmiOutput := base.Cmd("rmi", testutil.FfmpegSociImage).Out() + base.T.Logf("rmi output: %s", rmiOutput) + + sociExecutable, err := exec.LookPath("soci") + if err != nil { + t.Fatalf("SOCI is not installed.") + } + + rpullCmd := exec.Command(sociExecutable, []string{"image", "rpull", testutil.FfmpegSociImage}...) + + rpullCmd.Env = os.Environ() + + err = rpullCmd.Run() + if err != nil { + t.Fatal(err) + } + + expectedMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } + + remoteSnapshotsExpectedCount := strings.Count(string(expectedMounts), "fuse.rawBridge") + base.T.Logf("number of expected mounts: %v", remoteSnapshotsExpectedCount) + + if remoteSnapshotsExpectedCount != (remoteSnapshotsActualCount - remoteSnapshotsInitialCount) { + t.Fatalf("incorrect number of remote snapshots; expected=%d, actual=%d", + remoteSnapshotsExpectedCount, remoteSnapshotsActualCount) + } +} diff --git a/go.mod b/go.mod index c2dea8171be..e4181fc989a 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.10.0-rc.9 + github.com/awslabs/soci-snapshotter v0.3.0 github.com/compose-spec/compose-go v1.17.0 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 @@ -68,7 +69,7 @@ require ( require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect - github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 // indirect + github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/cilium/ebpf v0.9.1 // indirect github.com/containerd/cgroups v1.1.0 // indirect @@ -125,12 +126,12 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.14.0 // indirect - go.opentelemetry.io/otel/trace v1.14.0 // indirect + go.opentelemetry.io/otel v1.15.1 // indirect + go.opentelemetry.io/otel/trace v1.15.1 // indirect golang.org/x/mod v0.11.0 // indirect - golang.org/x/tools v0.8.0 // indirect - google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect - google.golang.org/grpc v1.54.0 // indirect + golang.org/x/tools v0.9.1 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/grpc v1.55.0 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect lukechampine.com/blake3 v1.1.7 // indirect diff --git a/go.sum b/go.sum index 03f55ce3416..2cd4d72cef1 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 h1:+vTEFqeoeur6XSq06bs+roX3YiT49gUniJK7Zky7Xjg= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= @@ -117,6 +117,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/awslabs/soci-snapshotter v0.3.0 h1:DcVedf88R8GO77WhJn/dusQqzCrjrh1RWBataW6pVV8= +github.com/awslabs/soci-snapshotter v0.3.0/go.mod h1:s3cGc7hKDMefFbTf4YGzxRC9Q9nm2E/IU+65ExdRbvA= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -1049,8 +1051,8 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.2 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= -go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= +go.opentelemetry.io/otel v1.15.1 h1:3Iwq3lfRByPaws0f6bU3naAqOR1n5IeDWd9390kWHa8= +go.opentelemetry.io/otel v1.15.1/go.mod h1:mHHGEHVDLal6YrKMmk9LqC4a3sF5g+fHfrttQIB1NTc= go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= @@ -1064,8 +1066,8 @@ go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= -go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel/trace v1.15.1 h1:uXLo6iHJEzDfrNC0L0mNjItIp06SyaBQxu5t3xMlngY= +go.opentelemetry.io/otel/trace v1.15.1/go.mod h1:IWdQG/5N1x7f6YUlmdLeJvH9yxtuJAfc4VW5Agv9r/8= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1416,8 +1418,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= -golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1501,8 +1503,8 @@ google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1531,8 +1533,8 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/pkg/imgutil/snapshotter.go b/pkg/imgutil/snapshotter.go index 0655c4774ce..922deca785f 100644 --- a/pkg/imgutil/snapshotter.go +++ b/pkg/imgutil/snapshotter.go @@ -19,6 +19,7 @@ package imgutil import ( "strings" + socisource "github.com/awslabs/soci-snapshotter/fs/source" "github.com/containerd/containerd" "github.com/containerd/containerd/images" ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" @@ -31,6 +32,7 @@ const ( snapshotterNameOverlaybd = "overlaybd" snapshotterNameStargz = "stargz" snapshotterNameNydus = "nydus" + snapshotterNameSoci = "soci" // prefetch size for stargz prefetchSize = 10 * 1024 * 1024 @@ -41,6 +43,7 @@ var builtinRemoteSnapshotterOpts = map[string]snapshotterOpts{ snapshotterNameOverlaybd: &remoteSnapshotterOpts{snapshotter: "overlaybd"}, snapshotterNameStargz: &remoteSnapshotterOpts{snapshotter: "stargz", extraLabels: stargzExtraLabels}, snapshotterNameNydus: &remoteSnapshotterOpts{snapshotter: "nydus"}, + snapshotterNameSoci: &remoteSnapshotterOpts{snapshotter: "soci", extraLabels: sociExtraLabels}, } // snapshotterOpts is used to update pull config @@ -107,3 +110,7 @@ func (dsn *defaultSnapshotterOpts) isRemote() bool { func stargzExtraLabels(f func(images.Handler) images.Handler) func(images.Handler) images.Handler { return source.AppendExtraLabelsHandler(prefetchSize, f) } + +func sociExtraLabels(f func(images.Handler) images.Handler) func(images.Handler) images.Handler { + return socisource.AppendDefaultLabelsHandlerWrapper("", f) +} diff --git a/pkg/imgutil/snapshotter_test.go b/pkg/imgutil/snapshotter_test.go index 975d421f811..5ca8115daa9 100644 --- a/pkg/imgutil/snapshotter_test.go +++ b/pkg/imgutil/snapshotter_test.go @@ -52,6 +52,10 @@ func TestGetSnapshotterOpts(t *testing.T) { sns: []string{"stargz", "stargz-v1"}, check: remoteSnOpts("stargz", true), }, + { + sns: []string{"soci"}, + check: remoteSnOpts("soci", true), + }, { sns: []string{"overlaybd", "overlaybd-v2"}, check: sameOpts(&remoteSnapshotterOpts{snapshotter: "overlaybd"}), @@ -132,6 +136,12 @@ func TestRemoteSnapshotterOpts(t *testing.T) { checkRemoteSnapshotterAnnotataions, checkStargzSnapshotterAnnotataions, }, }, + { + name: "soci", + check: []func(t *testing.T, a map[string]string){ + checkRemoteSnapshotterAnnotataions, checkSociSnapshotterAnnotataions, + }, + }, { name: "nydus", check: []func(t *testing.T, a map[string]string){checkRemoteSnapshotterAnnotataions}, @@ -175,3 +185,16 @@ func checkStargzSnapshotterAnnotataions(t *testing.T, a map[string]string) { _, ok := a["containerd.io/snapshot/remote/urls"] assert.Equal(t, ok, true) } + +// using values from soci source to check for annotations ( +// see https://github.com/awslabs/soci-snapshotter/blob/b05ba712d246ecc5146469f87e5e9305702fd72b/fs/source/source.go#L80C1-L80C6 +func checkSociSnapshotterAnnotataions(t *testing.T, a map[string]string) { + assert.Check(t, a != nil) + _, ok := a["containerd.io/snapshot/remote/soci.size"] + assert.Equal(t, ok, true) + _, ok = a["containerd.io/snapshot/remote/image.layers.size"] + assert.Equal(t, ok, true) + _, ok = a["containerd.io/snapshot/remote/soci.index.digest"] + assert.Equal(t, ok, true) + +} diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index fb27e609ea2..3fd65421c11 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -57,7 +57,8 @@ var ( ) const ( - FedoraESGZImage = "ghcr.io/stargz-containers/fedora:30-esgz" // eStargz + FedoraESGZImage = "ghcr.io/stargz-containers/fedora:30-esgz" // eStargz + FfmpegSociImage = "public.ecr.aws/soci-workshop-examples/ffmpeg:latest" // SOCI ) type delayOnceReader struct { From c2406a4be8d19aa32f2bda9c351bc0bc84b82bd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jul 2023 22:57:43 +0000 Subject: [PATCH 0040/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 24.0.4+incompatible to 24.0.5+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v24.0.4...v24.0.5) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c2dea8171be..197833d3acf 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.3 github.com/docker/cli v24.0.4+incompatible - github.com/docker/docker v24.0.4+incompatible + github.com/docker/docker v24.0.5+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.1.3 diff --git a/go.sum b/go.sum index 03f55ce3416..4344882280f 100644 --- a/go.sum +++ b/go.sum @@ -366,8 +366,8 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v24.0.4+incompatible h1:s/LVDftw9hjblvqIeTiGYXBCD95nOEEl7qRsRrIOuQI= -github.com/docker/docker v24.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= +github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= From 754b2ff472bc6dd41d5f53757272f0d02a711e7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jul 2023 22:58:22 +0000 Subject: [PATCH 0041/1066] build(deps): bump github.com/opencontainers/runtime-spec Bumps [github.com/opencontainers/runtime-spec](https://github.com/opencontainers/runtime-spec) from 1.1.0-rc.3 to 1.1.0. - [Release notes](https://github.com/opencontainers/runtime-spec/releases) - [Changelog](https://github.com/opencontainers/runtime-spec/blob/main/ChangeLog) - [Commits](https://github.com/opencontainers/runtime-spec/compare/v1.1.0-rc.3...v1.1.0) --- updated-dependencies: - dependency-name: github.com/opencontainers/runtime-spec dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c2dea8171be..10206cbd1da 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/moby/term v0.5.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc4 - github.com/opencontainers/runtime-spec v1.1.0-rc.3 + github.com/opencontainers/runtime-spec v1.1.0 github.com/pelletier/go-toml v1.9.5 github.com/rootless-containers/bypass4netns v0.3.0 github.com/rootless-containers/rootlesskit v1.1.1 diff --git a/go.sum b/go.sum index 03f55ce3416..791df7b21f2 100644 --- a/go.sum +++ b/go.sum @@ -818,8 +818,8 @@ github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.m github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.1.0-rc.3 h1:l04uafi6kxByhbxev7OWiuUv0LZxEsYUfDWZ6bztAuU= -github.com/opencontainers/runtime-spec v1.1.0-rc.3/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= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= From 7518a4c22cf5c0b67e23ef19e84460b1375ed7de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 01:17:43 +0000 Subject: [PATCH 0042/1066] build(deps): bump github.com/Microsoft/hcsshim Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.10.0-rc.9 to 0.10.0. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.10.0-rc.9...v0.10.0) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 12 ++++-------- go.sum | 15 ++++++--------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index e4181fc989a..e2adb527e90 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 - github.com/Microsoft/hcsshim v0.10.0-rc.9 + github.com/Microsoft/hcsshim v0.10.0 github.com/awslabs/soci-snapshotter v0.3.0 github.com/compose-spec/compose-go v1.17.0 github.com/containerd/accelerated-container-image v0.6.7 @@ -62,17 +62,13 @@ require ( gotest.tools/v3 v3.5.0 ) -require ( - github.com/golang/mock v1.6.0 // indirect - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect -) +require golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/cilium/ebpf v0.9.1 // indirect - github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/ttrpc v1.2.2 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect @@ -131,8 +127,8 @@ require ( golang.org/x/mod v0.11.0 // indirect golang.org/x/tools v0.9.1 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect - google.golang.org/grpc v1.55.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/grpc v1.56.2 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/go.sum b/go.sum index 2cd4d72cef1..a49dc5383ad 100644 --- a/go.sum +++ b/go.sum @@ -91,8 +91,8 @@ github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwT github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim v0.10.0-rc.9 h1:B4mguSolFL2yOHl0JjQxo0Si2Vwipj/Cbib4pyJ4pKA= -github.com/Microsoft/hcsshim v0.10.0-rc.9/go.mod h1:1g6+xpige+npSTrEkdm8JOZxOjJ9McQiT0JkEpzyZqA= +github.com/Microsoft/hcsshim v0.10.0 h1:PbvoxdUGgXxyirmN5Oncp3POLkxEG5LbWCEBfWmHTGA= +github.com/Microsoft/hcsshim v0.10.0/go.mod h1:3j1trOamcUdi86J5Tr5+1BpqMjSv/QeRWkX2whBF6dY= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -192,8 +192,6 @@ github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4S github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= -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.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= @@ -493,7 +491,6 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -1533,8 +1530,8 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= +google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1548,8 +1545,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 2135a5c8a077554172e3b5d433145b7a213d29dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 02:52:13 +0000 Subject: [PATCH 0043/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 24.0.4+incompatible to 24.0.5+incompatible. - [Commits](https://github.com/docker/cli/compare/v24.0.4...v24.0.5) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b2fdfcba69b..3b93437372c 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/coreos/go-iptables v0.6.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.3 - github.com/docker/cli v24.0.4+incompatible + github.com/docker/cli v24.0.5+incompatible github.com/docker/docker v24.0.5+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 5f7b7ced420..73ceaa514fa 100644 --- a/go.sum +++ b/go.sum @@ -360,8 +360,8 @@ 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/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v24.0.4+incompatible h1:Y3bYF9ekNTm2VFz5U/0BlMdJy73D+Y1iAAZ8l63Ydzw= -github.com/docker/cli v24.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= +github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= From 7091a12699033d075dcd42c20ad8b9b559d61717 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Jul 2023 22:31:28 +0000 Subject: [PATCH 0044/1066] build(deps): bump github.com/containerd/containerd from 1.7.2 to 1.7.3 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.2 to 1.7.3. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.2...v1.7.3) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3b93437372c..61fa5d68bee 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 - github.com/containerd/containerd v1.7.2 + github.com/containerd/containerd v1.7.3 github.com/containerd/continuity v0.4.1 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.7 diff --git a/go.sum b/go.sum index 73ceaa514fa..d3095928912 100644 --- a/go.sum +++ b/go.sum @@ -219,8 +219,8 @@ github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0 github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0= -github.com/containerd/containerd v1.7.2 h1:UF2gdONnxO8I6byZXDi5sXWiWvlW3D/sci7dTQimEJo= -github.com/containerd/containerd v1.7.2/go.mod h1:afcz74+K10M/+cjGHIVQrCt3RAQhUSCAjJ9iMYhhkuI= +github.com/containerd/containerd v1.7.3 h1:cKwYKkP1eTj54bP3wCdXXBymmKRQMrWjkLSWZZJDa8o= +github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= From fa6f85a05150bb0c0dc28172999980fc799ee9be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Jul 2023 22:31:37 +0000 Subject: [PATCH 0045/1066] build(deps): bump github.com/tidwall/gjson from 1.14.4 to 1.15.0 Bumps [github.com/tidwall/gjson](https://github.com/tidwall/gjson) from 1.14.4 to 1.15.0. - [Commits](https://github.com/tidwall/gjson/compare/v1.14.4...v1.15.0) --- updated-dependencies: - dependency-name: github.com/tidwall/gjson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3b93437372c..86b3817152f 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/tidwall/gjson v1.14.4 + github.com/tidwall/gjson v1.15.0 github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 diff --git a/go.sum b/go.sum index 73ceaa514fa..62bfba08eb4 100644 --- a/go.sum +++ b/go.sum @@ -965,8 +965,8 @@ github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= -github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.15.0 h1:5n/pM+v3r5ujuNl4YLZLsQ+UE5jlkLVm7jMzT5Mpolw= +github.com/tidwall/gjson v1.15.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= From c90ab390ec7eed0e618ec0c182cf8102e9a9f1cc Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Fri, 28 Jul 2023 20:48:55 +0200 Subject: [PATCH 0046/1066] registry documentation update Signed-off-by: fahed dorgaa --- docs/registry.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/registry.md b/docs/registry.md index 299809e26f2..b74e1ffa18b 100644 --- a/docs/registry.md +++ b/docs/registry.md @@ -49,6 +49,7 @@ See https://github.com/containerd/nerdctl/issues/86 for the discussion about wor + - [Amazon Elastic Container Registry (ECR)](#amazon-elastic-container-registry-ecr) - [Logging in](#logging-in) - [Creating a repo](#creating-a-repo) @@ -74,7 +75,7 @@ See https://github.com/containerd/nerdctl/issues/86 for the discussion about wor - [Logging in](#logging-in-5) - [Creating a repo](#creating-a-repo-5) - [Pushing an image](#pushing-an-image-5) -- [Google Container Registry (GCR)](#google-container-registry-gcr) +- [Google Container Registry (GCR) [DEPRECATED]](#google-container-registry-gcr-deprecated) - [Logging in](#logging-in-6) - [Creating a repo](#creating-a-repo-6) - [Pushing an image](#pushing-an-image-6) @@ -280,7 +281,7 @@ Create a [GCP Service Account](https://cloud.google.com/iam/docs/creating-managi Then run the following command: ```console -$ cat | docker login -u _json_key --password-stdin https://-docker.pkg.dev +$ cat | nerdctl login -u _json_key --password-stdin https://-docker.pkg.dev WARNING! Your password will be stored unencrypted in /home//.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store @@ -288,7 +289,7 @@ https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded ``` -See also https://cloud.google.com/artifact-registry/docs/docker/authentication#json-key +See also https://cloud.google.com/artifact-registry/docs/docker/authentication
@@ -336,7 +337,7 @@ $ nerdctl push -docker.pkg.dev///hello-world The pushed image appears in the repository you manually created in the previous step. -## Google Container Registry (GCR) +## Google Container Registry (GCR) [DEPRECATED] See also https://cloud.google.com/container-registry/docs/advanced-authentication ### Logging in @@ -347,7 +348,7 @@ Create a [GCP Service Account](https://cloud.google.com/iam/docs/creating-managi Then run the following command: ```console -$ cat | docker login -u _json_key --password-stdin https://asia.gcr.io +$ cat | nerdctl login -u _json_key --password-stdin https://asia.gcr.io WARNING! Your password will be stored unencrypted in /home//.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store From 8c73a5f6bbf14f95f08580279d46aaefac0af8f9 Mon Sep 17 00:00:00 2001 From: Han Xu Date: Thu, 27 Jul 2023 11:38:46 +0800 Subject: [PATCH 0047/1066] feat: add `stats` command to `container` Signed-off-by: Han Xu --- cmd/nerdctl/container.go | 1 + cmd/nerdctl/container_stats_linux_test.go | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/container.go b/cmd/nerdctl/container.go index 6c0a763f14b..ba2781ef646 100644 --- a/cmd/nerdctl/container.go +++ b/cmd/nerdctl/container.go @@ -49,6 +49,7 @@ func newContainerCommand() *cobra.Command { newCommitCommand(), newRenameCommand(), newContainerPruneCommand(), + newStatsCommand(), ) addCpCommand(containerCommand) return containerCommand diff --git a/cmd/nerdctl/container_stats_linux_test.go b/cmd/nerdctl/container_stats_linux_test.go index 738bb855551..4b6fcd14bdc 100644 --- a/cmd/nerdctl/container_stats_linux_test.go +++ b/cmd/nerdctl/container_stats_linux_test.go @@ -39,7 +39,9 @@ func TestStats(t *testing.T) { defer base.Cmd("rm", "-f", exitedTestContainerName).Run() base.Cmd("run", "--name", exitedTestContainerName, testutil.AlpineImage, "echo", "'exited'").AssertOK() - base.Cmd("run", "-d", "--name", testContainerName, testutil.AlpineImage, "sleep", "5").AssertOK() + base.Cmd("run", "-d", "--name", testContainerName, testutil.AlpineImage, "sleep", "10").AssertOK() base.Cmd("stats", "--no-stream").AssertOutContains(testContainerName) base.Cmd("stats", "--no-stream", testContainerName).AssertOK() + base.Cmd("container", "stats", "--no-stream").AssertOutContains(testContainerName) + base.Cmd("container", "stats", "--no-stream", testContainerName).AssertOK() } From 868dfeafbe6ebd3853b2b1c474041c5a6ff32c69 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 30 Jul 2023 16:52:16 +0900 Subject: [PATCH 0048/1066] update containerd (1.7.3) Signed-off-by: Akihiro Suda --- .cirrus.yml | 3 +++ .github/workflows/test.yml | 18 +++++++++--------- Dockerfile | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index b35984c3058..34d94521831 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -30,6 +30,9 @@ windows_task: matrix: - name: "Windows/containerd-1.7" env: + # containerd >= 1.7.2 can't pass nerdctl CI: + # `hcsshim::PrepareLayer failed in Win32: The parameter is incorrect. (0x57)` + # https://github.com/containerd/containerd/issues/8891 ctrdVersion: 1.7.1 env: CGO_ENABLED: 0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a439188a227..7621d0c5cc6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,11 +77,11 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.21 + containerd: v1.6.22 - ubuntu: 20.04 - containerd: v1.7.1 + containerd: v1.7.3 - ubuntu: 22.04 - containerd: v1.7.1 + containerd: v1.7.3 - ubuntu: 22.04 containerd: main env: @@ -113,25 +113,25 @@ jobs: # ubuntu-22.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.21 + containerd: v1.6.22 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.1 + containerd: v1.7.3 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.1 + containerd: v1.7.3 target: test-integration-rootless - ubuntu: 22.04 containerd: main target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.6.21 + containerd: v1.6.22 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.1 + containerd: v1.7.3 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.1 + containerd: v1.7.3 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main diff --git a/Dockerfile b/Dockerfile index 80a0726e485..fe50d83a8fa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.1 +ARG CONTAINERD_VERSION=v1.7.3 ARG RUNC_VERSION=v1.1.7 ARG CNI_PLUGINS_VERSION=v1.3.0 From fb007a66c1bbb2f028fe2c924441c7af114c5dd3 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 30 Jul 2023 16:52:47 +0900 Subject: [PATCH 0049/1066] update runc (1.1.8) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index fe50d83a8fa..d01d9fa3378 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v1.7.3 -ARG RUNC_VERSION=v1.1.7 +ARG RUNC_VERSION=v1.1.8 ARG CNI_PLUGINS_VERSION=v1.3.0 # Extra deps: Build From 42e0e6c77e793822263b87a81e981510ba0a8716 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 30 Jul 2023 16:56:19 +0900 Subject: [PATCH 0050/1066] update kubo (0.21.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/kubo-v0.20.0 | 3 --- Dockerfile.d/SHA256SUMS.d/kubo-v0.21.0 | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/kubo-v0.20.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/kubo-v0.21.0 diff --git a/Dockerfile b/Dockerfile index d01d9fa3378..da51f3cd8f2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ ARG BYPASS4NETNS_VERSION=v0.3.0 ARG FUSE_OVERLAYFS_VERSION=v1.12 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.6 # Extra deps: IPFS -ARG KUBO_VERSION=v0.20.0 +ARG KUBO_VERSION=v0.21.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug diff --git a/Dockerfile.d/SHA256SUMS.d/kubo-v0.20.0 b/Dockerfile.d/SHA256SUMS.d/kubo-v0.20.0 deleted file mode 100644 index f98990e14a3..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/kubo-v0.20.0 +++ /dev/null @@ -1,3 +0,0 @@ -# From https://github.com/ipfs/kubo/releases -46f3f14d75640dfedb0ee79ccb87eefa30da5c00b0af2c30f02f13454f5ab072 kubo_v0.20.0_linux-amd64.tar.gz -a073d4e9eefd5f7c1ee24f2c9d0a8975591beea34c49d8fee4c0ea731393ef84 kubo_v0.20.0_linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/kubo-v0.21.0 b/Dockerfile.d/SHA256SUMS.d/kubo-v0.21.0 new file mode 100644 index 00000000000..b6beb01de7f --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/kubo-v0.21.0 @@ -0,0 +1,3 @@ +# From https://github.com/ipfs/kubo/releases +b1897919a4f6dd299d6c73dec8e4be98f986e4071eeffaefadf921f26e271c4e kubo_v0.21.0_linux-amd64.tar.gz +702af7aa5dc9117e9bc32b03d13bb872105b74d361f119ce15fdad689a4f1bce kubo_v0.21.0_linux-arm64.tar.gz From 059e53f141e59af685ae40016d2a0fc24ce7c17c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 30 Jul 2023 16:57:26 +0900 Subject: [PATCH 0051/1066] update gotestsum (1.10.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index da51f3cd8f2..ef8c59da94d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ ARG BUILDG_VERSION=v0.4.1 ARG GO_VERSION=1.20 ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 -ARG GOTESTSUM_VERSION=v1.10.0 +ARG GOTESTSUM_VERSION=v1.10.1 ARG NYDUS_VERSION=v2.2.1 ARG SOCI_SNAPSHOTTER_VERSION=0.3.0 From f128aea61fc352de26203bf7d1c89e3668c5cf23 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 30 Jul 2023 16:57:51 +0900 Subject: [PATCH 0052/1066] update Nydus (2.2.2) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ef8c59da94d..12c947a0c0b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,7 +48,7 @@ ARG GO_VERSION=1.20 ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.10.1 -ARG NYDUS_VERSION=v2.2.1 +ARG NYDUS_VERSION=v2.2.2 ARG SOCI_SNAPSHOTTER_VERSION=0.3.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.2.1 AS xx From 5793cca96aad2e0fb1f04eb34dc80b7599357031 Mon Sep 17 00:00:00 2001 From: Xuanxin Zhen Date: Sat, 29 Jul 2023 17:04:53 +0800 Subject: [PATCH 0053/1066] fix: registry missing layer when concurrently push image Signed-off-by: Xuanxin Zhen --- pkg/cmd/image/push.go | 21 +++++++++++++++++++-- pkg/imgutil/push/push.go | 5 ++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index c9029bf17d8..2290619bb41 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -30,6 +30,8 @@ import ( "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" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/errutil" "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" @@ -117,8 +119,15 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options logrus.Infof("pushing as an eStargz image (%s, %s)", esgzImg.Target.MediaType, esgzImg.Target.Digest) } + // In order to push images where most layers are the same but the + // repository name is different, it is necessary to refresh the + // PushTracker. Otherwise, the MANIFEST_BLOB_UNKNOWN error will occur due + // to the registry not creating the corresponding layer link file, + // resulting in the failure of the entire image push. + pushTracker := docker.NewInMemoryTracker() + pushFunc := func(r remotes.Resolver) error { - return push.Push(ctx, client, r, options.Stdout, pushRef, ref, platMC, options.AllowNondistributableArtifacts, options.Quiet) + return push.Push(ctx, client, r, pushTracker, options.Stdout, pushRef, ref, platMC, options.AllowNondistributableArtifacts, options.Quiet) } var dOpts []dockerconfigresolver.Opt @@ -127,10 +136,18 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) } dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(options.GOptions.HostsDir)) - resolver, err := dockerconfigresolver.New(ctx, refDomain, dOpts...) + + ho, err := dockerconfigresolver.NewHostOptions(ctx, refDomain, dOpts...) if err != nil { return err } + + resolverOpts := docker.ResolverOptions{ + Tracker: pushTracker, + Hosts: dockerconfig.ConfigureHosts(ctx, *ho), + } + + resolver := docker.NewResolver(resolverOpts) if err = pushFunc(resolver); err != nil { // In some circumstance (e.g. people just use 80 port to support pure http), the error will contain message like "dial tcp : connection refused" if !errutil.IsErrHTTPResponseToHTTPSClient(err) && !errutil.IsErrConnectionRefused(err) { diff --git a/pkg/imgutil/push/push.go b/pkg/imgutil/push/push.go index d16b4b613f7..2829fbdd244 100644 --- a/pkg/imgutil/push/push.go +++ b/pkg/imgutil/push/push.go @@ -32,7 +32,6 @@ import ( "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/pkg/imgutil/jobs" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -40,7 +39,7 @@ import ( ) // Push pushes an image to a remote registry. -func Push(ctx context.Context, client *containerd.Client, resolver remotes.Resolver, stdout io.Writer, +func Push(ctx context.Context, client *containerd.Client, resolver remotes.Resolver, pushTracker docker.StatusTracker, stdout io.Writer, localRef, remoteRef string, platform platforms.MatchComparer, allowNonDist, quiet bool) error { img, err := client.ImageService().Get(ctx, localRef) if err != nil { @@ -48,7 +47,7 @@ func Push(ctx context.Context, client *containerd.Client, resolver remotes.Resol } desc := img.Target - ongoing := newPushJobs(dockerconfigresolver.PushTracker) + ongoing := newPushJobs(pushTracker) eg, ctx := errgroup.WithContext(ctx) From f57cb2419a9940e99c37e0c87ccae1b3b6def914 Mon Sep 17 00:00:00 2001 From: Gabriel Adrian Samfira Date: Tue, 1 Aug 2023 12:46:04 +0300 Subject: [PATCH 0054/1066] Add lease to prevent containerd GC Without adding a lease, the containerd GC will remove the view we just created, while we're attempting to use it, leading to the Mount() function erring out. The lease ensures that the view will not be reaped prematurely. Signed-off-by: Gabriel Adrian Samfira --- pkg/cmd/container/run_mount.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index 3051818c9a5..30a3508c09e 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -25,10 +25,12 @@ import ( "runtime" "sort" "strings" + "time" "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" @@ -159,6 +161,14 @@ func generateMountOpts(ctx context.Context, client *containerd.Client, ensuredIm // When the Unmount fails, RemoveAll will incorrectly delete data from the mounted dir defer os.Remove(tempDir) + // Add a lease of 1 hour to the view so that it is not garbage collected + // Note(gsamfira): should we make this shorter? + ctx, done, err := client.WithLease(ctx, leases.WithRandomID(), leases.WithExpiration(1*time.Hour)) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to create lease: %w", err) + } + defer done(ctx) + var mounts []mount.Mount mounts, err = s.View(ctx, tempDir, chainID) if err != nil { From 7f5bca18ffe6d498761e92dd6f2e5f16bdaaa144 Mon Sep 17 00:00:00 2001 From: Gabriel Adrian Samfira Date: Tue, 1 Aug 2023 12:49:11 +0300 Subject: [PATCH 0055/1066] Remove special case for Windows when mounting view Signed-off-by: Gabriel Adrian Samfira --- pkg/cmd/container/run_mount.go | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index 30a3508c09e..4ebfb5b7d41 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -186,19 +186,7 @@ func generateMountOpts(ctx context.Context, client *containerd.Client, ensuredIm } } - if runtime.GOOS == "windows" { - for _, m := range mounts { - defer unmounter(m.Source) - // appending the layerID to the root. - mountPath := filepath.Join(tempDir, filepath.Base(m.Source)) - if err := m.Mount(mountPath); err != nil { - if err := s.Remove(ctx, tempDir); err != nil && !errdefs.IsNotFound(err) { - return nil, nil, nil, err - } - return nil, nil, nil, err - } - } - } else if runtime.GOOS == "linux" { + if runtime.GOOS == "linux" { defer unmounter(tempDir) for _, m := range mounts { m := m From 352962683d833b0033f62c0b0224eeaf8f805031 Mon Sep 17 00:00:00 2001 From: Gabriel Adrian Samfira Date: Tue, 1 Aug 2023 13:52:08 +0300 Subject: [PATCH 0056/1066] Bump containerd to 1.7.3 Signed-off-by: Gabriel Adrian Samfira --- .cirrus.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 34d94521831..07b00531be4 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -30,10 +30,7 @@ windows_task: matrix: - name: "Windows/containerd-1.7" env: - # containerd >= 1.7.2 can't pass nerdctl CI: - # `hcsshim::PrepareLayer failed in Win32: The parameter is incorrect. (0x57)` - # https://github.com/containerd/containerd/issues/8891 - ctrdVersion: 1.7.1 + ctrdVersion: 1.7.3 env: CGO_ENABLED: 0 build_script: From f0140a5c1b13b89bd046cab4a5dc60d161b765a6 Mon Sep 17 00:00:00 2001 From: "Hsing-Yu (David) Chen" Date: Mon, 12 Jun 2023 10:06:48 -0700 Subject: [PATCH 0057/1066] feat: add 'nerdctl container attach' Signed-off-by: Hsing-Yu (David) Chen --- cmd/nerdctl/container.go | 1 + cmd/nerdctl/container_attach.go | 92 ++++++++++++++ cmd/nerdctl/container_attach_linux_test.go | 103 ++++++++++++++++ cmd/nerdctl/container_start_linux_test.go | 8 +- cmd/nerdctl/main.go | 1 + docs/command-reference.md | 26 +++- pkg/api/types/container_types.go | 12 ++ pkg/cmd/container/attach.go | 137 +++++++++++++++++++++ pkg/testutil/testutil_linux.go | 23 +++- 9 files changed, 394 insertions(+), 9 deletions(-) create mode 100644 cmd/nerdctl/container_attach.go create mode 100644 cmd/nerdctl/container_attach_linux_test.go create mode 100644 pkg/cmd/container/attach.go diff --git a/cmd/nerdctl/container.go b/cmd/nerdctl/container.go index ba2781ef646..311b77d8799 100644 --- a/cmd/nerdctl/container.go +++ b/cmd/nerdctl/container.go @@ -50,6 +50,7 @@ func newContainerCommand() *cobra.Command { newRenameCommand(), newContainerPruneCommand(), newStatsCommand(), + newAttachCommand(), ) addCpCommand(containerCommand) return containerCommand diff --git a/cmd/nerdctl/container_attach.go b/cmd/nerdctl/container_attach.go new file mode 100644 index 00000000000..feb26f479f4 --- /dev/null +++ b/cmd/nerdctl/container_attach.go @@ -0,0 +1,92 @@ +/* + 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 ( + "github.com/containerd/containerd" + "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/pkg/clientutil" + "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/pkg/consoleutil" + "github.com/spf13/cobra" +) + +func newAttachCommand() *cobra.Command { + var attachCommand = &cobra.Command{ + Use: "attach [flags] CONTAINER", + Args: cobra.ExactArgs(1), + Short: `Attach stdin, stdout, and stderr to a running container. For example: + +1. 'nerdctl run -it --name test busybox' to start a container with a pty +2. 'ctrl-p ctrl-q' to detach from the container +3. 'nerdctl attach test' to attach to the container + +Caveats: + +- Currently only one attach session is allowed. When the second session tries to attach, currently no error will be returned from nerdctl. + However, since behind the scenes, there's only one FIFO for stdin, stdout, and stderr respectively, + if there are multiple sessions, all the sessions will be reading from and writing to the same 3 FIFOs, which will result in mixed input and partial output. +- Until dual logging (issue #1946) is implemented, + a container that is spun up by either 'nerdctl run -d' or 'nerdctl start' (without '--attach') cannot be attached to.`, + RunE: containerAttachAction, + ValidArgsFunction: attachShellComplete, + SilenceUsage: true, + SilenceErrors: true, + } + attachCommand.Flags().String("detach-keys", consoleutil.DefaultDetachKeys, "Override the default detach keys") + return attachCommand +} + +func processContainerAttachOptions(cmd *cobra.Command) (types.ContainerAttachOptions, error) { + globalOptions, err := processRootCmdFlags(cmd) + if err != nil { + return types.ContainerAttachOptions{}, err + } + detachKeys, err := cmd.Flags().GetString("detach-keys") + if err != nil { + return types.ContainerAttachOptions{}, err + } + return types.ContainerAttachOptions{ + GOptions: globalOptions, + Stdin: cmd.InOrStdin(), + Stdout: cmd.OutOrStdout(), + Stderr: cmd.ErrOrStderr(), + DetachKeys: detachKeys, + }, nil +} + +func containerAttachAction(cmd *cobra.Command, args []string) error { + options, err := processContainerAttachOptions(cmd) + if err != nil { + return err + } + + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), options.GOptions.Namespace, options.GOptions.Address) + if err != nil { + return err + } + defer cancel() + + return container.Attach(ctx, client, args[0], options) +} + +func attachShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + statusFilterFn := func(st containerd.ProcessStatus) bool { + return st == containerd.Running + } + return shellCompleteContainerNames(cmd, statusFilterFn) +} diff --git a/cmd/nerdctl/container_attach_linux_test.go b/cmd/nerdctl/container_attach_linux_test.go new file mode 100644 index 00000000000..c1ab1356cb0 --- /dev/null +++ b/cmd/nerdctl/container_attach_linux_test.go @@ -0,0 +1,103 @@ +/* + 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 ( + "bytes" + "strings" + "testing" + + "github.com/containerd/nerdctl/pkg/testutil" + "gotest.tools/v3/assert" +) + +// skipAttachForDocker should be called by attach-related tests that assert 'read detach keys' in stdout. +func skipAttachForDocker(t *testing.T) { + t.Helper() + if testutil.GetTarget() == testutil.Docker { + t.Skip("When detaching from a container, for a session started with 'docker attach'" + + ", it prints 'read escape sequence', but for one started with 'docker (run|start)', it prints nothing." + + " However, the flag is called '--detach-keys' in all cases" + + ", so nerdctl prints 'read detach keys' for all cases" + + ", and that's why this test is skipped for Docker.") + } +} + +// prepareContainerToAttach spins up a container (entrypoint = shell) with `-it` and detaches from it +// so that it can be re-attached to later. +func prepareContainerToAttach(base *testutil.Base, containerName string) { + opts := []func(*testutil.Cmd){ + testutil.WithStdin(testutil.NewDelayOnceReader(bytes.NewReader( + []byte{16, 17}, // ctrl+p,ctrl+q, see https://www.physics.udel.edu/~watson/scen103/ascii.html + ))), + } + // unbuffer(1) emulates tty, which is required by `nerdctl run -t`. + // unbuffer(1) can be installed with `apt-get install expect`. + // + // "-p" is needed because we need unbuffer to read from stdin, and from [1]: + // "Normally, unbuffer does not read from stdin. This simplifies use of unbuffer in some situations. + // To use unbuffer in a pipeline, use the -p flag." + // + // [1] https://linux.die.net/man/1/unbuffer + base.CmdWithHelper([]string{"unbuffer", "-p"}, "run", "-it", "--name", containerName, testutil.CommonImage). + CmdOption(opts...).AssertOutContains("read detach keys") + container := base.InspectContainer(containerName) + assert.Equal(base.T, container.State.Running, true) +} + +func TestAttach(t *testing.T) { + t.Parallel() + + skipAttachForDocker(t) + + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + + defer base.Cmd("container", "rm", "-f", containerName).AssertOK() + prepareContainerToAttach(base, containerName) + + opts := []func(*testutil.Cmd){ + testutil.WithStdin(testutil.NewDelayOnceReader(strings.NewReader("expr 1 + 1\nexit\n"))), + } + // `unbuffer -p` returns 0 even if the underlying nerdctl process returns a non-zero exit code, + // so the exit code cannot be easily tested here. + base.CmdWithHelper([]string{"unbuffer", "-p"}, "attach", containerName).CmdOption(opts...).AssertOutContains("2") + container := base.InspectContainer(containerName) + assert.Equal(base.T, container.State.Running, false) +} + +func TestAttachDetachKeys(t *testing.T) { + t.Parallel() + + skipAttachForDocker(t) + + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + + defer base.Cmd("container", "rm", "-f", containerName).AssertOK() + prepareContainerToAttach(base, containerName) + + opts := []func(*testutil.Cmd){ + testutil.WithStdin(testutil.NewDelayOnceReader(bytes.NewReader( + []byte{1, 2}, // https://www.physics.udel.edu/~watson/scen103/ascii.html + ))), + } + base.CmdWithHelper([]string{"unbuffer", "-p"}, "attach", "--detach-keys=ctrl-a,ctrl-b", containerName). + CmdOption(opts...).AssertOutContains("read detach keys") + container := base.InspectContainer(containerName) + assert.Equal(base.T, container.State.Running, true) +} diff --git a/cmd/nerdctl/container_start_linux_test.go b/cmd/nerdctl/container_start_linux_test.go index 13ddf477626..c83e310c40e 100644 --- a/cmd/nerdctl/container_start_linux_test.go +++ b/cmd/nerdctl/container_start_linux_test.go @@ -28,13 +28,7 @@ import ( func TestStartDetachKeys(t *testing.T) { t.Parallel() - if testutil.GetTarget() == testutil.Docker { - t.Skip("When detaching from a container, for a session started with 'docker attach'" + - ", it prints 'read escape sequence', but for one started with 'docker (run|start)', it prints nothing." + - " However, the flag is called '--detach-keys' in all cases" + - ", so nerdctl prints 'read detach keys' for all cases" + - ", and that's why this test is skipped for Docker.") - } + skipAttachForDocker(t) base := testutil.NewBase(t) containerName := testutil.Identifier(t) diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 6113790c8e0..35a087f26b2 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -259,6 +259,7 @@ Config file ($NERDCTL_TOML): %s newCommitCommand(), newWaitCommand(), newRenameCommand(), + newAttachCommand(), // #endregion // Build diff --git a/docs/command-reference.md b/docs/command-reference.md index f2c9d5c6a87..f12c81b3ef1 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -31,6 +31,7 @@ It does not necessarily mean that the corresponding features are missing in cont - [:whale: nerdctl pause](#whale-nerdctl-pause) - [:whale: nerdctl unpause](#whale-nerdctl-unpause) - [:whale: nerdctl rename](#whale-nerdctl-rename) + - [:whale: nerdctl attach](#whale-nerdctl-attach) - [:whale: nerdctl container prune](#whale-nerdctl-container-prune) - [Build](#build) - [:whale: nerdctl build](#whale-nerdctl-build) @@ -609,6 +610,30 @@ Rename a container. Usage: `nerdctl rename CONTAINER NEW_NAME` +### :whale: nerdctl attach + +Attach stdin, stdout, and stderr to a running container. For example: + +1. `nerdctl run -it --name test busybox` to start a container with a pty +2. `ctrl-p ctrl-q` to detach from the container +3. `nerdctl attach test` to attach to the container + +Caveats: + +- Currently only one attach session is allowed. When the second session tries to attach, currently no error will be returned from nerdctl. + However, since behind the scenes, there's only one FIFO for stdin, stdout, and stderr respectively, + if there are multiple sessions, all the sessions will be reading from and writing to the same 3 FIFOs, which will result in mixed input and partial output. +- Until dual logging (issue #1946) is implemented, + a container that is spun up by either `nerdctl run -d` or `nerdctl start` (without `--attach`) cannot be attached to. + +Usage: `nerdctl attach CONTAINER` + +Flags: + +- :whale: `--detach-keys`: Override the default detach keys + +Unimplemented `docker attach` flags: `--no-stdin`, `--sig-proxy` + ### :whale: nerdctl container prune Remove all stopped containers. @@ -1620,7 +1645,6 @@ See [`./config.md`](./config.md). Container management: -- `docker attach` - `docker diff` - `docker checkpoint *` diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index 2cd94b48169..f742d8f5443 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -370,6 +370,18 @@ type ContainerWaitOptions struct { GOptions GlobalCommandOptions } +// ContainerAttachOptions specifies options for `nerdctl (container) attach`. +type ContainerAttachOptions struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer + + // GOptions is the global options. + GOptions GlobalCommandOptions + // DetachKeys is the key sequences to detach from the container. + DetachKeys string +} + // ContainerExecOptions specifies options for `nerdctl (container) exec` type ContainerExecOptions struct { GOptions GlobalCommandOptions diff --git a/pkg/cmd/container/attach.go b/pkg/cmd/container/attach.go new file mode 100644 index 00000000000..a84cb8febfe --- /dev/null +++ b/pkg/cmd/container/attach.go @@ -0,0 +1,137 @@ +/* + 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 container + +import ( + "context" + "errors" + "fmt" + + "github.com/containerd/console" + "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" + "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/pkg/consoleutil" + "github.com/containerd/nerdctl/pkg/errutil" + "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/pkg/signalutil" + "github.com/sirupsen/logrus" +) + +// Attach attaches stdin, stdout, and stderr to a running container. +func Attach(ctx context.Context, client *containerd.Client, req string, options types.ContainerAttachOptions) error { + // Find the container. + var container containerd.Container + walker := &containerwalker.ContainerWalker{ + Client: client, + OnFound: func(ctx context.Context, found containerwalker.Found) error { + container = found.Container + return nil + }, + } + n, err := walker.Walk(ctx, req) + if err != nil { + return fmt.Errorf("error when trying to find the container: %w", err) + } + if n == 0 { + return fmt.Errorf("no container is found given the string: %s", req) + } else if n > 1 { + return fmt.Errorf("more than one containers are found given the string: %s", req) + } + + // Attach to the container. + var task containerd.Task + detachC := make(chan struct{}) + spec, err := container.Spec(ctx) + if err != nil { + return fmt.Errorf("failed to get the OCI runtime spec for the container: %w", err) + } + var ( + opt cio.Opt + con console.Console + ) + if spec.Process.Terminal { + con = console.Current() + defer con.Reset() + if err := con.SetRaw(); err != nil { + return fmt.Errorf("failed to set the console to raw mode: %w", err) + } + closer := func() { + detachC <- struct{}{} + // task will be set by container.Task later. + // + // We cannot use container.Task(ctx, cio.Load) to get the IO here + // because the `cancel` field of the returned `*cio` is nil. [1] + // + // [1] https://github.com/containerd/containerd/blob/8f756bc8c26465bd93e78d9cd42082b66f276e10/cio/io.go#L358-L359 + io := task.IO() + if io == nil { + logrus.Errorf("got a nil io") + return + } + io.Cancel() + } + in, err := consoleutil.NewDetachableStdin(con, options.DetachKeys, closer) + if err != nil { + return err + } + opt = cio.WithStreams(in, con, nil) + } else { + opt = cio.WithStreams(options.Stdin, options.Stdout, options.Stderr) + } + task, err = container.Task(ctx, cio.NewAttach(opt)) + if err != nil { + return fmt.Errorf("failed to attach to the container: %w", err) + } + if spec.Process.Terminal { + if err := consoleutil.HandleConsoleResize(ctx, task, con); err != nil { + logrus.WithError(err).Error("console resize") + } + } + sigC := signalutil.ForwardAllSignals(ctx, task) + defer signalutil.StopCatch(sigC) + + // Wait for the container to exit. + statusC, err := task.Wait(ctx) + if err != nil { + return fmt.Errorf("failed to init an async wait for the container to exit: %w", err) + } + select { + // io.Wait() would return when either 1) the user detaches from the container OR 2) the container is about to exit. + // + // If we replace the `select` block with io.Wait() and + // directly use task.Status() to check the status of the container after io.Wait() returns, + // it can still be running even though the container is about to exit (somehow especially for Windows). + // + // As a result, we need a separate detachC to distinguish from the 2 cases mentioned above. + case <-detachC: + io := task.IO() + if io == nil { + return errors.New("got a nil IO from the task") + } + io.Wait() + case status := <-statusC: + code, _, err := status.Result() + if err != nil { + return err + } + if code != 0 { + return errutil.NewExitCoderErr(int(code)) + } + } + return nil +} diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index 3fd65421c11..f74785eb74e 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -17,6 +17,7 @@ package testutil import ( + "errors" "fmt" "io" "sync" @@ -81,11 +82,31 @@ type delayOnceReader struct { // Since detaching from a container is only applicable when there is a TTY, // which usually means that there's a human in front of the computer waiting for a prompt to start typing, // it's reasonable to assume that the user will not type the detach keys before the task is started. +// +// Besides delaying the first Read() by one second, +// the returned reader also sleeps for one second if EOF is reached for the wrapped reader. +// The reason follows: +// +// NewDelayOnceReader is usually used with `unbuffer -p`, which has a caveat: +// "unbuffer simply exits when it encounters an EOF from either its input or process2." [1] +// The implication is if we use `unbuffer -p` to feed a command to container shell, +// `unbuffer -p` will exit right after it finishes reading the command (i.e., encounter an EOF from its input), +// and by that time, the container may have not executed the command and printed the wanted results to stdout, +// which would fail the test if it asserts stdout to contain certain strings. +// +// As a result, to avoid flaky tests, +// we give the container shell one second to process the command before `unbuffer -p` exits. +// +// [1] https://linux.die.net/man/1/unbuffer func NewDelayOnceReader(wrapped io.Reader) io.Reader { return &delayOnceReader{wrapped: wrapped} } func (r *delayOnceReader) Read(p []byte) (int, error) { r.once.Do(func() { time.Sleep(time.Second) }) - return r.wrapped.Read(p) + n, err := r.wrapped.Read(p) + if errors.Is(err, io.EOF) { + time.Sleep(time.Second) + } + return n, err } From be2ba3efffc7622106a6670642a3a1225fd27e03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 22:05:57 +0000 Subject: [PATCH 0058/1066] build(deps): bump golang.org/x/net from 0.12.0 to 0.13.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.12.0 to 0.13.0. - [Commits](https://github.com/golang/net/compare/v0.12.0...v0.13.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8d42f5b3b60..ae9a5cd0c50 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 golang.org/x/crypto v0.11.0 - golang.org/x/net v0.12.0 + golang.org/x/net v0.13.0 golang.org/x/sync v0.3.0 golang.org/x/sys v0.10.0 golang.org/x/term v0.10.0 diff --git a/go.sum b/go.sum index 17136551f2b..2b12b528d55 100644 --- a/go.sum +++ b/go.sum @@ -1190,8 +1190,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= +golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= From b8a8100ed1722e836634b3594e980a68bcf71af3 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 2 Aug 2023 15:50:39 +0900 Subject: [PATCH 0059/1066] .cirrus.yml: fix FreeBSD CI failure dougrabson/freebsd-minimal:13.1 seems removed Signed-off-by: Akihiro Suda --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 07b00531be4..d194e368a13 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -8,7 +8,7 @@ freebsd_task: cpu: 2 memory: 4G env: - NERDCTL_RUN_ARGS: --net none dougrabson/freebsd-minimal:13.1 echo "Nerdctl is up and running." + NERDCTL_RUN_ARGS: --net none dougrabson/freebsd-minimal:13 echo "Nerdctl is up and running." install_script: - pkg install -y go containerd runj test_script: From cf7b74289b04b5510d59b682ff6ccbe00134467f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 07:48:16 +0000 Subject: [PATCH 0060/1066] build(deps): bump github.com/coreos/go-iptables from 0.6.0 to 0.7.0 Bumps [github.com/coreos/go-iptables](https://github.com/coreos/go-iptables) from 0.6.0 to 0.7.0. - [Release notes](https://github.com/coreos/go-iptables/releases) - [Commits](https://github.com/coreos/go-iptables/compare/v0.6.0...v0.7.0) --- updated-dependencies: - dependency-name: github.com/coreos/go-iptables dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index ae9a5cd0c50..d35d628b2d3 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/containerd/typeurl/v2 v2.1.1 github.com/containernetworking/cni v1.1.2 github.com/containernetworking/plugins v1.3.0 - github.com/coreos/go-iptables v0.6.0 + github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.3 github.com/docker/cli v24.0.5+incompatible diff --git a/go.sum b/go.sum index 2b12b528d55..33157eecefa 100644 --- a/go.sum +++ b/go.sum @@ -318,8 +318,9 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk= github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= +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-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= From 65934e9261876e07d9437dc68fcdcaec5e87dcba Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 6 Aug 2023 02:00:08 +0900 Subject: [PATCH 0061/1066] test-integration-docker-compatibility: install Docker 20.10 The test suite is still not ready for Docker 23 (issue 2421) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7621d0c5cc6..dbe85e73c91 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -181,14 +181,27 @@ jobs: go-version: ${{ env.GO_VERSION }} cache: true check-latest: true - - name: "Enable BuildKit" + # Docker >= 23 is still unsupported: https://github.com/containerd/nerdctl/issues/2421 + - name: "Install Docker 20.10" run: | set -eux -o pipefail + # Uninstall the preinstalled Docker (Moby) + sudo apt-get remove moby-* + # Enable BuildKit explicitly sudo apt-get install -y moreutils cat /etc/docker/daemon.json jq '.features.buildkit = true' Date: Sat, 5 Aug 2023 23:31:57 +0900 Subject: [PATCH 0062/1066] CI: move FreeBSD tests to GHA Signed-off-by: Akihiro Suda --- .cirrus.yml | 20 ------------ .github/workflows/test.yml | 28 +++++++++++++++++ .gitignore | 1 + Vagrantfile.freebsd | 64 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 20 deletions(-) create mode 100644 Vagrantfile.freebsd diff --git a/.cirrus.yml b/.cirrus.yml index d194e368a13..e17426eecdc 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,23 +1,3 @@ -freebsd_task: - name: FreeBSD - timeout_in: 20m - compute_engine_instance: - image_project: freebsd-org-cloud-dev - image: family/freebsd-13-0 - platform: freebsd - cpu: 2 - memory: 4G - env: - NERDCTL_RUN_ARGS: --net none dougrabson/freebsd-minimal:13 echo "Nerdctl is up and running." - install_script: - - pkg install -y go containerd runj - test_script: - - daemon -o containerd.out containerd - - go test -v ./pkg/... - - cd cmd/nerdctl - - sudo go run . run $NERDCTL_RUN_ARGS | grep running -# TODO: run `go test -v ./cmd/...` - windows_task: name: "Windows" timeout_in: 20m diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dbe85e73c91..e6719d26f91 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -211,3 +211,31 @@ jobs: sudo apt-get install -y expect - name: "Ensure that the integration test suite is compatible with Docker" run: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon + + + test-integration-freebsd: + name: FreeBSD + # "Larger" runner is needed for nested virtualization + # https://github.com/organizations/containerd/settings/actions/runners + runs-on: ubuntu-latest-4-cores + timeout-minutes: 20 + + steps: + - uses: actions/checkout@v3.5.3 + - uses: actions/cache@v3 + with: + path: /root/.vagrant.d + key: vagrant-${{ matrix.box }} + - name: Set up vagrant + run: | + sudo apt-get update + sudo apt-get install -y libvirt-daemon libvirt-daemon-system vagrant vagrant-libvirt + sudo systemctl enable --now libvirtd + - name: Boot VM + run: | + ln -sf Vagrantfile.freebsd Vagrantfile + sudo vagrant up --no-tty + - name: test-unit + run: sudo vagrant up --provision-with=test-unit + - name: test-integration + run: sudo vagrant up --provision-with=test-integration diff --git a/.gitignore b/.gitignore index 646cd932d8f..9381e921112 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ _output # vagrant /.vagrant +Vagrantfile diff --git a/Vagrantfile.freebsd b/Vagrantfile.freebsd new file mode 100644 index 00000000000..08db3dddc4f --- /dev/null +++ b/Vagrantfile.freebsd @@ -0,0 +1,64 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# 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. + +# Vagrantfile for FreeBSD +Vagrant.configure("2") do |config| + config.vm.box = "generic/freebsd13" + + memory = 2048 + cpus = 1 + config.vm.provider :virtualbox do |v, o| + v.memory = memory + v.cpus = cpus + end + config.vm.provider :libvirt do |v| + v.memory = memory + v.cpus = cpus + end + + config.vm.synced_folder ".", "/vagrant", type: "rsync" + + config.vm.provision "install", type: "shell", run: "once" do |sh| + sh.inline = <<~SHELL + #!/usr/bin/env bash + set -eux -o pipefail + pkg install -y go containerd runj + cd /vagrant + go install ./cmd/nerdctl + SHELL + end + + config.vm.provision "test-unit", type: "shell", run: "never" do |sh| + sh.inline = <<~SHELL + #!/usr/bin/env bash + set -eux -o pipefail + cd /vagrant + go test -v ./pkg/... + SHELL + end + + config.vm.provision "test-integration", type: "shell", run: "never" do |sh| + sh.inline = <<~SHELL + #!/usr/bin/env bash + set -eux -o pipefail + daemon -o containerd.out containerd + sleep 3 + /root/go/bin/nerdctl run --rm --net=none dougrabson/freebsd-minimal:13 echo "Nerdctl is up and running." + SHELL + end + +end From 2888c388e82ad25b31b0caa97a8b08e5903867b7 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sat, 5 Aug 2023 21:10:15 +0900 Subject: [PATCH 0063/1066] CI: move Windows tests to GHA Signed-off-by: Akihiro Suda --- .cirrus.yml | 21 --------- .github/workflows/test.yml | 37 ++++++++++++++++ .../container_run_network_windows_test.go | 5 ++- cmd/nerdctl/container_run_windows_test.go | 2 + hack/configure-windows-ci.ps1 | 44 +------------------ pkg/testutil/testutil_windows.go | 13 ++++-- 6 files changed, 53 insertions(+), 69 deletions(-) delete mode 100644 .cirrus.yml diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index e17426eecdc..00000000000 --- a/.cirrus.yml +++ /dev/null @@ -1,21 +0,0 @@ -windows_task: - name: "Windows" - timeout_in: 20m - compute_engine_instance: - image_project: cirrus-images - image: family/windows-docker-builder - platform: windows - cpu: 2 - memory: 4G - matrix: - - name: "Windows/containerd-1.7" - env: - ctrdVersion: 1.7.3 - env: - CGO_ENABLED: 0 - build_script: - - mkdir "C:\Windows\system32\config\systemprofile\AppData\Local\Temp\" - - powershell hack/configure-windows-ci.ps1 - - refreshenv - - go install .\cmd\nerdctl\ - - go test -v ./cmd/... diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6719d26f91..b93bcb3bb99 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -212,6 +212,43 @@ jobs: - name: "Ensure that the integration test suite is compatible with Docker" run: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon + test-integration-windows: + runs-on: windows-2022 + timeout-minutes: 30 + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v3.5.3 + with: + fetch-depth: 1 + - uses: actions/setup-go@v4 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + check-latest: true + - run: go install ./cmd/nerdctl + - uses: actions/checkout@v3.5.3 + with: + repository: containerd/containerd + ref: v1.7.3 + path: containerd + fetch-depth: 1 + - name: "Set up CNI" + working-directory: containerd + run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows + - name: "Set up containerd" + env: + ctrdVersion: 1.7.3 + run: powershell hack/configure-windows-ci.ps1 + # TODO: Run unit tests + - name: "Run integration tests" + env: + # Hyper-V tests fail on GHA: + # > failed to get host processor information: failed to retrieve processor and processor topology information: + # > hcs::GetServiceProperties: Catastrophic failure: unknown + NO_HYPERV: 1 + run: go test -v ./cmd/... test-integration-freebsd: name: FreeBSD diff --git a/cmd/nerdctl/container_run_network_windows_test.go b/cmd/nerdctl/container_run_network_windows_test.go index 3ae5bcf2db3..914627607ec 100644 --- a/cmd/nerdctl/container_run_network_windows_test.go +++ b/cmd/nerdctl/container_run_network_windows_test.go @@ -51,9 +51,10 @@ func TestRunInternetConnectivity(t *testing.T) { args := []string{"run", "--rm"} args = append(args, tc.args...) // TODO(aznashwan): smarter way to ensure internet connectivity is working. - args = append(args, testutil.CommonImage, "ping github.com") + // ping doesn't seem to work on GitHub Actions ("Request timed out.") + args = append(args, testutil.CommonImage, "curl.exe -sSL https://github.com") cmd := base.Cmd(args...) - cmd.AssertOutContains("Reply from") + cmd.AssertOutContains("") }) } } diff --git a/cmd/nerdctl/container_run_windows_test.go b/cmd/nerdctl/container_run_windows_test.go index 74bc189925e..84cfa25294e 100644 --- a/cmd/nerdctl/container_run_windows_test.go +++ b/cmd/nerdctl/container_run_windows_test.go @@ -17,6 +17,7 @@ package main import ( + "bytes" "os/exec" "strings" "testing" @@ -32,6 +33,7 @@ func TestRunHostProcessContainer(t *testing.T) { if err != nil { t.Fatalf("unable to get hostname: %s", err) } + hostname = bytes.TrimSpace(hostname) base.Cmd("run", "--rm", "--isolation=host", testutil.WindowsNano, "hostname").AssertOutContains(string(hostname)) output := base.Cmd("run", "--rm", "--isolation=host", testutil.WindowsNano, "whoami").Out() diff --git a/hack/configure-windows-ci.ps1 b/hack/configure-windows-ci.ps1 index f9d58e4e7e9..1c97a487182 100644 --- a/hack/configure-windows-ci.ps1 +++ b/hack/configure-windows-ci.ps1 @@ -1,12 +1,6 @@ -$ErrorActionPreference = "Stop" - -#install build dependencies -choco install --limitoutput --no-progress -y git golang +# To install CNI, see https://github.com/containerd/containerd/blob/release/1.7/script/setup/install-cni-windows -#cleanup containerd -echo "Stopping containerd" -Stop-Service containerd -sc.exe delete containerd +$ErrorActionPreference = "Stop" #install containerd $version=$env:ctrdVersion @@ -20,40 +14,6 @@ cp ./bin/* "$Env:ProgramFiles\containerd" & $Env:ProgramFiles\containerd\containerd.exe --register-service Start-Service containerd -#configure cni -mkdir -force "$Env:ProgramFiles\containerd\cni\bin" -mkdir -force "$Env:ProgramFiles\containerd\cni\conf" -curl.exe -LO https://github.com/microsoft/windows-container-networking/releases/download/v0.2.0/windows-container-networking-cni-amd64-v0.2.0.zip -Expand-Archive windows-container-networking-cni-amd64-v0.2.0.zip -DestinationPath "$Env:ProgramFiles\containerd\cni\bin" -Force - -curl.exe -LO https://raw.githubusercontent.com/microsoft/SDN/master/Kubernetes/windows/hns.psm1 -ipmo ./hns.psm1 - -# cirrus already has nat net work configured for docker. We can re-use that for testing -$sn=(get-hnsnetwork | ? Name -Like "nat" | select -ExpandProperty subnets) -$subnet=$sn.AddressPrefix -$gateway=$sn.GatewayAddress -@" -{ - "cniVersion": "0.2.0", - "name": "nat", - "type": "nat", - "master": "Ethernet", - "ipam": { - "subnet": "$subnet", - "routes": [ - { - "gateway": "$gateway" - } - ] - }, - "capabilities": { - "portMappings": true, - "dns": true - } -} -"@ | Set-Content "$Env:ProgramFiles\containerd\cni\conf\0-containerd-nat.conf" -Force - echo "configuration complete! Printing configuration..." echo "Service:" get-service containerd diff --git a/pkg/testutil/testutil_windows.go b/pkg/testutil/testutil_windows.go index 1f23cc78301..5d4de6d24e5 100644 --- a/pkg/testutil/testutil_windows.go +++ b/pkg/testutil/testutil_windows.go @@ -17,14 +17,14 @@ package testutil import ( - "sync" - + "os" + "strconv" "strings" - - "golang.org/x/sys/windows/svc/mgr" + "sync" "github.com/Microsoft/hcsshim" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "golang.org/x/sys/windows/svc/mgr" ) const ( @@ -60,6 +60,11 @@ var ( // HyperVSupported is a test helper to check if hyperv is enabled on // the host. This can be used to skip tests that require virtualization. func HyperVSupported() bool { + if s := os.Getenv("NO_HYPERV"); s != "" { + if b, err := strconv.ParseBool(s); err == nil && b { + return false + } + } hypervSupportedOnce.Do(func() { // Hyper-V Virtual Machine Management service name const hypervServiceName = "vmms" From dd60cfe67244d266a8b1faf1c616c73b7b9f4b20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Aug 2023 13:10:57 +0000 Subject: [PATCH 0064/1066] build(deps): bump golang.org/x/crypto from 0.11.0 to 0.12.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.11.0 to 0.12.0. - [Commits](https://github.com/golang/crypto/compare/v0.11.0...v0.12.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index d35d628b2d3..2ed26b20b66 100644 --- a/go.mod +++ b/go.mod @@ -52,12 +52,12 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 - golang.org/x/crypto v0.11.0 + golang.org/x/crypto v0.12.0 golang.org/x/net v0.13.0 golang.org/x/sync v0.3.0 - golang.org/x/sys v0.10.0 - golang.org/x/term v0.10.0 - golang.org/x/text v0.11.0 + golang.org/x/sys v0.11.0 + golang.org/x/term v0.11.0 + golang.org/x/text v0.12.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.0 ) diff --git a/go.sum b/go.sum index 33157eecefa..d2e3c53297e 100644 --- a/go.sum +++ b/go.sum @@ -1094,8 +1094,8 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1323,14 +1323,14 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1340,8 +1340,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 3df165d04ce5541807a1c1c242b2dfa11b38fbff Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Mon, 7 Aug 2023 17:33:28 +0000 Subject: [PATCH 0065/1066] fix attach help is messed up Signed-off-by: Kay Yan --- cmd/nerdctl/container_attach.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cmd/nerdctl/container_attach.go b/cmd/nerdctl/container_attach.go index feb26f479f4..8a18be23918 100644 --- a/cmd/nerdctl/container_attach.go +++ b/cmd/nerdctl/container_attach.go @@ -26,10 +26,8 @@ import ( ) func newAttachCommand() *cobra.Command { - var attachCommand = &cobra.Command{ - Use: "attach [flags] CONTAINER", - Args: cobra.ExactArgs(1), - Short: `Attach stdin, stdout, and stderr to a running container. For example: + const shortHelp = "Attach stdin, stdout, and stderr to a running container." + const longHelp = `Attach stdin, stdout, and stderr to a running container. For example: 1. 'nerdctl run -it --name test busybox' to start a container with a pty 2. 'ctrl-p ctrl-q' to detach from the container @@ -41,7 +39,13 @@ Caveats: However, since behind the scenes, there's only one FIFO for stdin, stdout, and stderr respectively, if there are multiple sessions, all the sessions will be reading from and writing to the same 3 FIFOs, which will result in mixed input and partial output. - Until dual logging (issue #1946) is implemented, - a container that is spun up by either 'nerdctl run -d' or 'nerdctl start' (without '--attach') cannot be attached to.`, + a container that is spun up by either 'nerdctl run -d' or 'nerdctl start' (without '--attach') cannot be attached to.` + + var attachCommand = &cobra.Command{ + Use: "attach [flags] CONTAINER", + Args: cobra.ExactArgs(1), + Short: shortHelp, + Long: longHelp, RunE: containerAttachAction, ValidArgsFunction: attachShellComplete, SilenceUsage: true, From 569fe4e3da72f97a887beacbed911c074f507bb5 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 7 Aug 2023 21:20:18 +0900 Subject: [PATCH 0066/1066] CI: Windows: enable Hyper-V containers Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b93bcb3bb99..d26bd36d111 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -213,7 +213,8 @@ jobs: run: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon test-integration-windows: - runs-on: windows-2022 + # A "larger" runner is used for enabling Hyper-V containers + runs-on: windows-2022-8-cores timeout-minutes: 30 defaults: run: @@ -243,11 +244,6 @@ jobs: run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" - env: - # Hyper-V tests fail on GHA: - # > failed to get host processor information: failed to retrieve processor and processor topology information: - # > hcs::GetServiceProperties: Catastrophic failure: unknown - NO_HYPERV: 1 run: go test -v ./cmd/... test-integration-freebsd: From 0d631726b77ee80391b169f5788b87f30abcf175 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 22:17:43 +0000 Subject: [PATCH 0067/1066] build(deps): bump golang.org/x/net from 0.13.0 to 0.14.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.13.0 to 0.14.0. - [Commits](https://github.com/golang/net/compare/v0.13.0...v0.14.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2ed26b20b66..258472bf346 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 golang.org/x/crypto v0.12.0 - golang.org/x/net v0.13.0 + golang.org/x/net v0.14.0 golang.org/x/sync v0.3.0 golang.org/x/sys v0.11.0 golang.org/x/term v0.11.0 diff --git a/go.sum b/go.sum index d2e3c53297e..77a4530d8ed 100644 --- a/go.sum +++ b/go.sum @@ -1191,8 +1191,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= From 424bf4ed3f64316700172b157f2e5b2dfd057afb Mon Sep 17 00:00:00 2001 From: Artem Khramov Date: Wed, 9 Aug 2023 06:03:38 +0300 Subject: [PATCH 0068/1066] FreeBSD: Linux Container Support and BuildKit Integration Adjusted documentation in docs/freebsd.md and extended runtime check in buildkitutil to encompass FreeBSD alongside Linux. Signed-off-by: Artem Khramov --- docs/freebsd.md | 17 ++++++++--------- pkg/buildkitutil/buildkitutil.go | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/freebsd.md b/docs/freebsd.md index aa7b404da9e..4ad17aedba3 100644 --- a/docs/freebsd.md +++ b/docs/freebsd.md @@ -14,10 +14,16 @@ instructions in the respective repositories. ## Usage -You can use the `knast/freebsd` image to run a standard FreeBSD 13 jail: +You can use the `dougrabson/freebsd13.2-small` image to run a FreeBSD 13 jail: ```sh -nerdctl run --net none -it knast/freebsd:13-STABLE +nerdctl run --net none -it dougrabson/freebsd13.2-small +``` + +Alternatively use `--platform` parameter to run linux containers + +```sh +nerdctl run --platform linux --net none -it amazonlinux:2 ``` @@ -25,10 +31,3 @@ nerdctl run --net none -it knast/freebsd:13-STABLE - :warning: CNI & CNI plugins are not yet ported to FreeBSD. The only supported network type is `none` -- :warning: buildkit is not yet ported to FreeBSD. - - [ ] https://github.com/tonistiigi/fsutil/pull/109 - buildkit dependency - - [ ] https://github.com/moby/moby/pull/42866 - buildkit dependency -- :warning: Linuxulator containers support is - WIP. https://github.com/containerd/nerdctl/issues/280 https://github.com/containerd/containerd/pull/5480 - -- :bug: `nerdctl compose` commands currently don't work. https://github.com/containerd/containerd/pull/5991 diff --git a/pkg/buildkitutil/buildkitutil.go b/pkg/buildkitutil/buildkitutil.go index 7a5ac2fd02f..9522cb69a59 100644 --- a/pkg/buildkitutil/buildkitutil.go +++ b/pkg/buildkitutil/buildkitutil.go @@ -144,8 +144,8 @@ func PingBKDaemon(buildkitHost string) error { } func pingBKDaemon(buildkitHost string) (output string, _ error) { - if runtime.GOOS != "linux" { - return "", errors.New("only linux is supported") + if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" { + return "", errors.New("only linux and freebsd are supported") } buildctlBinary, err := BuildctlBinary() if err != nil { From ac0146f9f4aadd2d7c4b81bf48d81bcc339c5ed9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Aug 2023 22:04:04 +0000 Subject: [PATCH 0069/1066] build(deps): bump github.com/fahedouch/go-logrotate from 0.1.3 to 0.2.0 Bumps [github.com/fahedouch/go-logrotate](https://github.com/fahedouch/go-logrotate) from 0.1.3 to 0.2.0. - [Release notes](https://github.com/fahedouch/go-logrotate/releases) - [Commits](https://github.com/fahedouch/go-logrotate/compare/v0.1.3...v0.2.0) --- updated-dependencies: - dependency-name: github.com/fahedouch/go-logrotate dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 258472bf346..dcf49f61b61 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/docker/docker v24.0.5+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.5.0 - github.com/fahedouch/go-logrotate v0.1.3 + github.com/fahedouch/go-logrotate v0.2.0 github.com/fatih/color v1.15.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/hashicorp/go-multierror v1.1.1 diff --git a/go.sum b/go.sum index 77a4530d8ed..3c254b4245f 100644 --- a/go.sum +++ b/go.sum @@ -63,8 +63,8 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 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= @@ -401,8 +401,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go. github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fahedouch/go-logrotate v0.1.3 h1:V5VGDXfKjzjuISflMsxJqKsHggpZE/7iNyxfyNlu5A8= -github.com/fahedouch/go-logrotate v0.1.3/go.mod h1:S8a52JNmJe9t7XdO5Y3NZ36Va3HcVQrI/HBJLpvnc9w= +github.com/fahedouch/go-logrotate v0.2.0 h1:UR9Fv8MDVfWwnkirmFHck+tRSWzqOwRjVRLMpQgSxaI= +github.com/fahedouch/go-logrotate v0.2.0/go.mod h1:1RL/yr7LntS4zadAC6FT6yB/C1CQt3V6eHAZzymfwzE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= From 56b0a7cbb8f592849ceb468e95e5a11378161447 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Thu, 10 Aug 2023 14:52:06 +0000 Subject: [PATCH 0070/1066] Update to Go 1.21 in CI Signed-off-by: Austin Vazquez --- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 6 +++--- Dockerfile | 2 +- go.mod | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 52dd9a4f91a..668139d622e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v3.5.3 - uses: actions/setup-go@v4 with: - go-version: 1.20.x + go-version: 1.21.x - name: "Compile binaries" run: make artifacts - name: "SHA256SUMS" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d26bd36d111..badf87f1d18 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ on: pull_request: env: - GO_VERSION: 1.20.x + GO_VERSION: 1.21.x jobs: project: @@ -48,7 +48,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v3.6.0 with: - version: v1.53.3 + version: v1.54.0 args: --verbose - name: yamllint-lint run: yamllint . @@ -156,7 +156,7 @@ jobs: timeout-minutes: 40 strategy: matrix: - go-version: ["1.19.x", "1.20.x"] + go-version: ["1.20.x", "1.21.x"] steps: - uses: actions/checkout@v3.5.3 with: diff --git a/Dockerfile b/Dockerfile index 12c947a0c0b..0304e414447 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,7 +44,7 @@ ARG TINI_VERSION=v0.19.0 ARG BUILDG_VERSION=v0.4.1 # Test deps -ARG GO_VERSION=1.20 +ARG GO_VERSION=1.21 ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.10.1 diff --git a/go.mod b/go.mod index dcf49f61b61..2362797043e 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/containerd/nerdctl -go 1.19 +go 1.20 require ( github.com/Masterminds/semver/v3 v3.2.1 From 3bc8f05bf905f59a52362ba7872a01d2b5db9c66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 22:56:16 +0000 Subject: [PATCH 0071/1066] build(deps): bump github.com/tidwall/gjson from 1.15.0 to 1.16.0 Bumps [github.com/tidwall/gjson](https://github.com/tidwall/gjson) from 1.15.0 to 1.16.0. - [Commits](https://github.com/tidwall/gjson/compare/v1.15.0...v1.16.0) --- updated-dependencies: - dependency-name: github.com/tidwall/gjson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dcf49f61b61..380837a9b4a 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/tidwall/gjson v1.15.0 + github.com/tidwall/gjson v1.16.0 github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 diff --git a/go.sum b/go.sum index 3c254b4245f..56b1830d743 100644 --- a/go.sum +++ b/go.sum @@ -966,8 +966,8 @@ github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tidwall/gjson v1.15.0 h1:5n/pM+v3r5ujuNl4YLZLsQ+UE5jlkLVm7jMzT5Mpolw= -github.com/tidwall/gjson v1.15.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg= +github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= From b98ce6a621e3aba0c68dfc0af648d092b4767308 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 22:56:25 +0000 Subject: [PATCH 0072/1066] build(deps): bump github.com/compose-spec/compose-go Bumps [github.com/compose-spec/compose-go](https://github.com/compose-spec/compose-go) from 1.17.0 to 1.18.1. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v1.17.0...v1.18.1) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dcf49f61b61..ab65971b53b 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.10.0 github.com/awslabs/soci-snapshotter v0.3.0 - github.com/compose-spec/compose-go v1.17.0 + github.com/compose-spec/compose-go v1.18.1 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 diff --git a/go.sum b/go.sum index 3c254b4245f..53a65d06a49 100644 --- a/go.sum +++ b/go.sum @@ -173,8 +173,8 @@ github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:z github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/compose-spec/compose-go v1.17.0 h1:cvje90CU94dQyTnJoHJYjx9yE4Iggse1XmGcO3Qi5ts= -github.com/compose-spec/compose-go v1.17.0/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= +github.com/compose-spec/compose-go v1.18.1 h1:YVYYkV8fAHW/eCOgtqSe1tHrlaDVvwS8zgs6F5ukm/Y= +github.com/compose-spec/compose-go v1.18.1/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= github.com/containerd/accelerated-container-image v0.6.7 h1:QDO12lgUubiUq0ogMzcL6CdSxkzFOX7vVaSIXAJ9EaM= github.com/containerd/accelerated-container-image v0.6.7/go.mod h1:a7MYTlNhR4+GGpXD7wuNSgxrwC2wE2rgUfCvef+FQzg= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= From 5130ccbfd088e802992ae7da2fbc2ab502f89c6f Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 11 Aug 2023 22:34:24 +0900 Subject: [PATCH 0073/1066] Remove dependency on github.com/hashicorp/go-multierror Signed-off-by: Akihiro Suda --- go.mod | 2 -- go.sum | 2 -- pkg/buildkitutil/buildkitutil.go | 3 +-- pkg/cmd/container/wait.go | 4 ++-- pkg/ipfs/registry.go | 3 +-- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index cfa9a8bf64c..4c1188dff3c 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,6 @@ require ( github.com/fahedouch/go-logrotate v0.2.0 github.com/fatih/color v1.15.0 github.com/fluent/fluent-logger-golang v1.9.0 - github.com/hashicorp/go-multierror v1.1.1 github.com/ipfs/go-cid v0.4.1 github.com/mattn/go-isatty v0.0.19 github.com/mitchellh/mapstructure v1.5.0 @@ -86,7 +85,6 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.16.7 diff --git a/go.sum b/go.sum index 92ce802d09f..22daefd37a7 100644 --- a/go.sum +++ b/go.sum @@ -581,14 +581,12 @@ github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBt github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 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= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= diff --git a/pkg/buildkitutil/buildkitutil.go b/pkg/buildkitutil/buildkitutil.go index 9522cb69a59..4f54c2675e6 100644 --- a/pkg/buildkitutil/buildkitutil.go +++ b/pkg/buildkitutil/buildkitutil.go @@ -36,7 +36,6 @@ import ( "runtime" "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/hashicorp/go-multierror" "github.com/sirupsen/logrus" ) @@ -84,7 +83,7 @@ func GetBuildkitHost(namespace string) (string, error) { logrus.Debugf("Chosen buildkit host %q", buildkitHost) return buildkitHost, nil } - allErr = multierror.Append(allErr, fmt.Errorf("failed to ping to host %s: %w", buildkitHost, err)) + allErr = errors.Join(allErr, fmt.Errorf("failed to ping to host %s: %w", buildkitHost, err)) } logrus.WithError(allErr).Error(getHint()) return "", fmt.Errorf("no buildkit host is available, tried %d candidates: %w", len(hostRel), allErr) diff --git a/pkg/cmd/container/wait.go b/pkg/cmd/container/wait.go index 4407e825b27..97e7706f6ee 100644 --- a/pkg/cmd/container/wait.go +++ b/pkg/cmd/container/wait.go @@ -18,13 +18,13 @@ package container import ( "context" + "errors" "fmt" "io" "github.com/containerd/containerd" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/hashicorp/go-multierror" ) // Wait blocks until all the containers specified by reqs have stopped, then print their exit codes. @@ -50,7 +50,7 @@ func Wait(ctx context.Context, client *containerd.Client, reqs []string, options w := options.Stdout for _, container := range containers { if waitErr := waitContainer(ctx, w, container); waitErr != nil { - allErr = multierror.Append(allErr, waitErr) + allErr = errors.Join(allErr, waitErr) } } return allErr diff --git a/pkg/ipfs/registry.go b/pkg/ipfs/registry.go index a80bfb8fdfa..6810b87ef37 100644 --- a/pkg/ipfs/registry.go +++ b/pkg/ipfs/registry.go @@ -32,7 +32,6 @@ import ( "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" ipfsclient "github.com/containerd/stargz-snapshotter/ipfs/client" - "github.com/hashicorp/go-multierror" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/sirupsen/logrus" @@ -238,7 +237,7 @@ func (s *server) resolveCIDOfDigest(ctx context.Context, dgst digest.Digest, des for _, desc := range descs { gotCID, gotDesc, err := s.resolveCIDOfDigest(ctx, dgst, desc) if err != nil { - allErr = multierror.Append(allErr, err) + allErr = errors.Join(allErr, err) continue } return gotCID, gotDesc, nil From 89bb5bc3cfe8bb675159a1022275b9a00a97f2e3 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 11 Aug 2023 22:39:06 +0900 Subject: [PATCH 0074/1066] update runc (1.1.9) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0304e414447..6328ca1c960 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v1.7.3 -ARG RUNC_VERSION=v1.1.8 +ARG RUNC_VERSION=v1.1.9 ARG CNI_PLUGINS_VERSION=v1.3.0 # Extra deps: Build From 42c312a801f969ce335e60c4618d53cd43e79533 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Fri, 11 Aug 2023 16:38:36 +0000 Subject: [PATCH 0075/1066] support volume create anonymous Signed-off-by: Kay Yan --- cmd/nerdctl/volume_create.go | 10 +++++++--- pkg/cmd/volume/create.go | 6 ++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume_create.go index 31cfa6a4214..9a10b46d326 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume_create.go @@ -25,9 +25,9 @@ import ( func newVolumeCreateCommand() *cobra.Command { volumeCreateCommand := &cobra.Command{ - Use: "create [flags] VOLUME", + Use: "create [flags] [VOLUME]", Short: "Create a volume", - Args: IsExactArgs(1), + Args: cobra.MaximumNArgs(1), RunE: volumeCreateAction, SilenceUsage: true, SilenceErrors: true, @@ -57,7 +57,11 @@ func volumeCreateAction(cmd *cobra.Command, args []string) error { if err != nil { return nil } - _, err = volume.Create(args[0], options) + volumeName := "" + if len(args) > 0 { + volumeName = args[0] + } + _, err = volume.Create(volumeName, options) return err } diff --git a/pkg/cmd/volume/create.go b/pkg/cmd/volume/create.go index 38610d55415..4726fc1ad66 100644 --- a/pkg/cmd/volume/create.go +++ b/pkg/cmd/volume/create.go @@ -22,10 +22,16 @@ import ( "github.com/containerd/containerd/identifiers" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/strutil" + "github.com/docker/docker/pkg/stringid" ) func Create(name string, options types.VolumeCreateOptions) (*native.Volume, error) { + if name == "" { + name = stringid.GenerateRandomID() + options.Labels = append(options.Labels, labels.AnonymousVolumes+"=") + } if err := identifiers.Validate(name); err != nil { return nil, fmt.Errorf("malformed name %s: %w", name, err) } From 0844a51e43df1c7c445c3142e7729069c06812bd Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Wed, 9 Aug 2023 14:35:12 +0000 Subject: [PATCH 0076/1066] support test integration docker 23 compatibility Signed-off-by: Kay Yan --- .github/workflows/test.yml | 15 ++------------- cmd/nerdctl/builder_build_test.go | 4 ---- cmd/nerdctl/compose_up_test.go | 2 +- cmd/nerdctl/system_prune_linux_test.go | 6 +++++- cmd/nerdctl/volume_prune.go | 7 +++++++ cmd/nerdctl/volume_prune_linux_test.go | 8 +++++--- pkg/api/types/volume_types.go | 2 ++ pkg/cmd/system/prune.go | 1 + pkg/cmd/volume/prune.go | 8 ++++++++ 9 files changed, 31 insertions(+), 22 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index badf87f1d18..534986876dd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -181,26 +181,15 @@ jobs: go-version: ${{ env.GO_VERSION }} cache: true check-latest: true - # Docker >= 23 is still unsupported: https://github.com/containerd/nerdctl/issues/2421 - - name: "Install Docker 20.10" + - name: "Enable BuildKit" run: | set -eux -o pipefail - # Uninstall the preinstalled Docker (Moby) - sudo apt-get remove moby-* # Enable BuildKit explicitly sudo apt-get install -y moreutils cat /etc/docker/daemon.json jq '.features.buildkit = true' Date: Tue, 15 Aug 2023 22:57:48 +0000 Subject: [PATCH 0077/1066] build(deps): bump golangci/golangci-lint-action from 3.6.0 to 3.7.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.6.0 to 3.7.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3.6.0...v3.7.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 534986876dd..a500e866607 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,7 +46,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v3.6.0 + uses: golangci/golangci-lint-action@v3.7.0 with: version: v1.54.0 args: --verbose From 6ed3118e5abea74bd7ab6fec2c7cf5b86c35cb5f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 22:31:07 +0000 Subject: [PATCH 0078/1066] build(deps): bump github.com/containerd/imgcrypt from 1.1.7 to 1.1.8 Bumps [github.com/containerd/imgcrypt](https://github.com/containerd/imgcrypt) from 1.1.7 to 1.1.8. - [Release notes](https://github.com/containerd/imgcrypt/releases) - [Changelog](https://github.com/containerd/imgcrypt/blob/main/CHANGES) - [Commits](https://github.com/containerd/imgcrypt/compare/v1.1.7...v1.1.8) --- updated-dependencies: - dependency-name: github.com/containerd/imgcrypt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: Akihiro Suda --- go.mod | 10 +- go.sum | 1205 +------------------------------------------------------- 2 files changed, 13 insertions(+), 1202 deletions(-) diff --git a/go.mod b/go.mod index 4c1188dff3c..b4c39c2defa 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/containerd/containerd v1.7.3 github.com/containerd/continuity v0.4.1 github.com/containerd/go-cni v1.1.9 - github.com/containerd/imgcrypt v1.1.7 + github.com/containerd/imgcrypt v1.1.8 github.com/containerd/nydus-snapshotter v0.10.0 github.com/containerd/stargz-snapshotter v0.14.3 github.com/containerd/stargz-snapshotter/estargz v0.14.3 @@ -61,22 +61,22 @@ require ( gotest.tools/v3 v3.5.0 ) -require golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect - require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/cilium/ebpf v0.9.1 // indirect github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/ttrpc v1.2.2 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect - github.com/containers/ocicrypt v1.1.7 // indirect + github.com/containers/ocicrypt v1.1.8 // indirect github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa // indirect 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 github.com/frankban/quicktest v1.14.2 // indirect + github.com/go-jose/go-jose/v3 v3.0.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect @@ -122,11 +122,11 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.15.1 // indirect go.opentelemetry.io/otel/trace v1.15.1 // indirect + golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect golang.org/x/mod v0.11.0 // indirect golang.org/x/tools v0.9.1 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.56.2 // indirect google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/square/go-jose.v2 v2.5.1 // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/go.sum b/go.sum index 22daefd37a7..947db77feae 100644 --- a/go.sum +++ b/go.sum @@ -1,504 +1,133 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 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.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= 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.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= -github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= -github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= -github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim v0.10.0 h1:PbvoxdUGgXxyirmN5Oncp3POLkxEG5LbWCEBfWmHTGA= github.com/Microsoft/hcsshim v0.10.0/go.mod h1:3j1trOamcUdi86J5Tr5+1BpqMjSv/QeRWkX2whBF6dY= -github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= -github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= -github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/awslabs/soci-snapshotter v0.3.0 h1:DcVedf88R8GO77WhJn/dusQqzCrjrh1RWBataW6pVV8= github.com/awslabs/soci-snapshotter v0.3.0/go.mod h1:s3cGc7hKDMefFbTf4YGzxRC9Q9nm2E/IU+65ExdRbvA= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/compose-spec/compose-go v1.18.1 h1:YVYYkV8fAHW/eCOgtqSe1tHrlaDVvwS8zgs6F5ukm/Y= github.com/compose-spec/compose-go v1.18.1/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= github.com/containerd/accelerated-container-image v0.6.7 h1:QDO12lgUubiUq0ogMzcL6CdSxkzFOX7vVaSIXAJ9EaM= github.com/containerd/accelerated-container-image v0.6.7/go.mod h1:a7MYTlNhR4+GGpXD7wuNSgxrwC2wE2rgUfCvef+FQzg= -github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= -github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= -github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= -github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= -github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= -github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= -github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= -github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= -github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0= github.com/containerd/containerd v1.7.3 h1:cKwYKkP1eTj54bP3wCdXXBymmKRQMrWjkLSWZZJDa8o= github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= github.com/containerd/continuity v0.4.1 h1:wQnVrjIyQ8vhU2sgOiL5T07jo+ouqc2bnKsv5/EqGhU= github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= 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.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= -github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= -github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= -github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= -github.com/containerd/go-cni v1.1.6/go.mod h1:BWtoWl5ghVymxu6MBjg79W9NZrCRyHIdUtk4cauMe34= github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9rU= github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= -github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= -github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= -github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= -github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= -github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4= -github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo= -github.com/containerd/imgcrypt v1.1.7 h1:WSf9o9EQ0KGHiUx2ESFZ+PKf4nxK9BcvV/nJDX8RkB4= -github.com/containerd/imgcrypt v1.1.7/go.mod h1:FD8gqIcX5aTotCtOmjeCsi3A1dHmTZpnMISGKSczt4k= -github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= -github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/imgcrypt v1.1.8 h1:ZS7TuywcRNLoHpU0g+v4/PsKynl6TYlw5xDVWWoIyFA= +github.com/containerd/imgcrypt v1.1.8/go.mod h1:x6QvFIkMyO2qGIY2zXc88ivEzcbgvLdWjoZyGqDap5U= github.com/containerd/nydus-snapshotter v0.10.0 h1:aCQoKmksOmZ2C34znlhOCOlYExiw4s/UPPzbIFKQc8U= github.com/containerd/nydus-snapshotter v0.10.0/go.mod h1:xEsAzeM0gZEW6POBPOa+1X7EThYsEJNWnO/fhf2moYU= github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= github.com/containerd/stargz-snapshotter v0.14.3/go.mod h1:j2Ya4JeA5gMZJr8BchSkPjlcCEh++auAxp4nidPI6N0= -github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/containerd/stargz-snapshotter/ipfs v0.14.3 h1:Y9jAdsjvZyG30dnEUvfMyV0FOnfs/pdEuYcxYMTDGSM= github.com/containerd/stargz-snapshotter/ipfs v0.14.3/go.mod h1:Y7oQmTVPao0mE8S6WqIKVTnd59FNW55Gy0r/RIGySew= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= -github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs= github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= -github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= -github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= 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= github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= -github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= -github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= -github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= -github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ= github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= -github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= -github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= -github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8= github.com/containernetworking/plugins v1.3.0 h1:QVNXMT6XloyMUoO2wUOqWTC1hWFV62Q6mVDp5H1HnjM= github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0= -github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= -github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= -github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/containers/ocicrypt v1.1.3/go.mod h1:xpdkbVAuaH3WzbEabUd5yDsl9SwJA5pABH85425Es2g= -github.com/containers/ocicrypt v1.1.6/go.mod h1:WgjxPWdTJMqYMjf3M6cuIFFA1/MpyyhIM99YInA+Rvc= -github.com/containers/ocicrypt v1.1.7 h1:thhNr4fu2ltyGz8aMx8u48Ae0Pnbip3ePP9/mzkZ/3U= -github.com/containers/ocicrypt v1.1.7/go.mod h1:7CAhjcj2H8AYp5YvEie7oVSK2AhBY8NscCYRawuDNtw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= +github.com/containers/ocicrypt v1.1.8 h1:saSBF0/8DyPUjzcxMVzL2OBUWCkvRvqIm75pu0ADSZk= +github.com/containers/ocicrypt v1.1.8/go.mod h1:jM362hyBtbwLMWzXQZTlkjKGAQf/BN/LFMtH0FIRt34= 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-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= -github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= -github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= -github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= 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/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa h1:L9Ay/slwQ4ERSPaurC+TVkZrM0K98GNrEEo1En3e8as= github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= 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/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fahedouch/go-logrotate v0.2.0 h1:UR9Fv8MDVfWwnkirmFHck+tRSWzqOwRjVRLMpQgSxaI= github.com/fahedouch/go-logrotate v0.2.0/go.mod h1:1RL/yr7LntS4zadAC6FT6yB/C1CQt3V6eHAZzymfwzE= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns= github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= +github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -508,235 +137,79 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= -github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= -github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0= github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0= -github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= 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.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= 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/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= 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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= @@ -749,209 +222,64 @@ github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= -github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= -github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 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.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= -github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk= github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/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= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rootless-containers/bypass4netns v0.3.0 h1:UwI55zWDZz7OGyN4YWgfCKdsI58VGY7OlghcLdxJX10= github.com/rootless-containers/bypass4netns v0.3.0/go.mod h1:IXHPjkQlJRygNBCN0hSSR3ITX6kDKr3aAaGHx6APd+g= github.com/rootless-containers/rootlesskit v1.1.1 h1:F5psKWoWY9/VjZ3ifVcaosjvFZJOagX85U22M0/EQZE= github.com/rootless-containers/rootlesskit v1.1.1/go.mod h1:UD5GoA3dqKCJrnvnhVgQQnweMF2qZnf9KLw8EewcMZI= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 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/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= 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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 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= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -959,11 +287,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg= github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -972,348 +295,92 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= -github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= -github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuchanns/srslog v1.1.0 h1:CEm97Xxxd8XpJThE0gc/XsqUGgPufh5u5MUjC27/KOk= github.com/yuchanns/srslog v1.1.0/go.mod h1:HsLjdv3XV02C3kgBW2bTyW6i88OQE+VYJZIxrPKPPak= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= 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 v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= go.opentelemetry.io/otel v1.15.1 h1:3Iwq3lfRByPaws0f6bU3naAqOR1n5IeDWd9390kWHa8= go.opentelemetry.io/otel v1.15.1/go.mod h1:mHHGEHVDLal6YrKMmk9LqC4a3sF5g+fHfrttQIB1NTc= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= go.opentelemetry.io/otel/trace v1.15.1 h1:uXLo6iHJEzDfrNC0L0mNjItIp06SyaBQxu5t3xMlngY= go.opentelemetry.io/otel/trace v1.15.1/go.mod h1:IWdQG/5N1x7f6YUlmdLeJvH9yxtuJAfc4VW5Agv9r/8= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= 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/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1323,212 +390,44 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1539,117 +438,29 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= -k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= -k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U= -k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= -k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ= -k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= -k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= -k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= -k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= -k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= -k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI= -k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= -k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= -k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= From 9129503367fdfdbc617e32d499193a93fb20da74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Aug 2023 22:45:51 +0000 Subject: [PATCH 0079/1066] build(deps): bump github.com/compose-spec/compose-go Bumps [github.com/compose-spec/compose-go](https://github.com/compose-spec/compose-go) from 1.18.1 to 1.18.2. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v1.18.1...v1.18.2) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b4c39c2defa..d914980e3e8 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.10.0 github.com/awslabs/soci-snapshotter v0.3.0 - github.com/compose-spec/compose-go v1.18.1 + github.com/compose-spec/compose-go v1.18.2 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 diff --git a/go.sum b/go.sum index 947db77feae..60de496e36e 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go v1.18.1 h1:YVYYkV8fAHW/eCOgtqSe1tHrlaDVvwS8zgs6F5ukm/Y= -github.com/compose-spec/compose-go v1.18.1/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= +github.com/compose-spec/compose-go v1.18.2 h1:ZxiSvB9K4coRs39wgGeWOwfjgziOpOQT+etJ4MB3PRA= +github.com/compose-spec/compose-go v1.18.2/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= github.com/containerd/accelerated-container-image v0.6.7 h1:QDO12lgUubiUq0ogMzcL6CdSxkzFOX7vVaSIXAJ9EaM= github.com/containerd/accelerated-container-image v0.6.7/go.mod h1:a7MYTlNhR4+GGpXD7wuNSgxrwC2wE2rgUfCvef+FQzg= github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= From 1e5baaafd696d399b4073f13293d3ace45219029 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sat, 19 Aug 2023 19:13:19 +0900 Subject: [PATCH 0080/1066] Fix usage of `errors.Join` Signed-off-by: Akihiro Suda --- pkg/buildkitutil/buildkitutil.go | 5 +++-- pkg/cmd/container/wait.go | 6 +++--- pkg/ipfs/registry.go | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pkg/buildkitutil/buildkitutil.go b/pkg/buildkitutil/buildkitutil.go index 4f54c2675e6..113bac0f64b 100644 --- a/pkg/buildkitutil/buildkitutil.go +++ b/pkg/buildkitutil/buildkitutil.go @@ -74,7 +74,7 @@ func GetBuildkitHost(namespace string) (string, error) { hostRel = append(hostRel, fmt.Sprintf("buildkit-%s/buildkitd.sock", namespace)) } hostRel = append(hostRel, "buildkit-default/buildkitd.sock", "buildkit/buildkitd.sock") - var allErr error + var errs []error //nolint:prealloc for _, p := range hostRel { logrus.Debugf("Choosing the buildkit host %q, candidates=%v (in %q)", p, hostRel, run) buildkitHost := "unix://" + filepath.Join(run, p) @@ -83,8 +83,9 @@ func GetBuildkitHost(namespace string) (string, error) { logrus.Debugf("Chosen buildkit host %q", buildkitHost) return buildkitHost, nil } - allErr = errors.Join(allErr, fmt.Errorf("failed to ping to host %s: %w", buildkitHost, err)) + errs = append(errs, fmt.Errorf("failed to ping to host %s: %w", buildkitHost, err)) } + allErr := errors.Join(errs...) logrus.WithError(allErr).Error(getHint()) return "", fmt.Errorf("no buildkit host is available, tried %d candidates: %w", len(hostRel), allErr) } diff --git a/pkg/cmd/container/wait.go b/pkg/cmd/container/wait.go index 97e7706f6ee..5540e7b3c11 100644 --- a/pkg/cmd/container/wait.go +++ b/pkg/cmd/container/wait.go @@ -46,14 +46,14 @@ func Wait(ctx context.Context, client *containerd.Client, reqs []string, options return err } - var allErr error + var errs []error w := options.Stdout for _, container := range containers { if waitErr := waitContainer(ctx, w, container); waitErr != nil { - allErr = errors.Join(allErr, waitErr) + errs = append(errs, waitErr) } } - return allErr + return errors.Join(errs...) } func waitContainer(ctx context.Context, w io.Writer, container containerd.Container) error { diff --git a/pkg/ipfs/registry.go b/pkg/ipfs/registry.go index 6810b87ef37..f9fd183a263 100644 --- a/pkg/ipfs/registry.go +++ b/pkg/ipfs/registry.go @@ -233,15 +233,16 @@ func (s *server) resolveCIDOfDigest(ctx context.Context, dgst digest.Digest, des if err != nil { return "", ocispec.Descriptor{}, err } - var allErr error + var errs []error for _, desc := range descs { gotCID, gotDesc, err := s.resolveCIDOfDigest(ctx, dgst, desc) if err != nil { - allErr = errors.Join(allErr, err) + errs = append(errs, err) continue } return gotCID, gotDesc, nil } + allErr := errors.Join(errs...) if allErr == nil { return "", ocispec.Descriptor{}, fmt.Errorf("not found") } From 4dcef6e0ab534b2b1ac140906f180876c61be870 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 22 Aug 2023 19:10:27 +0900 Subject: [PATCH 0081/1066] pkg/version: fulfill fields from `debug/buildinfo` Fulfill `version.Version` and `version.Revision` from `debug/buildinfo` when the build info is available so that the version can be still printed when nerdctl is installed from `go install`. The values from Makefile is still prioritized over `debug/buildinfo` values. Signed-off-by: Akihiro Suda --- cmd/nerdctl/compose_version.go | 4 +-- cmd/nerdctl/main.go | 2 +- pkg/infoutil/infoutil.go | 4 +-- pkg/version/version.go | 59 ++++++++++++++++++++++++++++++++-- 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/cmd/nerdctl/compose_version.go b/cmd/nerdctl/compose_version.go index dbea1318ec6..99a73274876 100644 --- a/cmd/nerdctl/compose_version.go +++ b/cmd/nerdctl/compose_version.go @@ -47,7 +47,7 @@ func composeVersionAction(cmd *cobra.Command, args []string) error { return err } if short { - fmt.Fprintln(cmd.OutOrStdout(), strings.TrimPrefix(version.Version, "v")) + fmt.Fprintln(cmd.OutOrStdout(), strings.TrimPrefix(version.GetVersion(), "v")) return nil } @@ -57,7 +57,7 @@ func composeVersionAction(cmd *cobra.Command, args []string) error { } switch format { case "pretty": - fmt.Fprintln(cmd.OutOrStdout(), "nerdctl Compose version "+version.Version) + fmt.Fprintln(cmd.OutOrStdout(), "nerdctl Compose version "+version.GetVersion()) case "json": fmt.Fprintf(cmd.OutOrStdout(), "{\"version\":\"%v\"}\n", version.Version) default: diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 35a087f26b2..ccb1ba6de2e 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -194,7 +194,7 @@ Config file ($NERDCTL_TOML): %s Use: "nerdctl", Short: short, Long: long, - Version: strings.TrimPrefix(version.Version, "v"), + Version: strings.TrimPrefix(version.GetVersion(), "v"), SilenceUsage: true, SilenceErrors: true, TraverseChildren: true, // required for global short hands like -a, -H, -n diff --git a/pkg/infoutil/infoutil.go b/pkg/infoutil/infoutil.go index c3eec405948..bee2792e1ab 100644 --- a/pkg/infoutil/infoutil.go +++ b/pkg/infoutil/infoutil.go @@ -115,8 +115,8 @@ func GetSnapshotterNames(ctx context.Context, introService introspection.Service func ClientVersion() dockercompat.ClientVersion { return dockercompat.ClientVersion{ - Version: version.Version, - GitCommit: version.Revision, + Version: version.GetVersion(), + GitCommit: version.GetRevision(), GoVersion: runtime.Version(), Os: runtime.GOOS, Arch: runtime.GOARCH, diff --git a/pkg/version/version.go b/pkg/version/version.go index dae44805521..91d43762670 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -16,9 +16,64 @@ package version +import ( + "runtime/debug" + "strconv" +) + var ( // Version is filled via Makefile - Version = "" + Version = "" // Revision is filled via Makefile - Revision = "" + Revision = "" ) + +const unknown = "" + +func GetVersion() string { + if Version != "" { + return Version + } + /* + * go install example.com/cmd/foo@vX.Y.Z: bi.Main.Version="vX.Y.Z", vcs.revision is unset + * go install example.com/cmd/foo@latest: bi.Main.Version="vX.Y.Z", vcs.revision is unset + * go install example.com/cmd/foo@master: bi.Main.Version="vX.Y.Z-N.yyyyMMddhhmmss-gggggggggggg", vcs.revision is unset + * go install ./cmd/foo: bi.Main.Version="(devel)", vcs.revision="gggggggggggggggggggggggggggggggggggggggg" + * vcs.time="yyyy-MM-ddThh:mm:ssZ", vcs.modified=("false"|"true") + */ + if bi, ok := debug.ReadBuildInfo(); ok { + if bi.Main.Version != "" && bi.Main.Version != "(devel)" { + return bi.Main.Version + } + } + return unknown +} + +func GetRevision() string { + if Revision != "" { + return Revision + } + if bi, ok := debug.ReadBuildInfo(); ok { + var ( + vcsRevision string + vcsModified bool + ) + for _, f := range bi.Settings { + switch f.Key { + case "vcs.revision": + vcsRevision = f.Value + case "vcs.modified": + vcsModified, _ = strconv.ParseBool(f.Value) + } + } + if vcsRevision == "" { + return unknown + } + rev := vcsRevision + if vcsModified { + rev += ".m" + } + return rev + } + return unknown +} From 31d5d4adf6f889bf922a47d109659d2a970c4e61 Mon Sep 17 00:00:00 2001 From: Tobias Bradtke Date: Wed, 23 Aug 2023 12:42:11 +0200 Subject: [PATCH 0082/1066] Fix typo Signed-off-by: Tobias Bradtke --- examples/nerdctl-ipfs-registry-kubernetes/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/nerdctl-ipfs-registry-kubernetes/README.md b/examples/nerdctl-ipfs-registry-kubernetes/README.md index 4ff6c1d341d..f5061252b3b 100644 --- a/examples/nerdctl-ipfs-registry-kubernetes/README.md +++ b/examples/nerdctl-ipfs-registry-kubernetes/README.md @@ -6,9 +6,9 @@ This directory contains examples of node-to-node image sharing on Kubernetes wit - [`./ipfs-cluster`](./ipfs-cluster): node-to-node image sharing with content replication using ipfs-cluster - [`./ipfs-stargz-snapshotter`](./ipfs-stargz-snapshotter): node-to-node image sharing with lazy pulling using eStargz and Stargz Snapshotter -## Example Dockerfile of `nerdctl ipfs regisry` +## Example Dockerfile of `nerdctl ipfs registry` -The above examples use `nerdctl ipfs regisry` running in a Pod. +The above examples use `nerdctl ipfs registry` running in a Pod. The image is available at [`ghcr.io/stargz-containers/nerdctl-ipfs-registry`](https://github.com/orgs/stargz-containers/packages/container/package/nerdctl-ipfs-registry). The following Dockerfile can be used to build it by yourself. From a0aac07a02d4cc32d5ad23bb9cb9ccaac06fc1cb Mon Sep 17 00:00:00 2001 From: Vishwas Siravara Date: Wed, 23 Aug 2023 17:12:03 -0700 Subject: [PATCH 0083/1066] Support copying out of volumes in stopped containers Signed-off-by: Vishwas Siravara --- cmd/nerdctl/container_cp_linux_test.go | 113 ++++++++++++++++++++++++- pkg/containerutil/cp_linux.go | 104 ++++++++++++++++++++--- 2 files changed, 203 insertions(+), 14 deletions(-) diff --git a/cmd/nerdctl/container_cp_linux_test.go b/cmd/nerdctl/container_cp_linux_test.go index c78a0a0519a..b71d694c838 100644 --- a/cmd/nerdctl/container_cp_linux_test.go +++ b/cmd/nerdctl/container_cp_linux_test.go @@ -51,8 +51,8 @@ func TestCopyToContainer(t *testing.T) { assertCat := func(catPath string, testContainer string, stopped bool) { if stopped { - base.Cmd("start", testStoppedContainer).AssertOK() - defer base.Cmd("stop", testStoppedContainer).AssertOK() + base.Cmd("start", testContainer).AssertOK() + defer base.Cmd("stop", testContainer).AssertOK() } t.Logf("catPath=%q", catPath) base.Cmd("exec", testContainer, "cat", catPath).AssertOutExactly(string(srcFileContent)) @@ -108,6 +108,75 @@ func TestCopyToContainer(t *testing.T) { base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() assertCat(catPath, testStoppedContainer, true) }) + t.Run("DEST_PATH is in a volume", func(t *testing.T) { + // Create a volume + vol := "somevol" + base.Cmd("volume", "create", vol).AssertOK() + defer base.Cmd("volume", "rm", vol).Run() + con := fmt.Sprintf("%s-with-volume", testContainer) + mountDir := "/some_dir" + base.Cmd("run", "-d", "--name", con, "-v", fmt.Sprintf("%s:%s", vol, mountDir), testutil.CommonImage, "sleep", "1h").AssertOK() + defer base.Cmd("rm", "-f", con).Run() + catPath := filepath.Join(mountDir, filepath.Base(srcFile)) + // Running container test + base.Cmd("cp", srcPath, con+":"+mountDir).AssertOK() + assertCat(catPath, con, false) + + // Skip for rootless + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + // Stopped container test + // Delete previously copied file + base.Cmd("exec", con, "rm", catPath).AssertOK() + base.Cmd("stop", con).AssertOK() + base.Cmd("cp", srcPath, con+":"+mountDir).AssertOK() + assertCat(catPath, con, true) + }) + t.Run("Destination path is a read-only", func(t *testing.T) { + vol := "somevol" + base.Cmd("volume", "create", vol).AssertOK() + defer base.Cmd("volume", "rm", vol).Run() + con := fmt.Sprintf("%s-with-read-only-volume", testContainer) + mountDir := "/some_dir" + // Create container with read-only volume mounted + base.Cmd("run", "-d", "--name", con, "-v", fmt.Sprintf("%s:%s:ro", vol, mountDir), testutil.CommonImage, "sleep", "1h").AssertOK() + defer base.Cmd("rm", "-f", con).Run() + base.Cmd("cp", srcPath, con+":"+mountDir).AssertFail() + + // Skip for rootless + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + + // Stopped container test + // Delete previously copied file + base.Cmd("stop", con).AssertOK() + base.Cmd("cp", srcPath, con+":"+mountDir).AssertFail() + }) + t.Run("Destination path is a read-only and default tmpfs mount point", func(t *testing.T) { + vol := "somevol" + base.Cmd("volume", "create", vol).AssertOK() + defer base.Cmd("volume", "rm", vol).Run() + con := fmt.Sprintf("%s-with-read-only-volume", testContainer) + + // /tmp is from rootfs of alpine + mountDir := "/tmp" + // Create container with read-only mounted volume mounted at /tmp + base.Cmd("run", "-d", "--name", con, "-v", fmt.Sprintf("%s:%s:ro", vol, mountDir), testutil.CommonImage, "sleep", "1h").AssertOK() + defer base.Cmd("rm", "-f", con).Run() + base.Cmd("cp", srcPath, con+":"+mountDir).AssertFail() + + // Skip for rootless + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + + // Stopped container test + // Delete previously copied file + base.Cmd("stop", con).AssertOK() + base.Cmd("cp", srcPath, con+":"+mountDir).AssertFail() + }) }) t.Run("SRC_PATH specifies a directory", func(t *testing.T) { srcPath := srcDir @@ -176,7 +245,6 @@ func TestCopyFromContainer(t *testing.T) { base := testutil.NewBase(t) testContainer := testutil.Identifier(t) testStoppedContainer := "stopped-container-" + testutil.Identifier(t) - base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", "1h").AssertOK() defer base.Cmd("rm", "-f", testContainer).Run() @@ -255,6 +323,45 @@ func TestCopyFromContainer(t *testing.T) { base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() assertCat(catPath) }) + t.Run("SRC_PATH is in a volume", func(t *testing.T) { + // Setup + // Create a volume + vol := "somevol" + base.Cmd("volume", "create", vol).AssertOK() + defer base.Cmd("volume", "rm", "-f", vol).Run() + + // Create container for test + con := fmt.Sprintf("%s-with-volume", testContainer) + + mountDir := "/some_dir" + base.Cmd("run", "-d", "--name", con, "-v", fmt.Sprintf("%s:%s", vol, mountDir), testutil.CommonImage, "sleep", "1h").AssertOK() + defer base.Cmd("rm", "-f", con).Run() + + // Create a file to mounted volume + mountedVolFile := filepath.Join(mountDir, "test-file") + mkSrcScript = fmt.Sprintf("echo -n %q >%q && chown %d %q", srcFileContent, mountedVolFile, srcUID, mountedVolFile) + base.Cmd("exec", con, "sh", "-euc", mkSrcScript).AssertOK() + + // Create destination directory on host for copy + destPath := filepath.Join(td, "dest-dir") + err := os.Mkdir(destPath, 0o700) + assert.NilError(t, err) + + catPath := filepath.Join(destPath, filepath.Base(mountedVolFile)) + + // Running container test + base.Cmd("cp", con+":"+mountedVolFile, destPath).AssertOK() + assertCat(catPath) + + // Skip for rootless + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for testStoppedContainer") + } + // Stopped container test + base.Cmd("stop", con).AssertOK() + base.Cmd("cp", con+":"+mountedVolFile, destPath).AssertOK() + assertCat(catPath) + }) }) t.Run("SRC_PATH specifies a directory", func(t *testing.T) { srcPath := srcDir diff --git a/pkg/containerutil/cp_linux.go b/pkg/containerutil/cp_linux.go index d0aeed9694c..c4716da5ea3 100644 --- a/pkg/containerutil/cp_linux.go +++ b/pkg/containerutil/cp_linux.go @@ -18,10 +18,12 @@ package containerutil import ( "context" + "errors" "fmt" "io/fs" "os" "os/exec" + "path" "path/filepath" "strconv" "strings" @@ -43,24 +45,42 @@ func CopyFiles(ctx context.Context, client *containerd.Client, container contain return err } logrus.Debugf("Detected tar binary %q (GNU=%v)", tarBinary, isGNUTar) - var srcFull, dstFull, root string + var srcFull, dstFull, root, mountDestination, containerPath string var cleanup func() task, err := container.Task(ctx, nil) if err != nil { - // if the task is simply not found, we should try to mount the snapshot. any other type of error from Task() is fatal here. - // Rootless does not support copying into/out of stopped/created containers as we need to nsenter into the user namespace of the + // FIXME: Rootless does not support copying into/out of stopped/created containers as we need to nsenter into the user namespace of the // pid of the running container with --preserve-credentials to preserve uid/gid mapping and copy files into the container. - - if !errdefs.IsNotFound(err) || rootlessutil.IsRootless() { + if rootlessutil.IsRootless() { + return errors.New("cannot use cp with stopped containers in rootless mode") + } + // if the task is simply not found, we should try to mount the snapshot. any other type of error from Task() is fatal here. + if !errdefs.IsNotFound(err) { return err } - root, cleanup, err = mountSnapshotForContainer(ctx, client, container, snapshotter) - if cleanup != nil { - defer cleanup() + if container2host { + containerPath = src + } else { + containerPath = dst } + // Check if containerPath is in a volume + root, mountDestination, err = getContainerMountInfo(ctx, container, containerPath, container2host) if err != nil { return err } + // if containerPath is in a volume and not read-only in case of host2container copy then handle volume paths, + // else containerPath is not in volume so mount container snapshot for copy + if root != "" { + dst, src = handleVolumePaths(container2host, dst, src, mountDestination) + } else { + root, cleanup, err = mountSnapshotForContainer(ctx, client, container, snapshotter) + if cleanup != nil { + defer cleanup() + } + if err != nil { + return err + } + } } else { status, err := task.Status(ctx) if err != nil { @@ -72,13 +92,28 @@ func CopyFiles(ctx context.Context, client *containerd.Client, container contain if rootlessutil.IsRootless() { return fmt.Errorf("cannot use cp with stopped containers in rootless mode") } - root, cleanup, err = mountSnapshotForContainer(ctx, client, container, snapshotter) - if cleanup != nil { - defer cleanup() + if container2host { + containerPath = src + } else { + containerPath = dst } + root, mountDestination, err = getContainerMountInfo(ctx, container, containerPath, container2host) if err != nil { return err } + // if containerPath is in a volume and not read-only in case of host2container copy then handle volume paths, + // else containerPath is not in volume so mount container snapshot for copy + if root != "" { + dst, src = handleVolumePaths(container2host, dst, src, mountDestination) + } else { + root, cleanup, err = mountSnapshotForContainer(ctx, client, container, snapshotter) + if cleanup != nil { + defer cleanup() + } + if err != nil { + return err + } + } } } if container2host { @@ -247,3 +282,50 @@ func mountSnapshotForContainer(ctx context.Context, client *containerd.Client, c } return tempDir, cleanup, nil } + +func getContainerMountInfo(ctx context.Context, con containerd.Container, containerPath string, container2host bool) (string, string, error) { + filePath := filepath.Clean(containerPath) + spec, err := con.Spec(ctx) + if err != nil { + return "", "", err + } + // read-only applies only while copying into container from host + if !container2host && spec.Root.Readonly { + return "", "", fmt.Errorf("container rootfs: %s is marked read-only", spec.Root.Path) + } + + for _, mount := range spec.Mounts { + if isSelfOrAscendant(filePath, mount.Destination) { + // read-only applies only while copying into container from host + if !container2host { + for _, option := range mount.Options { + if option == "ro" { + return "", "", fmt.Errorf("mount point %s is marked read-only", filePath) + } + } + } + return mount.Source, mount.Destination, nil + } + } + return "", "", nil +} + +func isSelfOrAscendant(filePath, potentialAncestor string) bool { + if filePath == "/" || filePath == "" || potentialAncestor == "" { + return false + } + filePath = filepath.Clean(filePath) + potentialAncestor = filepath.Clean(potentialAncestor) + if filePath == potentialAncestor { + return true + } + return isSelfOrAscendant(path.Dir(filePath), potentialAncestor) +} + +// When the path is in volume remove directory that volume is mounted on from the path +func handleVolumePaths(container2host bool, dst string, src string, mountDestination string) (string, string) { + if container2host { + return dst, strings.TrimPrefix(filepath.Clean(src), mountDestination) + } + return strings.TrimPrefix(filepath.Clean(dst), mountDestination), src +} From 9a41384bdb653a5ad69d019c2b67f3940a572f90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 22:11:17 +0000 Subject: [PATCH 0084/1066] build(deps): bump actions/checkout from 3.5.3 to 3.6.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.5.3...v3.6.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 20 +++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index f8d2a0ab68b..9de7245ed4f 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v3.6.0 - name: Set up QEMU uses: docker/setup-qemu-action@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 668139d622e..ddb15630f53 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 - uses: actions/setup-go@v4 with: go-version: 1.21.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a500e866607..8f0f8b04880 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -88,7 +88,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -141,7 +141,7 @@ jobs: CONTAINERD_VERSION: "${{ matrix.containerd }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -158,7 +158,7 @@ jobs: matrix: go-version: ["1.20.x", "1.21.x"] steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -173,7 +173,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 30 steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -209,7 +209,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -218,7 +218,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 with: repository: containerd/containerd ref: v1.7.3 @@ -243,7 +243,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v3.6.0 - uses: actions/cache@v3 with: path: /root/.vagrant.d From c6dd2f5f7132c94d5ea39dae3f3e2d1b438d2e62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Aug 2023 22:32:50 +0000 Subject: [PATCH 0085/1066] build(deps): bump github.com/containerd/containerd from 1.7.3 to 1.7.5 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.3 to 1.7.5. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.3...v1.7.5) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index d914980e3e8..34089e8a3ae 100644 --- a/go.mod +++ b/go.mod @@ -11,8 +11,8 @@ require ( github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 - github.com/containerd/containerd v1.7.3 - github.com/containerd/continuity v0.4.1 + github.com/containerd/containerd v1.7.5 + github.com/containerd/continuity v0.4.2 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 github.com/containerd/nydus-snapshotter v0.10.0 @@ -62,7 +62,7 @@ require ( ) require ( - github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect + 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 github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect diff --git a/go.sum b/go.sum index 60de496e36e..8fad26e49d2 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= @@ -34,10 +34,10 @@ github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKk github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.3 h1:cKwYKkP1eTj54bP3wCdXXBymmKRQMrWjkLSWZZJDa8o= -github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8= -github.com/containerd/continuity v0.4.1 h1:wQnVrjIyQ8vhU2sgOiL5T07jo+ouqc2bnKsv5/EqGhU= -github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/containerd v1.7.5 h1:i9T9XpAWMe11BHMN7pu1BZqOGjXaKTPyz2v+KYOZgkY= +github.com/containerd/containerd v1.7.5/go.mod h1:ieJNCSzASw2shSGYLHx8NAE7WsZ/gEigo5fQ78W5Zvw= +github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= +github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= 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= From 79a157827bd69b7eeea1c6e10131a9358d5aa08d Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Sun, 27 Aug 2023 10:03:33 +0800 Subject: [PATCH 0086/1066] fix: succeeded typo Signed-off-by: guoguangwu --- examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md b/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md index 67907c5783c..f5ca9a59615 100644 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md @@ -51,7 +51,7 @@ $ docker exec -it kind-worker /bin/bash The image added to `kind-worker` is shared to `kind-worker2` via IPFS. You can run this image on all worker nodes using the following manifest. -CID of the pushed image is printed when `nerdctl push` is succeded (we assume that the image is added to IPFS as CID `bafkreictyyoysj56v772xbfhyfrcvmgmfpa4vodmqaroz53ytvai7nof6u`). +CID of the pushed image is printed when `nerdctl push` is succeeded (we assume that the image is added to IPFS as CID `bafkreictyyoysj56v772xbfhyfrcvmgmfpa4vodmqaroz53ytvai7nof6u`). ```console $ cat < Date: Mon, 28 Aug 2023 09:01:35 +0800 Subject: [PATCH 0087/1066] fix: grammatical errors Signed-off-by: guoguangwu --- examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md b/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md index f5ca9a59615..64c91f02a88 100644 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md @@ -51,7 +51,7 @@ $ docker exec -it kind-worker /bin/bash The image added to `kind-worker` is shared to `kind-worker2` via IPFS. You can run this image on all worker nodes using the following manifest. -CID of the pushed image is printed when `nerdctl push` is succeeded (we assume that the image is added to IPFS as CID `bafkreictyyoysj56v772xbfhyfrcvmgmfpa4vodmqaroz53ytvai7nof6u`). +CID of the pushed image is printed when `nerdctl push` succeeded (we assume that the image is added to IPFS as CID `bafkreictyyoysj56v772xbfhyfrcvmgmfpa4vodmqaroz53ytvai7nof6u`). ```console $ cat < Date: Wed, 23 Aug 2023 12:44:07 +0200 Subject: [PATCH 0088/1066] Makefile: derive BINDIR from PREFIX The PREFIX variable is commonly used by dist build systems to define the FHS-style prefix dir (/usr vs /usr/local). Deriving our BINDIR from it (still pointing to /usr/local by default) makes it a bit easier for packagers, yet another aspect that they don't need to take extra care for. Signed-off-by: Enrico Weigelt, metux IT consult --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d4a76cb6cd8..57a70b493b2 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,10 @@ ifeq ($(GOOS),windows) endif PACKAGE := github.com/containerd/nerdctl -BINDIR ?= /usr/local/bin + +# distro builders might wanna override these +PREFIX ?= /usr/local +BINDIR ?= $(PREFIX)/bin VERSION ?= $(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags) VERSION_TRIMMED := $(VERSION:v%=%) From fa9e4edbdd0f235ed7781c18b07931f531637a31 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 21 Aug 2023 17:09:29 +0200 Subject: [PATCH 0089/1066] Makefile: add GO_BUILD_FLAGS variable This variable can be used by distros for injecting site/distro specific build flags. Signed-off-by: Enrico Weigelt, metux IT consult --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 57a70b493b2..f5adeb068e0 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,7 @@ VERSION_TRIMMED := $(VERSION:v%=%) REVISION ?= $(shell git rev-parse HEAD)$(shell if ! git diff --no-ext-diff --quiet --exit-code; then echo .m; fi) GO_BUILD_LDFLAGS ?= -s -w +GO_BUILD_FLAGS ?= export GO_BUILD=GO111MODULE=on CGO_ENABLED=0 GOOS=$(GOOS) $(GO) build -ldflags "$(GO_BUILD_LDFLAGS) -X $(PACKAGE)/pkg/version.Version=$(VERSION) -X $(PACKAGE)/pkg/version.Revision=$(REVISION)" ifdef VERBOSE @@ -51,7 +52,7 @@ help: @echo " * 'clean' - Clean artifacts." nerdctl: - $(GO_BUILD) $(VERBOSE_FLAG) -o $(CURDIR)/_output/nerdctl$(BIN_EXT) $(PACKAGE)/cmd/nerdctl + $(GO_BUILD) $(GO_BUILD_FLAGS) $(VERBOSE_FLAG) -o $(CURDIR)/_output/nerdctl$(BIN_EXT) $(PACKAGE)/cmd/nerdctl clean: find . -name \*~ -delete From da05f9265c34892c2d51be818d13ba411e086ad8 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 21 Aug 2023 17:18:09 +0200 Subject: [PATCH 0090/1066] Makefile: fix overriding GO command We already have the GO variable for injecting the actual go command to use (when it's not the first one found, or not at all in PATH), a usual scenario in isolated dist builds. But there's yet one call missing, that still had the command hardcoded. Signed-off-by: Enrico Weigelt, metux IT consult --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f5adeb068e0..30671305e66 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ # ----------------------------------------------------------------------------- GO ?= go -GOOS ?= $(shell go env GOOS) +GOOS ?= $(shell $(GO) env GOOS) ifeq ($(GOOS),windows) BIN_EXT := .exe endif From 6e542c3ae4d3637fbd50d17a01089a8347f0baa6 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Wed, 23 Aug 2023 13:34:27 +0200 Subject: [PATCH 0091/1066] Makefile: install docs Distros usually wanna have the docs installed to standard place. Signed-off-by: Enrico Weigelt, metux IT consult --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 30671305e66..8978d22b149 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,8 @@ PACKAGE := github.com/containerd/nerdctl # distro builders might wanna override these PREFIX ?= /usr/local BINDIR ?= $(PREFIX)/bin +DATADIR ?= $(PREFIX)/share +DOCDIR ?= $(DATADIR)/doc VERSION ?= $(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags) VERSION_TRIMMED := $(VERSION:v%=%) @@ -65,6 +67,7 @@ install: install -D -m 755 $(CURDIR)/_output/nerdctl $(DESTDIR)$(BINDIR)/nerdctl install -D -m 755 $(CURDIR)/extras/rootless/containerd-rootless.sh $(DESTDIR)$(BINDIR)/containerd-rootless.sh install -D -m 755 $(CURDIR)/extras/rootless/containerd-rootless-setuptool.sh $(DESTDIR)$(BINDIR)/containerd-rootless-setuptool.sh + install -D -m 644 -t $(DESTDIR)$(DOCDIR)/nerdctl docs/*.md define make_artifact_full_linux DOCKER_BUILDKIT=1 docker build --output type=tar,dest=$(CURDIR)/_output/nerdctl-full-$(VERSION_TRIMMED)-linux-$(1).tar --target out-full --platform $(1) --build-arg GO_VERSION $(CURDIR) From 1352ac0d9e56d0400a8bec3d7ef041c84f8119a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 22:10:15 +0000 Subject: [PATCH 0092/1066] build(deps): bump github.com/awslabs/soci-snapshotter Bumps [github.com/awslabs/soci-snapshotter](https://github.com/awslabs/soci-snapshotter) from 0.3.0 to 0.4.0. - [Release notes](https://github.com/awslabs/soci-snapshotter/releases) - [Changelog](https://github.com/awslabs/soci-snapshotter/blob/main/RELEASES.md) - [Commits](https://github.com/awslabs/soci-snapshotter/compare/v0.3.0...v0.4.0) --- updated-dependencies: - dependency-name: github.com/awslabs/soci-snapshotter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 17 +++++++++++------ go.sum | 30 +++++++++++++++++------------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 34089e8a3ae..3c8c072e354 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.10.0 - github.com/awslabs/soci-snapshotter v0.3.0 + github.com/awslabs/soci-snapshotter v0.4.0 github.com/compose-spec/compose-go v1.18.2 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 @@ -61,6 +61,11 @@ require ( gotest.tools/v3 v3.5.0 ) +require ( + go.opentelemetry.io/otel/metric v1.16.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // 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 @@ -120,12 +125,12 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.15.1 // indirect - go.opentelemetry.io/otel/trace v1.15.1 // indirect + go.opentelemetry.io/otel v1.16.0 // indirect + go.opentelemetry.io/otel/trace v1.16.0 // indirect golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect - golang.org/x/mod v0.11.0 // indirect - golang.org/x/tools v0.9.1 // indirect - google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/tools v0.11.0 // indirect + google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect google.golang.org/grpc v1.56.2 // indirect google.golang.org/protobuf v1.31.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect diff --git a/go.sum b/go.sum index 8fad26e49d2..bb0d56da08c 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.10.0 h1:PbvoxdUGgXxyirmN5Oncp3POLkxEG5LbWCEBfWmHTGA= github.com/Microsoft/hcsshim v0.10.0/go.mod h1:3j1trOamcUdi86J5Tr5+1BpqMjSv/QeRWkX2whBF6dY= -github.com/awslabs/soci-snapshotter v0.3.0 h1:DcVedf88R8GO77WhJn/dusQqzCrjrh1RWBataW6pVV8= -github.com/awslabs/soci-snapshotter v0.3.0/go.mod h1:s3cGc7hKDMefFbTf4YGzxRC9Q9nm2E/IU+65ExdRbvA= +github.com/awslabs/soci-snapshotter v0.4.0 h1:dA9lOYbzSUaYMahB8qXQZTVXUszhc0w8rwjRs6EPd24= +github.com/awslabs/soci-snapshotter v0.4.0/go.mod h1:+ST8F4E/b6b6pnFBJKprdvzkxyXODMs0FC2TmclkgJc= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -254,7 +254,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rootless-containers/bypass4netns v0.3.0 h1:UwI55zWDZz7OGyN4YWgfCKdsI58VGY7OlghcLdxJX10= @@ -318,10 +318,12 @@ go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwf go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.15.1 h1:3Iwq3lfRByPaws0f6bU3naAqOR1n5IeDWd9390kWHa8= -go.opentelemetry.io/otel v1.15.1/go.mod h1:mHHGEHVDLal6YrKMmk9LqC4a3sF5g+fHfrttQIB1NTc= -go.opentelemetry.io/otel/trace v1.15.1 h1:uXLo6iHJEzDfrNC0L0mNjItIp06SyaBQxu5t3xMlngY= -go.opentelemetry.io/otel/trace v1.15.1/go.mod h1:IWdQG/5N1x7f6YUlmdLeJvH9yxtuJAfc4VW5Agv9r/8= +go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= +go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= +go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= +go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= +go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= +go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -337,8 +339,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= -golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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= @@ -408,8 +410,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8= +golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -420,8 +422,10 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 h1:+VoAg+OKmWaommL56xmZSE2sUK8A7m6SUO7X89F2tbw= +google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753/go.mod h1:iqkVr8IRpZ53gx1dEnWlCUIEwDWqWARWrbzpasaTNYM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 h1:XUODHrpzJEUeWmVo/jfNTLj0YyVveOo28oE6vkFbkO4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= 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= From 2739c8fc8b98a8f80fff2b9bfbcb009e493fd7ec Mon Sep 17 00:00:00 2001 From: Vishwas Siravara Date: Tue, 29 Aug 2023 16:56:15 -0700 Subject: [PATCH 0093/1066] fix nerdctl run -v when host folder does not exist for bind mounts Signed-off-by: Vishwas Siravara --- cmd/nerdctl/container_run_mount_linux_test.go | 26 +++++++++++++++++++ pkg/cmd/container/run_mount.go | 3 ++- pkg/mountutil/mountutil.go | 14 +++++++++- pkg/mountutil/mountutil_linux.go | 3 ++- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container_run_mount_linux_test.go index b2eb09c3034..bed8f0936b1 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container_run_mount_linux_test.go @@ -684,3 +684,29 @@ func TestRunVolumesFrom(t *testing.T) { "cat", "/mnt1/file1", "/mnt3/file3", ).AssertOutExactly("str1str3") } + +func TestBindMountWhenHostFolderDoesNotExist(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + "-host-dir-not-found" + hostDir, err := os.MkdirTemp(t.TempDir(), "rw") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(hostDir) + hp := filepath.Join(hostDir, "does-not-exist") + base.Cmd("run", "--name", containerName, "-d", "-v", fmt.Sprintf("%s:/tmp", + hp), testutil.AlpineImage).AssertOK() + base.Cmd("rm", "-f", containerName).AssertOK() + + // Host directory should get created + _, err = os.Stat(hp) + assert.NilError(t, err) + + // Test for --mount + os.RemoveAll(hp) + base.Cmd("run", "--name", containerName, "-d", "--mount", fmt.Sprintf("type=bind, source=%s, target=/tmp", + hp), testutil.AlpineImage).AssertFail() + _, err = os.Stat(hp) + assert.ErrorIs(t, err, os.ErrNotExist) +} diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index 4ebfb5b7d41..251be8ebd7e 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -93,7 +93,8 @@ func withMounts(mounts []specs.Mount) oci.SpecOpts { func parseMountFlags(volStore volumestore.VolumeStore, options types.ContainerCreateOptions) ([]*mountutil.Processed, error) { var parsed []*mountutil.Processed //nolint:prealloc for _, v := range strutil.DedupeStrSlice(options.Volume) { - x, err := mountutil.ProcessFlagV(v, volStore) + // createDir=true for -v option to allow creation of directory on host if not found. + x, err := mountutil.ProcessFlagV(v, volStore, true) if err != nil { return nil, err } diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index 4e44d0bf06a..6f8a71bc68f 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -19,6 +19,7 @@ package mountutil import ( "errors" "fmt" + "os" "path/filepath" "runtime" "strings" @@ -49,7 +50,7 @@ type Processed struct { Opts []oci.SpecOpts } -func ProcessFlagV(s string, volStore volumestore.VolumeStore) (*Processed, error) { +func ProcessFlagV(s string, volStore volumestore.VolumeStore, createDir bool) (*Processed, error) { var ( res Processed src, dst string @@ -98,6 +99,17 @@ func ProcessFlagV(s string, volStore volumestore.VolumeStore) (*Processed, error return nil, fmt.Errorf("failed to get the absolute path of %q: %w", src, err) } } + if createDir { + if _, err := os.Stat(src); err != nil { + if !os.IsNotExist(err) { + return nil, fmt.Errorf("failed to stat %q: %w", src, err) + } + if err := os.MkdirAll(src, 0o755); err != nil { + return nil, fmt.Errorf("failed to mkdir %q: %w", src, err) + } + } + } + if !filepath.IsAbs(dst) { return nil, fmt.Errorf("expected an absolute path, got %q", dst) } diff --git a/pkg/mountutil/mountutil_linux.go b/pkg/mountutil/mountutil_linux.go index 68940ab9a4e..92e6ebadfee 100644 --- a/pkg/mountutil/mountutil_linux.go +++ b/pkg/mountutil/mountutil_linux.go @@ -424,7 +424,8 @@ func ProcessFlagMount(s string, volStore volumestore.VolumeStore) (*Processed, e case Tmpfs: return ProcessFlagTmpfs(fieldsStr) case Volume, Bind: - return ProcessFlagV(fieldsStr, volStore) + // createDir=false for --mount option to disallow creating directories on host if not found + return ProcessFlagV(fieldsStr, volStore, false) } return nil, fmt.Errorf("invalid mount type '%s' must be a volume/bind/tmpfs", mountType) } From f7752221c01ac9aff89b94dd2d8cb1a6482a4a16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 22:28:32 +0000 Subject: [PATCH 0094/1066] build(deps): bump actions/checkout from 3.6.0 to 4.0.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.6.0...v4.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 20 +++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 9de7245ed4f..9b586a74e08 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4.0.0 - name: Set up QEMU uses: docker/setup-qemu-action@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ddb15630f53..680c8c45ff5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 - uses: actions/setup-go@v4 with: go-version: 1.21.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8f0f8b04880..91466a18ef3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -88,7 +88,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -141,7 +141,7 @@ jobs: CONTAINERD_VERSION: "${{ matrix.containerd }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -158,7 +158,7 @@ jobs: matrix: go-version: ["1.20.x", "1.21.x"] steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -173,7 +173,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 30 steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -209,7 +209,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -218,7 +218,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 with: repository: containerd/containerd ref: v1.7.3 @@ -243,7 +243,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4.0.0 - uses: actions/cache@v3 with: path: /root/.vagrant.d From c2b9f877fd410293602850f466606c83bb44b59a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 22:37:38 +0000 Subject: [PATCH 0095/1066] build(deps): bump golang.org/x/sys from 0.11.0 to 0.12.0 Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.11.0 to 0.12.0. - [Commits](https://github.com/golang/sys/compare/v0.11.0...v0.12.0) --- updated-dependencies: - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3c8c072e354..78212728dad 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( golang.org/x/crypto v0.12.0 golang.org/x/net v0.14.0 golang.org/x/sync v0.3.0 - golang.org/x/sys v0.11.0 + golang.org/x/sys v0.12.0 golang.org/x/term v0.11.0 golang.org/x/text v0.12.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index bb0d56da08c..c359a7ea059 100644 --- a/go.sum +++ b/go.sum @@ -390,8 +390,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= From c565933b0d3d40fa0df8d54b5409ee036d7d7192 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 23:43:41 +0000 Subject: [PATCH 0096/1066] build(deps): bump golang.org/x/text from 0.12.0 to 0.13.0 Bumps [golang.org/x/text](https://github.com/golang/text) from 0.12.0 to 0.13.0. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.12.0...v0.13.0) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 78212728dad..117cd1f59a5 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( golang.org/x/sync v0.3.0 golang.org/x/sys v0.12.0 golang.org/x/term v0.11.0 - golang.org/x/text v0.12.0 + golang.org/x/text v0.13.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.0 ) diff --git a/go.sum b/go.sum index c359a7ea059..f139b7832e3 100644 --- a/go.sum +++ b/go.sum @@ -398,8 +398,8 @@ golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From cf6ba3055da655a4048e39fabd8c6c9c7777c612 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 07:14:32 +0000 Subject: [PATCH 0097/1066] build(deps): bump golang.org/x/term from 0.11.0 to 0.12.0 Bumps [golang.org/x/term](https://github.com/golang/term) from 0.11.0 to 0.12.0. - [Commits](https://github.com/golang/term/compare/v0.11.0...v0.12.0) --- updated-dependencies: - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 117cd1f59a5..2eefdbcd045 100644 --- a/go.mod +++ b/go.mod @@ -55,7 +55,7 @@ require ( golang.org/x/net v0.14.0 golang.org/x/sync v0.3.0 golang.org/x/sys v0.12.0 - golang.org/x/term v0.11.0 + golang.org/x/term v0.12.0 golang.org/x/text v0.13.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.0 diff --git a/go.sum b/go.sum index f139b7832e3..b286aaaae42 100644 --- a/go.sum +++ b/go.sum @@ -393,8 +393,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 1bb407c032d69c4d9c780873e424446964dbce6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 22:41:59 +0000 Subject: [PATCH 0098/1066] build(deps): bump golang.org/x/net from 0.14.0 to 0.15.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.14.0 to 0.15.0. - [Commits](https://github.com/golang/net/compare/v0.14.0...v0.15.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 2eefdbcd045..77e2f15fa2d 100644 --- a/go.mod +++ b/go.mod @@ -51,8 +51,8 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 - golang.org/x/crypto v0.12.0 - golang.org/x/net v0.14.0 + golang.org/x/crypto v0.13.0 + golang.org/x/net v0.15.0 golang.org/x/sync v0.3.0 golang.org/x/sys v0.12.0 golang.org/x/term v0.12.0 diff --git a/go.sum b/go.sum index b286aaaae42..c3b5690cda7 100644 --- a/go.sum +++ b/go.sum @@ -329,8 +329,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= @@ -353,8 +353,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 84309f24f6f9fcae08ac12c0670f2440cb4f3ac3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 22:42:24 +0000 Subject: [PATCH 0099/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 24.0.5+incompatible to 24.0.6+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v24.0.5...v24.0.6) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2eefdbcd045..7411ddfad60 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.3 github.com/docker/cli v24.0.5+incompatible - github.com/docker/docker v24.0.5+incompatible + github.com/docker/docker v24.0.6+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.0 diff --git a/go.sum b/go.sum index b286aaaae42..64ff634ab4d 100644 --- a/go.sum +++ b/go.sum @@ -82,8 +82,8 @@ 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.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY= -github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= +github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From cdc917eb9f9d41a64ebae525bd7c158d2b9057cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 00:00:36 +0000 Subject: [PATCH 0100/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 24.0.5+incompatible to 24.0.6+incompatible. - [Commits](https://github.com/docker/cli/compare/v24.0.5...v24.0.6) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7411ddfad60..bb8f18b5701 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.3 - github.com/docker/cli v24.0.5+incompatible + github.com/docker/cli v24.0.6+incompatible github.com/docker/docker v24.0.6+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 64ff634ab4d..0b7b5f8bc9e 100644 --- a/go.sum +++ b/go.sum @@ -80,8 +80,8 @@ github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa h1:L9 github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= 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.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= -github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= +github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= From b598b583ae6c23ef8e3ba11dbedea8130ec9909c Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Wed, 6 Sep 2023 22:57:45 +0200 Subject: [PATCH 0101/1066] add missing zero-length list check Signed-off-by: fahed dorgaa --- cmd/nerdctl/container_list.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container_list.go index c227548bf93..5422b76d860 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container_list.go @@ -202,6 +202,10 @@ func formatAndPrintContainerInfo(containers []container.ListItem, options Format return err } } else { + var name string + if len(c.Names) > 0 { + name = c.Names[0] + } format := "%s\t%s\t%s\t%s\t%s\t%s\t%s" args := []interface{}{ c.ID, @@ -210,7 +214,7 @@ func formatAndPrintContainerInfo(containers []container.ListItem, options Format formatter.TimeSinceInHuman(c.CreatedAt), c.Status, c.Ports, - c.Names[0], + name, } if wide { format += "\t%s\t%s\t%s\n" From a80e0eb179fa549f91bd6ed1996421372415ba25 Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Tue, 5 Sep 2023 22:57:49 +0200 Subject: [PATCH 0102/1066] fix container_create_windows_test Signed-off-by: fahed dorgaa --- cmd/nerdctl/container_create_windows_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/nerdctl/container_create_windows_test.go b/cmd/nerdctl/container_create_windows_test.go index e8f662895ac..643fce767b9 100644 --- a/cmd/nerdctl/container_create_windows_test.go +++ b/cmd/nerdctl/container_create_windows_test.go @@ -24,7 +24,6 @@ import ( ) func TestCreateProcessContainer(t *testing.T) { - t.Parallel() base := testutil.NewBase(t) tID := testutil.Identifier(t) @@ -36,7 +35,6 @@ func TestCreateProcessContainer(t *testing.T) { } func TestCreateHyperVContainer(t *testing.T) { - //t.Parallel() base := testutil.NewBase(t) tID := testutil.Identifier(t) From e1bad09da97ec8503b248d9264236309a2f5e397 Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Wed, 6 Sep 2023 22:58:30 +0200 Subject: [PATCH 0103/1066] adjust writers fmt Signed-off-by: fahed dorgaa --- cmd/nerdctl/compose_top.go | 2 +- cmd/nerdctl/container_list.go | 2 +- cmd/nerdctl/container_run.go | 2 +- cmd/nerdctl/image_history.go | 2 +- cmd/nerdctl/version.go | 6 +++--- pkg/cmd/container/commit.go | 2 +- pkg/cmd/container/kill.go | 2 +- pkg/cmd/container/pause.go | 2 +- pkg/cmd/container/remove.go | 2 +- pkg/cmd/container/restart.go | 2 +- pkg/cmd/container/start.go | 2 +- pkg/cmd/container/stop.go | 2 +- pkg/cmd/container/unpause.go | 2 +- pkg/cmd/image/list.go | 2 +- pkg/cmd/namespace/remove.go | 2 +- pkg/cmd/network/create.go | 2 +- pkg/cmd/system/info.go | 6 +++--- pkg/cmd/volume/create.go | 2 +- pkg/composer/pause.go | 4 ++-- pkg/ocihook/ocihook.go | 2 +- 20 files changed, 25 insertions(+), 25 deletions(-) diff --git a/cmd/nerdctl/compose_top.go b/cmd/nerdctl/compose_top.go index 254e1c7a557..54aa9ce2b41 100644 --- a/cmd/nerdctl/compose_top.go +++ b/cmd/nerdctl/compose_top.go @@ -82,7 +82,7 @@ func composeTopAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - fmt.Fprintf(stdout, "%s\n", info.Labels[labels.Name]) + fmt.Fprintln(stdout, info.Labels[labels.Name]) // `compose ps` uses empty ps args err = container.Top(ctx, client, []string{c.ID()}, types.ContainerTopOptions{ Stdout: cmd.OutOrStdout(), diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container_list.go index 5422b76d860..f203900a2e0 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container_list.go @@ -198,7 +198,7 @@ func formatAndPrintContainerInfo(containers []container.ListItem, options Format return err } } else if options.Quiet { - if _, err := fmt.Fprintf(w, "%s\n", c.ID); err != nil { + if _, err := fmt.Fprintln(w, c.ID); err != nil { return err } } else { diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index df6e4521806..2c2a97c1a3f 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -378,7 +378,7 @@ func runAction(cmd *cobra.Command, args []string) error { } if createOpt.Detach { - fmt.Fprintf(createOpt.Stdout, "%s\n", id) + fmt.Fprintln(createOpt.Stdout, id) return nil } if createOpt.TTY { diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index 890573044ef..c18cd8f08ee 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -223,7 +223,7 @@ func (x *historyPrinter) printHistory(p historyPrintable) error { return err } } else if x.quiet { - if _, err := fmt.Fprintf(x.w, "%s\n", p.Snapshot); err != nil { + if _, err := fmt.Fprintln(x.w, p.Snapshot); err != nil { return err } } else { diff --git a/cmd/nerdctl/version.go b/cmd/nerdctl/version.go index ac9c4d6097d..f74a9d44846 100644 --- a/cmd/nerdctl/version.go +++ b/cmd/nerdctl/version.go @@ -76,7 +76,7 @@ func versionAction(cmd *cobra.Command, args []string) error { return err } } else { - fmt.Fprintf(w, "Client:\n") + fmt.Fprintln(w, "Client:") fmt.Fprintf(w, " Version:\t%s\n", v.Client.Version) fmt.Fprintf(w, " OS/Arch:\t%s/%s\n", v.Client.Os, v.Client.Arch) fmt.Fprintf(w, " Git commit:\t%s\n", v.Client.GitCommit) @@ -88,8 +88,8 @@ func versionAction(cmd *cobra.Command, args []string) error { } } if v.Server != nil { - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "Server:\n") + fmt.Fprintln(w) + fmt.Fprintln(w, "Server:") for _, compo := range v.Server.Components { fmt.Fprintf(w, " %s:\n", compo.Name) fmt.Fprintf(w, " Version:\t%s\n", compo.Version) diff --git a/pkg/cmd/container/commit.go b/pkg/cmd/container/commit.go index 2b9a556fcd7..1dd6fc3ecc7 100644 --- a/pkg/cmd/container/commit.go +++ b/pkg/cmd/container/commit.go @@ -60,7 +60,7 @@ func Commit(ctx context.Context, client *containerd.Client, rawRef string, req s if err != nil { return err } - _, err = fmt.Fprintf(options.Stdout, "%s\n", imageID) + _, err = fmt.Fprintln(options.Stdout, imageID) return err }, } diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index a4c3ecd388e..9666faae6cd 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -57,7 +57,7 @@ func Kill(ctx context.Context, client *containerd.Client, reqs []string, options } return err } - _, err := fmt.Fprintf(options.Stdout, "%s\n", found.Container.ID()) + _, err := fmt.Fprintln(options.Stdout, found.Container.ID()) return err }, } diff --git a/pkg/cmd/container/pause.go b/pkg/cmd/container/pause.go index 86cd5130298..8a18a35ba41 100644 --- a/pkg/cmd/container/pause.go +++ b/pkg/cmd/container/pause.go @@ -38,7 +38,7 @@ func Pause(ctx context.Context, client *containerd.Client, reqs []string, option return err } - _, err := fmt.Fprintf(options.Stdout, "%s\n", found.Req) + _, err := fmt.Fprintln(options.Stdout, found.Req) return err }, } diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 90c0ef5231e..81a7d851ccb 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -75,7 +75,7 @@ func Remove(ctx context.Context, client *containerd.Client, containers []string, } return err } - _, err := fmt.Fprintf(options.Stdout, "%s\n", found.Req) + _, err := fmt.Fprintln(options.Stdout, found.Req) return err }, } diff --git a/pkg/cmd/container/restart.go b/pkg/cmd/container/restart.go index 068a11a8001..5547074d128 100644 --- a/pkg/cmd/container/restart.go +++ b/pkg/cmd/container/restart.go @@ -40,7 +40,7 @@ func Restart(ctx context.Context, client *containerd.Client, containers []string if err := containerutil.Start(ctx, found.Container, false, client, ""); err != nil { return err } - _, err := fmt.Fprintf(options.Stdout, "%s\n", found.Req) + _, err := fmt.Fprintln(options.Stdout, found.Req) return err }, } diff --git a/pkg/cmd/container/start.go b/pkg/cmd/container/start.go index c4b98e8d09b..7267972b614 100644 --- a/pkg/cmd/container/start.go +++ b/pkg/cmd/container/start.go @@ -43,7 +43,7 @@ func Start(ctx context.Context, client *containerd.Client, reqs []string, option return err } if !options.Attach { - _, err := fmt.Fprintf(options.Stdout, "%s\n", found.Req) + _, err := fmt.Fprintln(options.Stdout, found.Req) if err != nil { return err } diff --git a/pkg/cmd/container/stop.go b/pkg/cmd/container/stop.go index 2a836da7bf0..25b78a9d769 100644 --- a/pkg/cmd/container/stop.go +++ b/pkg/cmd/container/stop.go @@ -42,7 +42,7 @@ func Stop(ctx context.Context, client *containerd.Client, reqs []string, opt typ } return err } - _, err := fmt.Fprintf(opt.Stdout, "%s\n", found.Req) + _, err := fmt.Fprintln(opt.Stdout, found.Req) return err }, } diff --git a/pkg/cmd/container/unpause.go b/pkg/cmd/container/unpause.go index 7f57dd59038..f8044ba5992 100644 --- a/pkg/cmd/container/unpause.go +++ b/pkg/cmd/container/unpause.go @@ -38,7 +38,7 @@ func Unpause(ctx context.Context, client *containerd.Client, reqs []string, opti return err } - _, err := fmt.Fprintf(options.Stdout, "%s\n", found.Req) + _, err := fmt.Fprintln(options.Stdout, found.Req) return err }, } diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 279e7074c4f..27f69cec1cc 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -268,7 +268,7 @@ func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images. return err } } else if x.quiet { - if _, err := fmt.Fprintf(x.w, "%s\n", p.ID); err != nil { + if _, err := fmt.Fprintln(x.w, p.ID); err != nil { return err } } else { diff --git a/pkg/cmd/namespace/remove.go b/pkg/cmd/namespace/remove.go index 130e302b9b2..4c1ca7ae29e 100644 --- a/pkg/cmd/namespace/remove.go +++ b/pkg/cmd/namespace/remove.go @@ -43,7 +43,7 @@ func Remove(ctx context.Context, client *containerd.Client, deletedNamespaces [] continue } } - _, err := fmt.Fprintf(options.Stdout, "%s\n", target) + _, err := fmt.Fprintln(options.Stdout, target) return err } return exitErr diff --git a/pkg/cmd/network/create.go b/pkg/cmd/network/create.go index f592a5ee62b..4c0cc65d020 100644 --- a/pkg/cmd/network/create.go +++ b/pkg/cmd/network/create.go @@ -43,6 +43,6 @@ func Create(options types.NetworkCreateOptions, stdout io.Writer) error { } return err } - _, err = fmt.Fprintf(stdout, "%s\n", *net.NerdctlID) + _, err = fmt.Fprintln(stdout, *net.NerdctlID) return err } diff --git a/pkg/cmd/system/info.go b/pkg/cmd/system/info.go index 04dfe1b1df3..d7d1cecc2d0 100644 --- a/pkg/cmd/system/info.go +++ b/pkg/cmd/system/info.go @@ -84,7 +84,7 @@ func Info(ctx context.Context, client *containerd.Client, options types.SystemIn if err := tmpl.Execute(w, x); err != nil { return err } - _, err = fmt.Fprintf(w, "\n") + _, err = fmt.Fprintln(w) return err } @@ -130,7 +130,7 @@ func prettyPrintInfoNative(w io.Writer, info *native.Info) error { } sort.Slice(enabledPlugins, sorter(enabledPlugins)) sort.Slice(disabledPlugins, sorter(disabledPlugins)) - fmt.Fprintf(w, "containerd Plugins:\n") + fmt.Fprintln(w, "containerd Plugins:") for _, f := range enabledPlugins { fmt.Fprintf(w, " - %s.%s\n", f.Type, f.ID) } @@ -147,7 +147,7 @@ func prettyPrintInfoDockerCompat(stdout io.Writer, stderr io.Writer, info *docke fmt.Fprintf(w, "Client:\n") fmt.Fprintf(w, " Namespace:\t%s\n", globalOptions.Namespace) fmt.Fprintf(w, " Debug Mode:\t%v\n", debug) - fmt.Fprintf(w, "\n") + fmt.Fprintln(w) fmt.Fprintf(w, "Server:\n") fmt.Fprintf(w, " Server Version: %s\n", info.ServerVersion) // Storage Driver is not really Server concept for nerdctl, but mimics `docker info` output diff --git a/pkg/cmd/volume/create.go b/pkg/cmd/volume/create.go index 4726fc1ad66..77290f9d666 100644 --- a/pkg/cmd/volume/create.go +++ b/pkg/cmd/volume/create.go @@ -44,6 +44,6 @@ func Create(name string, options types.VolumeCreateOptions) (*native.Volume, err if err != nil { return nil, err } - fmt.Fprintf(options.Stdout, "%s\n", name) + fmt.Fprintln(options.Stdout, name) return vol, nil } diff --git a/pkg/composer/pause.go b/pkg/composer/pause.go index 6f94cd60ffb..51a05503b62 100644 --- a/pkg/composer/pause.go +++ b/pkg/composer/pause.go @@ -55,7 +55,7 @@ func (c *Composer) Pause(ctx context.Context, services []string, writer io.Write mu.Lock() defer mu.Unlock() - _, err = fmt.Fprintf(writer, "%s\n", info.Labels[labels.Name]) + _, err = fmt.Fprintln(writer, info.Labels[labels.Name]) return err }) @@ -91,7 +91,7 @@ func (c *Composer) Unpause(ctx context.Context, services []string, writer io.Wri mu.Lock() defer mu.Unlock() - _, err = fmt.Fprintf(writer, "%s\n", info.Labels[labels.Name]) + _, err = fmt.Fprintln(writer, info.Labels[labels.Name]) return err }) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index d49b12bbfb0..6e4499a3269 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -517,7 +517,7 @@ func writePidFile(path string, pid int) error { if err != nil { return err } - _, err = fmt.Fprintf(f, "%d", pid) + _, err = fmt.Fprint(f, pid) f.Close() if err != nil { return err From 2cbb162bc8bda2b9f320ef92b4921fa24029d4c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 22:29:39 +0000 Subject: [PATCH 0104/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.2.3 to 0.2.4. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.2.3...v0.2.4) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f2a157b7a51..1e0ef119dbf 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/containernetworking/plugins v1.3.0 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.2.3 + github.com/cyphar/filepath-securejoin v0.2.4 github.com/docker/cli v24.0.6+incompatible github.com/docker/docker v24.0.6+incompatible github.com/docker/go-connections v0.4.0 diff --git a/go.sum b/go.sum index 12d34b95cc9..ae9c563d516 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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= From a976067cf11702486d22bf5055f329f0468b2db2 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 7 Sep 2023 15:16:39 +0000 Subject: [PATCH 0105/1066] fix bash completion of volume rm Signed-off-by: Kay Yan --- cmd/nerdctl/completion_linux_test.go | 7 +++++++ cmd/nerdctl/volume_list.go | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/completion_linux_test.go b/cmd/nerdctl/completion_linux_test.go index ea0edc4c926..20b95f7f412 100644 --- a/cmd/nerdctl/completion_linux_test.go +++ b/cmd/nerdctl/completion_linux_test.go @@ -54,6 +54,13 @@ func TestCompletion(t *testing.T) { base.Cmd(gsc, "network", "rm", "").AssertOutContains(testNetworkName) base.Cmd(gsc, "run", "--net", "").AssertOutContains(testNetworkName) + // Tests with a volume + testVolumekName := "nerdctl-test-completion" + defer base.Cmd("volume", "rm", testVolumekName).Run() + base.Cmd("volume", "create", testVolumekName).AssertOK() + base.Cmd(gsc, "volume", "inspect", "").AssertOutContains(testVolumekName) + base.Cmd(gsc, "volume", "rm", "").AssertOutContains(testVolumekName) + // Tests with raw base (without Args={"--namespace=nerdctl-test"}) rawBase := testutil.NewBase(t) rawBase.Args = nil // unset "--namespace=nerdctl-test" diff --git a/cmd/nerdctl/volume_list.go b/cmd/nerdctl/volume_list.go index 847eba092e0..163c5da4427 100644 --- a/cmd/nerdctl/volume_list.go +++ b/cmd/nerdctl/volume_list.go @@ -87,7 +87,8 @@ func volumeLsAction(cmd *cobra.Command, args []string) error { func getVolumes(cmd *cobra.Command, globalOptions types.GlobalCommandOptions) (map[string]native.Volume, error) { volumeSize, err := cmd.Flags().GetBool("size") if err != nil { - return nil, err + // The `nerdctl volume rm` does not have the flag `size`, so set it to false as the default value. + volumeSize = false } return volume.Volumes(globalOptions.Namespace, globalOptions.DataRoot, globalOptions.Address, volumeSize, nil) } From bc7edb76c509534d9f90af249d257532105add74 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 8 Sep 2023 20:15:55 +0900 Subject: [PATCH 0106/1066] MAINTAINERS: add Kay Yan (yankay) as a REVIEWER Signed-off-by: Akihiro Suda --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1bdc6f9e2cf..ddee8a402a3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23,3 +23,4 @@ "yuchanns", "Hanchin Hsieh", "me@yuchanns.xyz","" "manugupt1", "Manu Gupta", "manugupt1@gmail.com","FCA9 504A 4118 EA5C F466 CC30 A5C3 A8F4 E7FE 9E10" "djdongjin", "Jin Dong", "djdongjin95@gmail.com","" +"yankay", "Kay Yan", "kay.yan@daocloud.io", "" From fe87f8b70d735c9ec3e829f48665b3cf1bc2dfd0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 22:56:41 +0000 Subject: [PATCH 0107/1066] build(deps): bump docker/build-push-action from 4.1.1 to 4.2.1 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.1.1 to 4.2.1. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v4.1.1...v4.2.1) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 9b586a74e08..51454173949 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -59,7 +59,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v4.1.1 + uses: docker/build-push-action@v4.2.1 with: context: . platforms: linux/amd64,linux/arm64 From 248b2b3ad6fb87f80494ee17c9daa5b243f43b9d Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Tue, 12 Sep 2023 10:28:59 +0200 Subject: [PATCH 0108/1066] remove useless option from containerd-rootless-setuptool Signed-off-by: fahed dorgaa --- extras/rootless/containerd-rootless-setuptool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/rootless/containerd-rootless-setuptool.sh b/extras/rootless/containerd-rootless-setuptool.sh index 6a26d07f639..6ce786c2808 100755 --- a/extras/rootless/containerd-rootless-setuptool.sh +++ b/extras/rootless/containerd-rootless-setuptool.sh @@ -150,7 +150,7 @@ show_systemd_error() { unit="$1" n="20" ERROR "Failed to start ${unit}. Run \`journalctl -n ${n} --no-pager --user --unit ${unit}\` to show the error log." - ERROR "Before retrying installation, you might need to uninstall the current setup: \`$0 uninstall -f ; ${BIN}/rootlesskit rm -rf ${HOME}/.local/share/containerd\`" + ERROR "Before retrying installation, you might need to uninstall the current setup: \`$0 uninstall; ${BIN}/rootlesskit rm -rf ${HOME}/.local/share/containerd\`" } install_systemd_unit() { From 68b58d8a9fa3849450a6996a3efd41f256edb816 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 22:37:54 +0000 Subject: [PATCH 0109/1066] build(deps): bump github.com/compose-spec/compose-go Bumps [github.com/compose-spec/compose-go](https://github.com/compose-spec/compose-go) from 1.18.2 to 1.18.4. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v1.18.2...v1.18.4) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: Akihiro Suda --- go.mod | 5 +++-- go.sum | 9 +++++---- pkg/composer/composer.go | 6 +++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 1e0ef119dbf..9b298bff463 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.10.0 github.com/awslabs/soci-snapshotter v0.4.0 - github.com/compose-spec/compose-go v1.18.2 + github.com/compose-spec/compose-go v1.18.4 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 @@ -62,8 +62,10 @@ require ( ) require ( + github.com/distribution/reference v0.5.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) require ( @@ -76,7 +78,6 @@ require ( github.com/containerd/ttrpc v1.2.2 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect github.com/containers/ocicrypt v1.1.8 // indirect - github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa // indirect 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 diff --git a/go.sum b/go.sum index ae9c563d516..bb51f6dadf5 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go v1.18.2 h1:ZxiSvB9K4coRs39wgGeWOwfjgziOpOQT+etJ4MB3PRA= -github.com/compose-spec/compose-go v1.18.2/go.mod h1:zR2tP1+kZHi5vJz7PjpW6oMoDji/Js3GHjP+hfjf70Q= +github.com/compose-spec/compose-go v1.18.4 h1:yLYfsc3ATAYZVAJcXyx/V847/JVBmf3pfKfR13mXU4s= +github.com/compose-spec/compose-go v1.18.4/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= github.com/containerd/accelerated-container-image v0.6.7 h1:QDO12lgUubiUq0ogMzcL6CdSxkzFOX7vVaSIXAJ9EaM= github.com/containerd/accelerated-container-image v0.6.7/go.mod h1:a7MYTlNhR4+GGpXD7wuNSgxrwC2wE2rgUfCvef+FQzg= github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= @@ -76,8 +76,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/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa h1:L9Ay/slwQ4ERSPaurC+TVkZrM0K98GNrEEo1En3e8as= -github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= +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/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.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= @@ -451,6 +451,7 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= diff --git a/pkg/composer/composer.go b/pkg/composer/composer.go index ef60632d96d..a01fc41576e 100644 --- a/pkg/composer/composer.go +++ b/pkg/composer/composer.go @@ -70,12 +70,16 @@ func New(o Options, client *containerd.Client) (*Composer, error) { optionsFn = append(optionsFn, composecli.WithOsEnv, composecli.WithWorkingDirectory(o.ProjectDirectory), - composecli.WithEnvFile(o.EnvFile), composecli.WithConfigFileEnv, composecli.WithDefaultConfigPath, composecli.WithDotEnv, composecli.WithName(o.Project), ) + if o.EnvFile != "" { + optionsFn = append(optionsFn, + composecli.WithEnvFiles(o.EnvFile), + ) + } projectOptions, err := composecli.NewProjectOptions(o.ConfigPaths, optionsFn...) if err != nil { From 03cb689c39021a9a63e771dff98668aee78a6474 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 22:04:39 +0000 Subject: [PATCH 0110/1066] build(deps): bump docker/build-push-action from 4.2.1 to 5.0.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.2.1 to 5.0.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v4.2.1...v5.0.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 51454173949..fec2b79df0e 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -59,7 +59,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v4.2.1 + uses: docker/build-push-action@v5.0.0 with: context: . platforms: linux/amd64,linux/arm64 From ebede8d06932710d37e443b877551fb1f6505ccf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 22:04:42 +0000 Subject: [PATCH 0111/1066] build(deps): bump docker/setup-buildx-action from 2 to 3 Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 51454173949..313503cac42 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -36,7 +36,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 # Login against a Docker registry except on PR # https://github.com/docker/login-action From 765711c496275399c47205ec9cf9ea3c9574d39c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 22:04:49 +0000 Subject: [PATCH 0112/1066] build(deps): bump docker/metadata-action from 4.6.0 to 5.0.0 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4.6.0 to 5.0.0. - [Release notes](https://github.com/docker/metadata-action/releases) - [Upgrade guide](https://github.com/docker/metadata-action/blob/master/UPGRADE.md) - [Commits](https://github.com/docker/metadata-action/compare/v4.6.0...v5.0.0) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 51454173949..92470845e2f 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -52,7 +52,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v4.6.0 + uses: docker/metadata-action@v5.0.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} From 81f4dba58767245348a57bf82d439958a2eb1319 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 23:59:10 +0000 Subject: [PATCH 0113/1066] build(deps): bump docker/setup-qemu-action from 2 to 3 Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 94d8a375a2b..1fccf6d25eb 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -33,7 +33,7 @@ jobs: uses: actions/checkout@v4.0.0 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 From c373e1bcb3684b89614548786dedcb3339922491 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 23:59:25 +0000 Subject: [PATCH 0114/1066] build(deps): bump docker/login-action from 2.2.0 to 3.0.0 Bumps [docker/login-action](https://github.com/docker/login-action) from 2.2.0 to 3.0.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v2.2.0...v3.0.0) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 94d8a375a2b..c7779a5e877 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -42,7 +42,7 @@ jobs: # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} if: github.event_name != 'pull_request' - uses: docker/login-action@v2.2.0 + uses: docker/login-action@v3.0.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} From 6d77b40b5356cd5dbce158779203fa7193c0962a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 22:17:12 +0000 Subject: [PATCH 0115/1066] build(deps): bump github.com/containerd/containerd from 1.7.5 to 1.7.6 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.5 to 1.7.6. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.5...v1.7.6) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: Akihiro Suda --- go.mod | 16 +++++++--------- go.sum | 10 ++++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 9b298bff463..47501a32fac 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,13 @@ go 1.20 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 - github.com/Microsoft/hcsshim v0.10.0 + github.com/Microsoft/hcsshim v0.11.0 github.com/awslabs/soci-snapshotter v0.4.0 github.com/compose-spec/compose-go v1.18.4 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 - github.com/containerd/containerd v1.7.5 + github.com/containerd/containerd v1.7.6 github.com/containerd/continuity v0.4.2 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 @@ -61,23 +61,18 @@ require ( gotest.tools/v3 v3.5.0 ) -require ( - github.com/distribution/reference v0.5.0 // indirect - go.opentelemetry.io/otel/metric v1.16.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // 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 github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/cilium/ebpf v0.9.1 // indirect + github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/ttrpc v1.2.2 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect github.com/containers/ocicrypt v1.1.8 // indirect + github.com/distribution/reference v0.5.0 // indirect 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 @@ -127,12 +122,15 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.16.0 // indirect + go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/trace v1.16.0 // indirect golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/tools v0.11.0 // indirect google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect google.golang.org/grpc v1.56.2 // indirect google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/go.sum b/go.sum index bb51f6dadf5..604f0f95b8b 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 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.10.0 h1:PbvoxdUGgXxyirmN5Oncp3POLkxEG5LbWCEBfWmHTGA= -github.com/Microsoft/hcsshim v0.10.0/go.mod h1:3j1trOamcUdi86J5Tr5+1BpqMjSv/QeRWkX2whBF6dY= +github.com/Microsoft/hcsshim v0.11.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= +github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= github.com/awslabs/soci-snapshotter v0.4.0 h1:dA9lOYbzSUaYMahB8qXQZTVXUszhc0w8rwjRs6EPd24= github.com/awslabs/soci-snapshotter v0.4.0/go.mod h1:+ST8F4E/b6b6pnFBJKprdvzkxyXODMs0FC2TmclkgJc= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= @@ -30,12 +30,14 @@ github.com/compose-spec/compose-go v1.18.4 h1:yLYfsc3ATAYZVAJcXyx/V847/JVBmf3pfK github.com/compose-spec/compose-go v1.18.4/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= github.com/containerd/accelerated-container-image v0.6.7 h1:QDO12lgUubiUq0ogMzcL6CdSxkzFOX7vVaSIXAJ9EaM= github.com/containerd/accelerated-container-image v0.6.7/go.mod h1:a7MYTlNhR4+GGpXD7wuNSgxrwC2wE2rgUfCvef+FQzg= +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.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.5 h1:i9T9XpAWMe11BHMN7pu1BZqOGjXaKTPyz2v+KYOZgkY= -github.com/containerd/containerd v1.7.5/go.mod h1:ieJNCSzASw2shSGYLHx8NAE7WsZ/gEigo5fQ78W5Zvw= +github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8= +github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= From 1e0b0bbfb24b85fa66992aca21afa49759c8018f Mon Sep 17 00:00:00 2001 From: zhuangqh Date: Mon, 11 Sep 2023 20:31:06 +0800 Subject: [PATCH 0116/1066] image: dedup same platform entry Signed-off-by: zhuangqh --- pkg/cmd/image/list.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 27f69cec1cc..5bd0a117005 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "io" + "path" "strings" "text/tabwriter" "text/template" @@ -197,7 +198,13 @@ func (x *imagePrinter) printImage(ctx context.Context, img images.Image) error { logrus.WithError(err).Warnf("failed to get the platform list of image %q", img.Name) return x.printImageSinglePlatform(ctx, img, platforms.DefaultSpec()) } + psm := map[string]struct{}{} for _, ociPlatform := range ociPlatforms { + platformKey := makePlatformKey(ociPlatform) + if _, done := psm[platformKey]; done { + continue + } + psm[platformKey] = struct{}{} if err := x.printImageSinglePlatform(ctx, img, ociPlatform); err != nil { logrus.WithError(err).Warnf("failed to get platform %q of image %q", platforms.Format(ociPlatform), img.Name) } @@ -205,6 +212,14 @@ func (x *imagePrinter) printImage(ctx context.Context, img images.Image) error { return nil } +func makePlatformKey(platform v1.Platform) string { + if platform.OS == "" { + return "unknown" + } + + return path.Join(platform.OS, platform.Architecture, platform.OSVersion, platform.Variant) +} + func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images.Image, ociPlatform v1.Platform) error { platMC := platforms.OnlyStrict(ociPlatform) if avail, _, _, _, availErr := images.Check(ctx, x.contentStore, img.Target, platMC); !avail { From e4a2ceb72895345b2a1b1e9ab8d8dad54fbd385e Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:01:54 +0900 Subject: [PATCH 0117/1066] update containerd (1.7.6) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 91466a18ef3..cef53d8973a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,9 +79,9 @@ jobs: - ubuntu: 20.04 containerd: v1.6.22 - ubuntu: 20.04 - containerd: v1.7.3 + containerd: v1.7.6 - ubuntu: 22.04 - containerd: v1.7.3 + containerd: v1.7.6 - ubuntu: 22.04 containerd: main env: @@ -116,10 +116,10 @@ jobs: containerd: v1.6.22 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.3 + containerd: v1.7.6 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.3 + containerd: v1.7.6 target: test-integration-rootless - ubuntu: 22.04 containerd: main @@ -128,10 +128,10 @@ jobs: containerd: v1.6.22 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.3 + containerd: v1.7.6 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.3 + containerd: v1.7.6 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main @@ -221,7 +221,7 @@ jobs: - uses: actions/checkout@v4.0.0 with: repository: containerd/containerd - ref: v1.7.3 + ref: v1.7.6 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -229,7 +229,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.3 + ctrdVersion: 1.7.6 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" From bcface0790ddc88468b347fbb20ccd5599d5fe32 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:03:30 +0900 Subject: [PATCH 0118/1066] update BuildKit (0.12.2) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.0 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.2 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.2 diff --git a/Dockerfile b/Dockerfile index 6328ca1c960..106bb201fce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.9 ARG CNI_PLUGINS_VERSION=v1.3.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.12.0 +ARG BUILDKIT_VERSION=v0.12.2 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.14.3 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.0 deleted file mode 100644 index ee8f1b2bd41..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.0 +++ /dev/null @@ -1,2 +0,0 @@ -77db8cb0b88d54a5524548de125f83d909e2a1693791642d50d56639a1632ecf buildkit-v0.12.0.linux-amd64.tar.gz -f6d0d49ff366ad2199e3da2e8622dbe02f46707bdb572612507f5a2d3b84d016 buildkit-v0.12.0.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.2 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.2 new file mode 100644 index 00000000000..2c9236831c1 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.2 @@ -0,0 +1,2 @@ +c856bb4e6584d75ca6b2a7b6e946b7b14628e82bf1eccb4a43bc731bbc8e67ea buildkit-v0.12.2.linux-amd64.tar.gz +78846e12435f00e0ee5b9ca0af28ec78691fa712ebe7d2c799ec8a074c791969 buildkit-v0.12.2.linux-arm64.tar.gz From 822f115424b8cfa5376120295b45267f10a38ad6 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:05:21 +0900 Subject: [PATCH 0119/1066] update imgcrypt (1.1.8) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 106bb201fce..b9fe7147914 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ ARG BUILDKIT_VERSION=v0.12.2 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.14.3 # Extra deps: Encryption -ARG IMGCRYPT_VERSION=v1.1.7 +ARG IMGCRYPT_VERSION=v1.1.8 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v1.1.0 ARG SLIRP4NETNS_VERSION=v1.2.0 From 70b1ba314c5b811191d2f4627fdf3c01f291799f Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:06:31 +0900 Subject: [PATCH 0120/1066] update RootlessKit (1.1.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/rootlesskit-v1.1.0 | 6 ------ Dockerfile.d/SHA256SUMS.d/rootlesskit-v1.1.1 | 6 ++++++ 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v1.1.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v1.1.1 diff --git a/Dockerfile b/Dockerfile index b9fe7147914..19309f4275d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.14.3 # Extra deps: Encryption ARG IMGCRYPT_VERSION=v1.1.8 # Extra deps: Rootless -ARG ROOTLESSKIT_VERSION=v1.1.0 +ARG ROOTLESSKIT_VERSION=v1.1.1 ARG SLIRP4NETNS_VERSION=v1.2.0 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.3.0 diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v1.1.0 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v1.1.0 deleted file mode 100644 index 0a944324c85..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v1.1.0 +++ /dev/null @@ -1,6 +0,0 @@ -3e5e0dd91f53fda3591098de368727297b56ce86ce4c121fac483251b72069bd rootlesskit-aarch64.tar.gz -d4faf36efa88d2b9ea7f2506873fc3562e8d030da18106e9c8eb6d84d4b3edc8 rootlesskit-armv7l.tar.gz -e47a019fdfa043ddcff8aee2593383c66935874e8328d7a8138966a28106b70f rootlesskit-ppc64le.tar.gz -9f15b93ff7b991705db5eafe769405393ecee51c7adb553f9c255c01cfb92d9a rootlesskit-riscv64.tar.gz -0072436fb718c79b3bea02b3d6003939a9f4cb6d0bedf3d31f14c8b4456a6b49 rootlesskit-s390x.tar.gz -503257d14960ff04b5c90c14a4f4f3410244a1468c144430251c87971ac714d4 rootlesskit-x86_64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v1.1.1 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v1.1.1 new file mode 100644 index 00000000000..73980f90118 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v1.1.1 @@ -0,0 +1,6 @@ +b74c577abd6ad721e0b7e10a74f4c5ac26cb3afe005ad3d28d4d7912c356079f rootlesskit-aarch64.tar.gz +95c27e6808c942c67ab93d94e37bada3a62cfc47de848101889f8e3ba5c9f7dd rootlesskit-armv7l.tar.gz +df35c74cd030e1b3978f28d1cb7c909da2ab962fb0c9369463d43a89b9f16cc2 rootlesskit-ppc64le.tar.gz +79af3e96e9d6deddc5faa4680de7e28120ae333386c48a30e79fe156f17bad9b rootlesskit-riscv64.tar.gz +32da9a11b67340ff498de8a3268673277a1e1d9e9d8d5f619bbf09305beaaa6c rootlesskit-s390x.tar.gz +3c83affbb405cafe2d32e2e24462af9b4dcfa19e3809030012ad0d4e3fd49e8f rootlesskit-x86_64.tar.gz From bdb2c0068c24e921431f7e64b3f9e9083e7c9afc Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:11:53 +0900 Subject: [PATCH 0121/1066] update slirp4netns (1.2.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.0 | 6 ------ Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.1 | 6 ++++++ 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.1 diff --git a/Dockerfile b/Dockerfile index 19309f4275d..10708ce2d60 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.14.3 ARG IMGCRYPT_VERSION=v1.1.8 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v1.1.1 -ARG SLIRP4NETNS_VERSION=v1.2.0 +ARG SLIRP4NETNS_VERSION=v1.2.1 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.3.0 # Extra deps: FUSE-OverlayFS diff --git a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.0 b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.0 deleted file mode 100644 index 77c7008dec2..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.0 +++ /dev/null @@ -1,6 +0,0 @@ -fb82c4a8e63fe1acc0bdc92300080b8c80e514e409dc70fd593045df644ac306 slirp4netns-aarch64 -31e2555c320746083c11c959f88313b5ac277a79a804b8c59c4b030b2ba8f41b slirp4netns-armv7l -dcae54bc1ab854bb71aa98c9ec2ad86f6817acaa75910ccf7d899219fa926cea slirp4netns-ppc64le -2d420e3e1ab51526d9e05ce0020a505775ffcf00f64d5244973a0e0602d8c864 slirp4netns-riscv64 -65925c8d6bea7bd380a6271b06ca63dab425599ab759eb055072cff9d7f33fb9 slirp4netns-s390x -11080fdfb2c47b99f2b0c2b72d92cc64400d0eaba11c1ec34f779e17e8844360 slirp4netns-x86_64 diff --git a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.1 b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.1 new file mode 100644 index 00000000000..2d6ef565aa6 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.1 @@ -0,0 +1,6 @@ +da4d301ffe36a0edf1cc769059c1f89eadd1afeba285636bcb2f250a6cffffed slirp4netns-aarch64 +0a540774fd15bdb39cb07d0b9f1e1968640c822cacf879abf0d1a3966f98d30d slirp4netns-armv7l +b8c8a1747524ae79c9df9fa21c5d436dca7e5a777de552f8b5dabb1c9a60b941 slirp4netns-ppc64le +de4c50f9ee29bef7c756d8487ed1ae5694825d853ba96908de23eea6f806431a slirp4netns-riscv64 +55fe4b10e7279ba4d780091d3a259ff080dc974811e060753599e0d2ba8520a5 slirp4netns-s390x +cb1d7b7f9bc946c6179efdb8e069d5ee673c3f135668da6bf54f2ed689981833 slirp4netns-x86_64 From ee1ac8f092aad10929be3c34232908b81bf66874 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:13:30 +0900 Subject: [PATCH 0122/1066] update fuse-overlayfs (1.13) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.12 | 6 ------ Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.13 | 6 ++++++ 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.12 create mode 100644 Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.13 diff --git a/Dockerfile b/Dockerfile index 10708ce2d60..53368fc5d4e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,7 +34,7 @@ ARG SLIRP4NETNS_VERSION=v1.2.1 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.3.0 # Extra deps: FUSE-OverlayFS -ARG FUSE_OVERLAYFS_VERSION=v1.12 +ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.6 # Extra deps: IPFS ARG KUBO_VERSION=v0.21.0 diff --git a/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.12 b/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.12 deleted file mode 100644 index 5da63cd7e47..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.12 +++ /dev/null @@ -1,6 +0,0 @@ -6d2813904de47350adf6d61998c97d5c262fc01b4cf4a0b70be21097aa2acda4 fuse-overlayfs-aarch64 -357763baab2e4cfd7de07e0683252d5ea0dde5e5c7bd8aba99662e25f5e63329 fuse-overlayfs-armv7l -5b781adc8861f095719a3d61d936621f8a17bf68cc78c73c0e693dafb679831f fuse-overlayfs-ppc64le -8b147b181c068c858bb8e8c4966817f3f884d9aad6ee7860f2a46e82c70d02ba fuse-overlayfs-riscv64 -e3fabc7529071e490b0a5e4848feaf3a0d984b50ebe84f0c4e4686503e1d5f07 fuse-overlayfs-s390x -152318f61b1fbe91ddaef42ed31f4a173d288af1376484bc54aff892c53f4a90 fuse-overlayfs-x86_64 diff --git a/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.13 b/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.13 new file mode 100644 index 00000000000..1a6d275766c --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.13 @@ -0,0 +1,6 @@ +ab8685073e6daef4d8935e878cd55a8350dd0299eea1d3249684a548ad6394bf fuse-overlayfs-aarch64 +ffaaa64b858e6fe10a1f00d02c0e598556ad0fc85165f740cd5bb08eeb991142 fuse-overlayfs-armv7l +fa078140cb1caf85849559af56f654d351973f63a47b1613422d02d28b8c4f8b fuse-overlayfs-ppc64le +06c9dc13d2c0afdb0ee3007d0ebb5cec64feaaa4a79497d08b1f2cfcb6316a43 fuse-overlayfs-riscv64 +322d48a0e98b34715e4857b826b91ae510d7e56fa1fbd7b4d0a6bbae5a01435c fuse-overlayfs-s390x +0011ad825dc0274b6e330fb9a8d3d578ea7bbf738bab08934b90be070b8d0a4a fuse-overlayfs-x86_64 From c5794dd605ffacf4ebd61f61a63a935fc47ccdcb Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:15:13 +0900 Subject: [PATCH 0123/1066] update Kubo (0.22.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/kubo-v0.21.0 | 3 --- Dockerfile.d/SHA256SUMS.d/kubo-v0.22.0 | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/kubo-v0.21.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/kubo-v0.22.0 diff --git a/Dockerfile b/Dockerfile index 53368fc5d4e..3048beb8bca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ ARG BYPASS4NETNS_VERSION=v0.3.0 ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.6 # Extra deps: IPFS -ARG KUBO_VERSION=v0.21.0 +ARG KUBO_VERSION=v0.22.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug diff --git a/Dockerfile.d/SHA256SUMS.d/kubo-v0.21.0 b/Dockerfile.d/SHA256SUMS.d/kubo-v0.21.0 deleted file mode 100644 index b6beb01de7f..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/kubo-v0.21.0 +++ /dev/null @@ -1,3 +0,0 @@ -# From https://github.com/ipfs/kubo/releases -b1897919a4f6dd299d6c73dec8e4be98f986e4071eeffaefadf921f26e271c4e kubo_v0.21.0_linux-amd64.tar.gz -702af7aa5dc9117e9bc32b03d13bb872105b74d361f119ce15fdad689a4f1bce kubo_v0.21.0_linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/kubo-v0.22.0 b/Dockerfile.d/SHA256SUMS.d/kubo-v0.22.0 new file mode 100644 index 00000000000..449d89bb7ff --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/kubo-v0.22.0 @@ -0,0 +1,3 @@ +# From https://github.com/ipfs/kubo/releases +d708b484d93e95832105968cfe5b2dff592706d18dbfe41d87df8fcb20512baf kubo_v0.22.0_linux-amd64.tar.gz +505fd3dff8419b81e9e755297a2c614169d86d25b7bd8e3b0af49d1fd771b0c3 kubo_v0.22.0_linux-arm64.tar.gz From b5b1f2a1c788831ff821ddc20bb3e0057958acd5 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:16:29 +0900 Subject: [PATCH 0124/1066] update Nydus (2.2.3) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3048beb8bca..daec20a90ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,7 +48,7 @@ ARG GO_VERSION=1.21 ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.10.1 -ARG NYDUS_VERSION=v2.2.2 +ARG NYDUS_VERSION=v2.2.3 ARG SOCI_SNAPSHOTTER_VERSION=0.3.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.2.1 AS xx From ba3c6b91fa1bba095400d970d4d389b5b8b363a0 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:16:54 +0900 Subject: [PATCH 0125/1066] update soci-snapshotter (0.4.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index daec20a90ff..cc480741ca2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,7 +49,7 @@ ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.10.1 ARG NYDUS_VERSION=v2.2.3 -ARG SOCI_SNAPSHOTTER_VERSION=0.3.0 +ARG SOCI_SNAPSHOTTER_VERSION=0.4.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.2.1 AS xx From be2acea76940d4a09b7bf12b4f9f5a4b9c4809bc Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:18:12 +0900 Subject: [PATCH 0126/1066] update golangci-lint (1.54.2) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cef53d8973a..484d31da6d4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,7 +48,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v3.7.0 with: - version: v1.54.0 + version: v1.54.2 args: --verbose - name: yamllint-lint run: yamllint . From 9d4e5d680977b022e68985325c52a90a30a508f8 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Sep 2023 15:35:37 +0900 Subject: [PATCH 0127/1066] seccomp: rename "default" to "builtin" to follow Docker 23 Docker 23 renamed the "default" profile to "builtin" - https://github.com/moby/moby/commit/ac449d6b5ad29a5086824729ce54eec6b0cc8545 - https://github.com/moby/moby/commit/f8795ed364586acd93f72e206a409e7e0e27edcc Signed-off-by: Akihiro Suda --- cmd/nerdctl/container_run.go | 6 +++++- pkg/cmd/container/run_security_linux.go | 2 +- pkg/defaults/defaults_freebsd.go | 7 +++++-- pkg/defaults/defaults_linux.go | 7 +++++-- pkg/defaults/defaults_windows.go | 7 +++++-- pkg/infoutil/infoutil_linux.go | 2 +- 6 files changed, 22 insertions(+), 9 deletions(-) diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 2c2a97c1a3f..1784161ed98 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -172,7 +172,11 @@ func setCreateFlags(cmd *cobra.Command) { // #region security flags cmd.Flags().StringArray("security-opt", []string{}, "Security options") cmd.RegisterFlagCompletionFunc("security-opt", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"seccomp=", "seccomp=unconfined", "apparmor=", "apparmor=" + defaults.AppArmorProfileName, "apparmor=unconfined", "no-new-privileges", "privileged-without-host-devices"}, cobra.ShellCompDirectiveNoFileComp + return []string{ + "seccomp=", "seccomp=" + defaults.SeccompProfileName, "seccomp=unconfined", + "apparmor=", "apparmor=" + defaults.AppArmorProfileName, "apparmor=unconfined", + "no-new-privileges", + "privileged-without-host-devices"}, cobra.ShellCompDirectiveNoFileComp }) // cap-add and cap-drop are defined as StringSlice, not StringArray, to allow specifying "--cap-add=CAP_SYS_ADMIN,CAP_NET_ADMIN" (compatible with Podman) cmd.Flags().StringSlice("cap-add", []string{}, "Add Linux capabilities") diff --git a/pkg/cmd/container/run_security_linux.go b/pkg/cmd/container/run_security_linux.go index a325c91b87c..66f241e966c 100644 --- a/pkg/cmd/container/run_security_linux.go +++ b/pkg/cmd/container/run_security_linux.go @@ -53,7 +53,7 @@ func generateSecurityOpts(privileged bool, securityOptsMap map[string]string) ([ } } var opts []oci.SpecOpts - if seccompProfile, ok := securityOptsMap["seccomp"]; ok { + if seccompProfile, ok := securityOptsMap["seccomp"]; ok && seccompProfile != defaults.SeccompProfileName { if seccompProfile == "" { return nil, errors.New("invalid security-opt \"seccomp\"") } diff --git a/pkg/defaults/defaults_freebsd.go b/pkg/defaults/defaults_freebsd.go index 620006a5e9a..ec5f3e8421c 100644 --- a/pkg/defaults/defaults_freebsd.go +++ b/pkg/defaults/defaults_freebsd.go @@ -20,8 +20,11 @@ import ( gocni "github.com/containerd/go-cni" ) -const AppArmorProfileName = "" -const Runtime = "wtf.sbk.runj.v1" +const ( + AppArmorProfileName = "" + SeccompProfileName = "" + Runtime = "wtf.sbk.runj.v1" +) func DataRoot() string { return "/var/lib/nerdctl" diff --git a/pkg/defaults/defaults_linux.go b/pkg/defaults/defaults_linux.go index b5a6a462f0a..c931c13893f 100644 --- a/pkg/defaults/defaults_linux.go +++ b/pkg/defaults/defaults_linux.go @@ -28,8 +28,11 @@ import ( "github.com/sirupsen/logrus" ) -const AppArmorProfileName = "nerdctl-default" -const Runtime = plugin.RuntimeRuncV2 +const ( + AppArmorProfileName = "nerdctl-default" + SeccompProfileName = "builtin" + Runtime = plugin.RuntimeRuncV2 +) func DataRoot() string { if !rootlessutil.IsRootless() { diff --git a/pkg/defaults/defaults_windows.go b/pkg/defaults/defaults_windows.go index 7c4a7929dfe..7adcce3fc9c 100644 --- a/pkg/defaults/defaults_windows.go +++ b/pkg/defaults/defaults_windows.go @@ -22,8 +22,11 @@ import ( "path/filepath" ) -const AppArmorProfileName = "" -const Runtime = "io.containerd.runhcs.v1" +const ( + AppArmorProfileName = "" + SeccompProfileName = "" + Runtime = "io.containerd.runhcs.v1" +) func DataRoot() string { return filepath.Join(os.Getenv("ProgramData"), "nerdctl") diff --git a/pkg/infoutil/infoutil_linux.go b/pkg/infoutil/infoutil_linux.go index f7f7ef0d81b..2ed28e22aa9 100644 --- a/pkg/infoutil/infoutil_linux.go +++ b/pkg/infoutil/infoutil_linux.go @@ -49,7 +49,7 @@ WARNING: AppArmor profile %q is not loaded. This warning is negligible if you do not intend to use AppArmor.`), defaults.AppArmorProfileName)) } } - info.SecurityOptions = append(info.SecurityOptions, "name=seccomp,profile=default") + info.SecurityOptions = append(info.SecurityOptions, "name=seccomp,profile="+defaults.SeccompProfileName) if defaults.CgroupnsMode() == "private" { info.SecurityOptions = append(info.SecurityOptions, "name=cgroupns") } From ce611af192e55a8492673ae7f0bdea575c75b5af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 10:12:12 +0000 Subject: [PATCH 0128/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.10.0 to 0.12.0. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.10.0...v0.12.0) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: Akihiro Suda --- go.mod | 5 ++--- go.sum | 23 ++++++++--------------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 47501a32fac..2d0437b8a97 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/containerd/continuity v0.4.2 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 - github.com/containerd/nydus-snapshotter v0.10.0 + github.com/containerd/nydus-snapshotter v0.12.0 github.com/containerd/stargz-snapshotter v0.14.3 github.com/containerd/stargz-snapshotter/estargz v0.14.3 github.com/containerd/stargz-snapshotter/ipfs v0.14.3 @@ -76,7 +76,6 @@ require ( 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 - github.com/frankban/quicktest v1.14.2 // indirect github.com/go-jose/go-jose/v3 v3.0.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -90,6 +89,7 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.16.7 github.com/klauspost/cpuid/v2 v2.1.1 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect @@ -131,6 +131,5 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect google.golang.org/grpc v1.56.2 // indirect google.golang.org/protobuf v1.31.0 // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/go.sum b/go.sum index 604f0f95b8b..5a79cf439bb 100644 --- a/go.sum +++ b/go.sum @@ -46,8 +46,8 @@ github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9 github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= github.com/containerd/imgcrypt v1.1.8 h1:ZS7TuywcRNLoHpU0g+v4/PsKynl6TYlw5xDVWWoIyFA= github.com/containerd/imgcrypt v1.1.8/go.mod h1:x6QvFIkMyO2qGIY2zXc88ivEzcbgvLdWjoZyGqDap5U= -github.com/containerd/nydus-snapshotter v0.10.0 h1:aCQoKmksOmZ2C34znlhOCOlYExiw4s/UPPzbIFKQc8U= -github.com/containerd/nydus-snapshotter v0.10.0/go.mod h1:xEsAzeM0gZEW6POBPOa+1X7EThYsEJNWnO/fhf2moYU= +github.com/containerd/nydus-snapshotter v0.12.0 h1:cpMu3eq+jQjEFKrm+1T5rI74nCthKF7WMxS37DxSYoM= +github.com/containerd/nydus-snapshotter v0.12.0/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= github.com/containerd/stargz-snapshotter v0.14.3/go.mod h1:j2Ya4JeA5gMZJr8BchSkPjlcCEh++auAxp4nidPI6N0= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= @@ -104,8 +104,7 @@ github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= -github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns= -github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= @@ -150,7 +149,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -174,11 +172,8 @@ github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0= github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -250,6 +245,7 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -257,7 +253,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rootless-containers/bypass4netns v0.3.0 h1:UwI55zWDZz7OGyN4YWgfCKdsI58VGY7OlghcLdxJX10= github.com/rootless-containers/bypass4netns v0.3.0/go.mod h1:IXHPjkQlJRygNBCN0hSSR3ITX6kDKr3aAaGHx6APd+g= @@ -450,11 +446,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 78c855e098c3675dc7a5858981e0645ca4ee234c Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Wed, 13 Sep 2023 15:42:40 +0000 Subject: [PATCH 0129/1066] add feature nerdctl compose cp Signed-off-by: Kay Yan --- cmd/nerdctl/compose.go | 1 + cmd/nerdctl/compose_cp.go | 95 ++++++++++++++++ cmd/nerdctl/compose_cp_linux_test.go | 72 ++++++++++++ docs/command-reference.md | 20 ++++ pkg/composer/copy.go | 161 +++++++++++++++++++++++++++ 5 files changed, 349 insertions(+) create mode 100644 cmd/nerdctl/compose_cp.go create mode 100644 cmd/nerdctl/compose_cp_linux_test.go create mode 100644 pkg/composer/copy.go diff --git a/cmd/nerdctl/compose.go b/cmd/nerdctl/compose.go index d806c57cb27..863ce44d59c 100644 --- a/cmd/nerdctl/compose.go +++ b/cmd/nerdctl/compose.go @@ -42,6 +42,7 @@ func newComposeCommand() *cobra.Command { newComposeUpCommand(), newComposeLogsCommand(), newComposeConfigCommand(), + newComposeCopyCommand(), newComposeBuildCommand(), newComposeExecCommand(), newComposeImagesCommand(), diff --git a/cmd/nerdctl/compose_cp.go b/cmd/nerdctl/compose_cp.go new file mode 100644 index 00000000000..7d591cfaef1 --- /dev/null +++ b/cmd/nerdctl/compose_cp.go @@ -0,0 +1,95 @@ +/* + 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 ( + "errors" + + "github.com/containerd/nerdctl/pkg/clientutil" + "github.com/containerd/nerdctl/pkg/cmd/compose" + "github.com/containerd/nerdctl/pkg/composer" + "github.com/spf13/cobra" +) + +func newComposeCopyCommand() *cobra.Command { + usage := `cp [OPTIONS] SERVICE:SRC_PATH DEST_PATH|- + nerdctl compose cp [OPTIONS] SRC_PATH|- SERVICE:DEST_PATH` + var composeCpCommand = &cobra.Command{ + Use: usage, + Short: "Copy files/folders between a service container and the local filesystem", + Args: cobra.ExactArgs(2), + RunE: composeCopyAction, + SilenceUsage: true, + SilenceErrors: true, + } + composeCpCommand.Flags().Bool("dry-run", false, "Execute command in dry run mode") + composeCpCommand.Flags().BoolP("follow-link", "L", false, "Always follow symbol link in SRC_PATH") + composeCpCommand.Flags().Int("index", 0, "index of the container if service has multiple replicas") + return composeCpCommand +} + +func composeCopyAction(cmd *cobra.Command, args []string) error { + globalOptions, err := processRootCmdFlags(cmd) + if err != nil { + return err + } + // TODO: unimplemented rootless mode + source := args[0] + if source == "" { + return errors.New("source can not be empty") + } + destination := args[1] + if destination == "" { + return errors.New("destination can not be empty") + } + + dryRun, err := cmd.Flags().GetBool("dry-run") + if err != nil { + return err + } + followLink, err := cmd.Flags().GetBool("follow-link") + if err != nil { + return err + } + index, err := cmd.Flags().GetInt("index") + if err != nil { + return err + } + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) + if err != nil { + return err + } + defer cancel() + options, err := getComposeOptions(cmd, globalOptions.DebugFull, globalOptions.Experimental) + if err != nil { + return err + } + c, err := compose.New(client, globalOptions, options, cmd.OutOrStdout(), cmd.ErrOrStderr()) + if err != nil { + return err + } + + co := composer.CopyOptions{ + Source: source, + Destination: destination, + Index: index, + FollowLink: followLink, + DryRun: dryRun, + } + return c.Copy(ctx, co) + +} diff --git a/cmd/nerdctl/compose_cp_linux_test.go b/cmd/nerdctl/compose_cp_linux_test.go new file mode 100644 index 00000000000..15a55018769 --- /dev/null +++ b/cmd/nerdctl/compose_cp_linux_test.go @@ -0,0 +1,72 @@ +/* + 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" + "os" + "path/filepath" + "testing" + + "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/pkg/testutil" + "gotest.tools/v3/assert" +) + +func TestComposeCopy(t *testing.T) { + if rootlessutil.IsRootless() { + t.Skip("Test skipped in rootless mode for compose copy") + } + base := testutil.NewBase(t) + + var dockerComposeYAML = fmt.Sprintf(` +version: '3.1' + +services: + svc0: + image: %s + command: "sleep infinity" +`, testutil.CommonImage) + + comp := testutil.NewComposeDir(t, dockerComposeYAML) + defer comp.CleanUp() + projectName := comp.ProjectName() + t.Logf("projectName=%q", projectName) + + base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "-d").AssertOK() + defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").AssertOK() + + // gernetate test file + srcDir := t.TempDir() + srcFile := filepath.Join(srcDir, "test-file") + srcFileContent := []byte("test-file-content") + err := os.WriteFile(srcFile, srcFileContent, 0o644) + assert.NilError(t, err) + + // test copy to service + destPath := "/dest-no-exist-no-slash" + base.ComposeCmd("-f", comp.YAMLFullPath(), "cp", srcFile, "svc0:"+destPath).AssertOK() + + // test copy from service + destFile := filepath.Join(srcDir, "test-file2") + base.ComposeCmd("-f", comp.YAMLFullPath(), "cp", "svc0:"+destPath, destFile).AssertOK() + + destFileContent, err := os.ReadFile(destFile) + assert.NilError(t, err) + assert.DeepEqual(t, srcFileContent, destFileContent) + +} diff --git a/docs/command-reference.md b/docs/command-reference.md index f12c81b3ef1..7334c6f0a7a 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -110,6 +110,7 @@ It does not necessarily mean that the corresponding features are missing in cont - [:whale: nerdctl compose pause](#whale-nerdctl-compose-pause) - [:whale: nerdctl compose unpause](#whale-nerdctl-compose-unpause) - [:whale: nerdctl compose config](#whale-nerdctl-compose-config) + - [:whale: nerdctl compose cp](#whale-nerdctl-compose-cp) - [:whale: nerdctl compose kill](#whale-nerdctl-compose-kill) - [:whale: nerdctl compose restart](#whale-nerdctl-compose-restart) - [:whale: nerdctl compose rm](#whale-nerdctl-compose-rm) @@ -1540,6 +1541,25 @@ Unimplemented `docker-compose config` (V1) flags: `--resolve-image-digests`, `-- Unimplemented `docker compose config` (V2) flags: `--resolve-image-digests`, `--no-interpolate`, `--format`, `--output`, `--profiles` +### :whale: nerdctl compose cp + +Copy files/folders between a service container and the local filesystem + +Usage: +``` +nerdctl compose cp [OPTIONS] SERVICE:SRC_PATH DEST_PATH|- +nerdctl compose cp [OPTIONS] SRC_PATH|- SERVICE:DEST_PATH [flags] +``` + +Flags: +- :whale: `--dry-run`: Execute command in dry run mode +- :whale: `-L, --follow-link`: Always follow symbol link in SRC_PATH +- :whale: `--index int`: index of the container if service has multiple replicas + +Unimplemented `docker compose cp` flags: `--archive` + +Unimplemented rootless mode + ### :whale: nerdctl compose kill Force stop service containers diff --git a/pkg/composer/copy.go b/pkg/composer/copy.go new file mode 100644 index 00000000000..837427f523c --- /dev/null +++ b/pkg/composer/copy.go @@ -0,0 +1,161 @@ +/* + 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 composer + +import ( + "context" + "errors" + "fmt" + "strings" + + "github.com/containerd/containerd" + "github.com/containerd/nerdctl/pkg/labels" + "github.com/docker/docker/pkg/system" + "github.com/sirupsen/logrus" +) + +type CopyOptions struct { + Source string + Destination string + Index int + FollowLink bool + DryRun bool +} + +type copyDirection int + +const ( + fromService copyDirection = 0 + toService copyDirection = 1 +) + +func (c *Composer) Copy(ctx context.Context, co CopyOptions) error { + srcService, srcPath := splitCpArg(co.Source) + destService, dstPath := splitCpArg(co.Destination) + var serviceName string + var direction copyDirection + + if srcService != "" && destService != "" { + return errors.New("copying between services is not supported") + } + if srcService == "" && destService == "" { + return errors.New("unknown copy direction") + } + + if srcService != "" { + direction = fromService + serviceName = srcService + } + if destService != "" { + direction = toService + serviceName = destService + } + + containers, err := c.listContainersTargetedForCopy(ctx, co.Index, direction, serviceName) + if err != nil { + return err + } + + for _, container := range containers { + args := []string{"cp"} + if co.FollowLink { + args = append(args, "--follow-link") + } + if direction == fromService { + args = append(args, fmt.Sprintf("%s:%s", container.ID(), srcPath), dstPath) + } + if direction == toService { + args = append(args, srcPath, fmt.Sprintf("%s:%s", container.ID(), dstPath)) + } + err := c.logCopyMsg(ctx, container, direction, srcService, srcPath, destService, dstPath, co.DryRun) + if err != nil { + return err + } + if !co.DryRun { + if err := c.runNerdctlCmd(ctx, args...); err != nil { + return err + } + } + } + return nil +} + +func (c *Composer) logCopyMsg(ctx context.Context, container containerd.Container, direction copyDirection, srcService string, srcPath string, destService string, dstPath string, dryRun bool) error { + containerLabels, err := container.Labels(ctx) + if err != nil { + return err + } + containerName := containerLabels[labels.Name] + msg := "" + if dryRun { + msg = "DRY-RUN MODE - " + } + if direction == fromService { + msg = msg + fmt.Sprintf("copy %s:%s to %s", containerName, srcPath, dstPath) + } + if direction == toService { + msg = msg + fmt.Sprintf("copy %s to %s:%s", srcPath, containerName, dstPath) + } + logrus.Info(msg) + return nil +} + +func (c *Composer) listContainersTargetedForCopy(ctx context.Context, index int, direction copyDirection, serviceName string) ([]containerd.Container, error) { + var containers []containerd.Container + var err error + + containers, err = c.Containers(ctx, serviceName) + if err != nil { + return nil, err + } + + if index > 0 { + if index > len(containers) { + return nil, fmt.Errorf("index (%d) out of range: only %d running instances from service %s", + index, len(containers), serviceName) + } + container := containers[index-1] + return []containerd.Container{container}, nil + } + + if len(containers) < 1 { + return nil, fmt.Errorf("no container found for service %q", serviceName) + } + if direction == fromService { + return containers[:1], err + + } + return containers, err +} + +// https://github.com/docker/compose/blob/v2.21.0/pkg/compose/cp.go#L307 +func splitCpArg(arg string) (container, path string) { + if system.IsAbs(arg) { + // Explicit local absolute path, e.g., `C:\foo` or `/foo`. + return "", arg + } + + parts := strings.SplitN(arg, ":", 2) + + if len(parts) == 1 || strings.HasPrefix(parts[0], ".") { + // Either there's no `:` in the arg + // OR it's an explicit local relative path like `./file:name.txt`. + return "", arg + } + + return parts[0], parts[1] +} From 76dd7065c0908b3f9862363c67252349b3d009ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 22:36:28 +0000 Subject: [PATCH 0130/1066] build(deps): bump github.com/opencontainers/image-spec Bumps [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec) from 1.1.0-rc4 to 1.1.0-rc5. - [Release notes](https://github.com/opencontainers/image-spec/releases) - [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md) - [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0-rc4...v1.1.0-rc5) --- updated-dependencies: - dependency-name: github.com/opencontainers/image-spec dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2d0437b8a97..3b0dac53af7 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/moby/sys/signal v0.7.0 github.com/moby/term v0.5.0 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.1.0-rc4 + github.com/opencontainers/image-spec v1.1.0-rc5 github.com/opencontainers/runtime-spec v1.1.0 github.com/pelletier/go-toml v1.9.5 github.com/rootless-containers/bypass4netns v0.3.0 diff --git a/go.sum b/go.sum index 5a79cf439bb..a73eb0c54b6 100644 --- a/go.sum +++ b/go.sum @@ -233,8 +233,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= 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-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +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/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk= github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= From a08e668f2cf778397f4a907a52c9bc73fcd41b43 Mon Sep 17 00:00:00 2001 From: Ziwen Ning Date: Thu, 14 Sep 2023 22:04:11 -0700 Subject: [PATCH 0131/1066] docs: fix docs for supported quiet flag of push command Signed-off-by: Ziwen Ning --- docs/command-reference.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/command-reference.md b/docs/command-reference.md index f12c81b3ef1..84ce8483bea 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -768,8 +768,9 @@ Flags: - :nerd_face: `--notation-key-name`: Signing key name for a key previously added to notation's key list for `--sign=notation` - :nerd_face: `--allow-nondistributable-artifacts`: Allow pushing images with non-distributable blobs - :nerd_face: `--ipfs-address`: Multiaddr of IPFS API (default uses `$IPFS_PATH` env variable if defined or local directory `~/.ipfs`) +- :whale: `-q, --quiet`: Suppress verbose output -Unimplemented `docker push` flags: `--all-tags`, `--disable-content-trust` (default true), `--quiet` +Unimplemented `docker push` flags: `--all-tags`, `--disable-content-trust` (default true) ### :whale: nerdctl load From 1605587bd9c4c8580d1edbdc51b6d2f32393cb96 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sat, 16 Sep 2023 01:54:21 +0900 Subject: [PATCH 0132/1066] Implement `nerdctl compose exec -T` Signed-off-by: Akihiro Suda --- cmd/nerdctl/compose_exec.go | 14 ++++++++++++-- docs/command-reference.md | 3 +-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/compose_exec.go b/cmd/nerdctl/compose_exec.go index 06919b6309e..f4bebfc9b92 100644 --- a/cmd/nerdctl/compose_exec.go +++ b/cmd/nerdctl/compose_exec.go @@ -36,17 +36,27 @@ func newComposeExecCommand() *cobra.Command { } composeExecCommand.Flags().SetInterspersed(false) - composeExecCommand.Flags().BoolP("tty", "t", true, "Allocate a pseudo-TTY") + composeExecCommand.Flags().BoolP("tty", "t", true, "Allocate a pseudo-TTY") // missing in Docker Compose v2? + composeExecCommand.Flags().BoolP("no-TTY", "T", false, "Disable pseudo-TTY allocation. By default nerdctl compose exec allocates a TTY.") composeExecCommand.Flags().BoolP("interactive", "i", true, "Keep STDIN open even if not attached") composeExecCommand.Flags().BoolP("detach", "d", false, "Detached mode: Run containers in the background") composeExecCommand.Flags().StringP("workdir", "w", "", "Working directory inside the container") // env needs to be StringArray, not StringSlice, to prevent "FOO=foo1,foo2" from being split to {"FOO=foo1", "foo2"} composeExecCommand.Flags().StringArrayP("env", "e", nil, "Set environment variables") - // TODO: no-TTY flag composeExecCommand.Flags().Bool("privileged", false, "Give extended privileges to the command") composeExecCommand.Flags().StringP("user", "u", "", "Username or UID (format: [:])") composeExecCommand.Flags().Int("index", 1, "index of the container if the service has multiple instances.") + composeExecCommand.PreRunE = func(cmd *cobra.Command, args []string) error { + flags := cmd.Flags() + if noTTY, _ := flags.GetBool("no-TTY"); noTTY { + if err := flags.Set("tty", "false"); err != nil { + return err + } + } + return nil + } + return composeExecCommand } diff --git a/docs/command-reference.md b/docs/command-reference.md index 84ce8483bea..3143bc4a084 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1427,11 +1427,10 @@ Flags: - :whale: `-i, --interactive`: Keep STDIN open even if not attached (default true) - :whale: `--privileged`: Give extended privileges to the command - :whale: `-t, --tty`: Allocate a pseudo-TTY +- :whale: `-T, --no-TTY`: Disable pseudo-TTY allocation. By default nerdctl compose exec allocates a TTY. - :whale: `-u, --user`: Username or UID (format: `[:]`) - :whale: `-w, --workdir`: Working directory inside the container -Unimplemented `docker-compose exec` (V2) flags: `-T, --no-TTY` - ### :whale: nerdctl compose down Remove containers and associated resources From 69a1833efb58cb954b7caabc70bfd1e8543f24c2 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 17 Sep 2023 03:58:23 +0900 Subject: [PATCH 0133/1066] compose: silence "build.config should be relative path" warning This warning was always printed with a compose yaml that contains a build, as `compose-go/loader.ResolveServiceRelativePaths` automatically expands a relative context path to an abstract path: https://github.com/compose-spec/compose-go/blob/v1.18.4/loader/paths.go#L91-L93 ("build.config" was a typo of "build.context") Fix issue 2508 Signed-off-by: Akihiro Suda --- pkg/composer/serviceparser/build.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/composer/serviceparser/build.go b/pkg/composer/serviceparser/build.go index a61e7975af8..e191163ddd9 100644 --- a/pkg/composer/serviceparser/build.go +++ b/pkg/composer/serviceparser/build.go @@ -44,9 +44,6 @@ func parseBuildConfig(c *types.BuildConfig, project *types.Project, imageName st if strings.Contains(c.Context, "://") { return nil, fmt.Errorf("build: URL-style context (%q) is not supported yet: %w", c.Context, errdefs.ErrNotImplemented) } - if filepath.IsAbs(c.Context) { - logrus.Warnf("build.config should be relative path, got %q", c.Context) - } ctxDir := project.RelativePath(c.Context) var b Build From dd03ebeaa7ae83db2d202cbcd4a4ea6e20aba674 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 18 Sep 2023 19:34:30 +0900 Subject: [PATCH 0134/1066] nerdctl compose cp: support rootless rootless cp runs in the host namespace (for inspecting file owners) Fix issue 2512 Signed-off-by: Akihiro Suda --- cmd/nerdctl/compose_cp.go | 12 ++++++++++-- cmd/nerdctl/compose_cp_linux_test.go | 4 ---- cmd/nerdctl/main_linux.go | 10 +++++++++- docs/command-reference.md | 2 -- pkg/rootlessutil/rootlessutil_other.go | 4 ++++ 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/cmd/nerdctl/compose_cp.go b/cmd/nerdctl/compose_cp.go index 7d591cfaef1..252b9e1c261 100644 --- a/cmd/nerdctl/compose_cp.go +++ b/cmd/nerdctl/compose_cp.go @@ -22,6 +22,7 @@ import ( "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/compose" "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/spf13/cobra" ) @@ -47,7 +48,6 @@ func composeCopyAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - // TODO: unimplemented rootless mode source := args[0] if source == "" { return errors.New("source can not be empty") @@ -69,7 +69,15 @@ func composeCopyAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) + address := globalOptions.Address + // rootless cp runs in the host namespaces, so the address is different + if rootlessutil.IsRootless() { + address, err = rootlessutil.RootlessContainredSockAddress() + if err != nil { + return err + } + } + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, address) if err != nil { return err } diff --git a/cmd/nerdctl/compose_cp_linux_test.go b/cmd/nerdctl/compose_cp_linux_test.go index 15a55018769..8c65752db2c 100644 --- a/cmd/nerdctl/compose_cp_linux_test.go +++ b/cmd/nerdctl/compose_cp_linux_test.go @@ -22,15 +22,11 @@ import ( "path/filepath" "testing" - "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/testutil" "gotest.tools/v3/assert" ) func TestComposeCopy(t *testing.T) { - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for compose copy") - } base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` diff --git a/cmd/nerdctl/main_linux.go b/cmd/nerdctl/main_linux.go index a20cb00dbb6..1fa33e6ca73 100644 --- a/cmd/nerdctl/main_linux.go +++ b/cmd/nerdctl/main_linux.go @@ -39,7 +39,7 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { switch commands[1] { // completion, login, logout: false, because it shouldn't require the daemon to be running // apparmor: false, because it requires the initial mount namespace to access /sys/kernel/security - // cp: false, because it requires the initial mount namespace to inspect file owners + // cp, compose cp: false, because it requires the initial mount namespace to inspect file owners case "", "completion", "login", "logout", "apparmor", "cp": return false case "container": @@ -50,6 +50,14 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { case "cp": return false } + case "compose": + if len(commands) < 3 { + return true + } + switch commands[2] { + case "cp": + return false + } } return true } diff --git a/docs/command-reference.md b/docs/command-reference.md index ab1e8bba2ac..4d8ac6c1648 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1558,8 +1558,6 @@ Flags: Unimplemented `docker compose cp` flags: `--archive` -Unimplemented rootless mode - ### :whale: nerdctl compose kill Force stop service containers diff --git a/pkg/rootlessutil/rootlessutil_other.go b/pkg/rootlessutil/rootlessutil_other.go index 7f9abe2a1cc..9fa5d12f737 100644 --- a/pkg/rootlessutil/rootlessutil_other.go +++ b/pkg/rootlessutil/rootlessutil_other.go @@ -62,3 +62,7 @@ func NewRootlessKitClient() (client.Client, error) { func ParentMain(hostGatewayIP string) error { return fmt.Errorf("cannot use RootlessKit on main entry point on non-Linux hosts") } + +func RootlessContainredSockAddress() (string, error) { + return "", fmt.Errorf("cannot inspect RootlessKit state on non-Linux hosts") +} From 4c82cde7d594d3952344d815c0645205215cfec7 Mon Sep 17 00:00:00 2001 From: Ziwen Ning Date: Sat, 2 Sep 2023 03:39:54 -0700 Subject: [PATCH 0135/1066] feat: support push with soci Signed-off-by: Ziwen Ning --- cmd/nerdctl/flagutil.go | 10 ++ cmd/nerdctl/image_push.go | 10 ++ cmd/nerdctl/image_push_linux_test.go | 16 +++ docs/command-reference.md | 2 + pkg/api/types/image_types.go | 9 ++ pkg/cmd/image/push.go | 9 ++ pkg/snapshotterutil/sociutil.go | 166 +++++++++++++++++++++++++++ pkg/testutil/testutil_linux.go | 1 + 8 files changed, 223 insertions(+) create mode 100644 pkg/snapshotterutil/sociutil.go diff --git a/cmd/nerdctl/flagutil.go b/cmd/nerdctl/flagutil.go index 2c6102a5401..cf50b59a30e 100644 --- a/cmd/nerdctl/flagutil.go +++ b/cmd/nerdctl/flagutil.go @@ -56,6 +56,16 @@ func processImageVerifyOptions(cmd *cobra.Command) (opt types.ImageVerifyOptions return } +func processSociOptions(cmd *cobra.Command) (opt types.SociOptions, err error) { + if opt.SpanSize, err = cmd.Flags().GetInt64("soci-span-size"); err != nil { + return + } + if opt.MinLayerSize, err = cmd.Flags().GetInt64("soci-min-layer-size"); err != nil { + return + } + return +} + func processRootCmdFlags(cmd *cobra.Command) (types.GlobalCommandOptions, error) { debug, err := cmd.Flags().GetBool("debug") if err != nil { diff --git a/cmd/nerdctl/image_push.go b/cmd/nerdctl/image_push.go index b217d281a97..3dac0d986c1 100644 --- a/cmd/nerdctl/image_push.go +++ b/cmd/nerdctl/image_push.go @@ -57,6 +57,11 @@ func newPushCommand() *cobra.Command { pushCommand.Flags().String("notation-key-name", "", "Signing key name for a key previously added to notation's key list for --sign=notation") // #endregion + // #region soci flags + pushCommand.Flags().Int64("soci-span-size", -1, "Span size that soci index uses to segment layer data. Default is 4 MiB.") + pushCommand.Flags().Int64("soci-min-layer-size", -1, "Minimum layer size to build zTOC for. Smaller layers won't have zTOC and not lazy pulled. Default is 10 MiB.") + // #endregion + pushCommand.Flags().BoolP("quiet", "q", false, "Suppress verbose output") pushCommand.Flags().Bool(allowNonDistFlag, false, "Allow pushing images with non-distributable blobs") @@ -101,9 +106,14 @@ func processImagePushOptions(cmd *cobra.Command) (types.ImagePushOptions, error) if err != nil { return types.ImagePushOptions{}, err } + sociOptions, err := processSociOptions(cmd) + if err != nil { + return types.ImagePushOptions{}, err + } return types.ImagePushOptions{ GOptions: globalOptions, SignOptions: signOptions, + SociOptions: sociOptions, Platforms: platform, AllPlatforms: allPlatforms, Estargz: estargz, diff --git a/cmd/nerdctl/image_push_linux_test.go b/cmd/nerdctl/image_push_linux_test.go index ccf5673fed6..9a6bdbd5622 100644 --- a/cmd/nerdctl/image_push_linux_test.go +++ b/cmd/nerdctl/image_push_linux_test.go @@ -174,3 +174,19 @@ func TestPushNonDistributableArtifacts(t *testing.T) { } assert.Equal(t, resp.StatusCode, http.StatusOK, "non-distributable blob should be available") } + +func TestPushSoci(t *testing.T) { + testutil.DockerIncompatible(t) + base := testutil.NewBase(t) + requiresSoci(base) + reg := testregistry.NewPlainHTTP(base, 5000) + defer reg.Cleanup() + + base.Cmd("pull", testutil.UbuntuImage).AssertOK() + testImageRef := fmt.Sprintf("%s:%d/%s:%s", + reg.IP.String(), reg.ListenPort, testutil.Identifier(t), strings.Split(testutil.UbuntuImage, ":")[1]) + t.Logf("testImageRef=%q", testImageRef) + base.Cmd("tag", testutil.UbuntuImage, testImageRef).AssertOK() + + base.Cmd("--snapshotter=soci", "--insecure-registry", "push", "--soci-span-size=2097152", "--soci-min-layer-size=20971520", testImageRef).AssertOK() +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 84ce8483bea..c1010315194 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -769,6 +769,8 @@ Flags: - :nerd_face: `--allow-nondistributable-artifacts`: Allow pushing images with non-distributable blobs - :nerd_face: `--ipfs-address`: Multiaddr of IPFS API (default uses `$IPFS_PATH` env variable if defined or local directory `~/.ipfs`) - :whale: `-q, --quiet`: Suppress verbose output +- :nerd_face: `--soci-span-size`: Span size in bytes that soci index uses to segment layer data. Default is 4 MiB. +- :nerd_face: `--soci-min-layer-size`: Minimum layer size in bytes to build zTOC for. Smaller layers won't have zTOC and not lazy pulled. Default is 10 MiB. Unimplemented `docker push` flags: `--all-tags`, `--disable-content-trust` (default true) diff --git a/pkg/api/types/image_types.go b/pkg/api/types/image_types.go index 51fd3bc4bff..d18a3c6692e 100644 --- a/pkg/api/types/image_types.go +++ b/pkg/api/types/image_types.go @@ -152,6 +152,7 @@ type ImagePushOptions struct { Stdout io.Writer GOptions GlobalCommandOptions SignOptions ImageSignOptions + SociOptions SociOptions // Platforms convert content for a specific platform Platforms []string // AllPlatforms convert content for all platforms @@ -256,3 +257,11 @@ type ImageVerifyOptions struct { // CosignCertificateOidcIssuerRegexp A regular expression alternative to --certificate-oidc-issuer for --verify=cosign. Accepts the Go regular expression syntax described at https://golang.org/s/re2syntax. Either --cosign-certificate-oidc-issuer or --cosign-certificate-oidc-issuer-regexp must be set for keyless flows CosignCertificateOidcIssuerRegexp string } + +// SociOptions contains options for SOCI. +type SociOptions struct { + // Span size that soci index uses to segment layer data. Default is 4 MiB. + SpanSize int64 + // Minimum layer size to build zTOC for. Smaller layers won't have zTOC and not lazy pulled. Default is 10 MiB. + MinLayerSize int64 +} diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index 2290619bb41..0f49b2ad229 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -40,6 +40,7 @@ import ( "github.com/containerd/nerdctl/pkg/platformutil" "github.com/containerd/nerdctl/pkg/referenceutil" "github.com/containerd/nerdctl/pkg/signutil" + "github.com/containerd/nerdctl/pkg/snapshotterutil" "github.com/containerd/stargz-snapshotter/estargz" "github.com/containerd/stargz-snapshotter/estargz/zstdchunked" estargzconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz" @@ -181,6 +182,14 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options options.SignOptions); err != nil { return err } + if options.GOptions.Snapshotter == "soci" { + if err = snapshotterutil.CreateSoci(ref, options.GOptions, options.AllPlatforms, options.Platforms, options.SociOptions); err != nil { + return err + } + if err = snapshotterutil.PushSoci(ref, options.GOptions, options.AllPlatforms, options.Platforms); err != nil { + return err + } + } if options.Quiet { fmt.Fprintln(options.Stdout, ref) } diff --git a/pkg/snapshotterutil/sociutil.go b/pkg/snapshotterutil/sociutil.go new file mode 100644 index 00000000000..7c01ed3d666 --- /dev/null +++ b/pkg/snapshotterutil/sociutil.go @@ -0,0 +1,166 @@ +/* + 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 snapshotterutil + +import ( + "bufio" + "os" + "os/exec" + "strconv" + "strings" + + "github.com/containerd/nerdctl/pkg/api/types" + "github.com/sirupsen/logrus" +) + +// CreateSoci creates a SOCI index(`rawRef`) +func CreateSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, platforms []string, sOpts types.SociOptions) error { + sociExecutable, err := exec.LookPath("soci") + if err != nil { + logrus.WithError(err).Error("soci executable not found in path $PATH") + logrus.Info("you might consider installing soci from: https://github.com/awslabs/soci-snapshotter/blob/main/docs/install.md") + return err + } + + sociCmd := exec.Command(sociExecutable) + sociCmd.Env = os.Environ() + + // #region for global flags. + if gOpts.Address != "" { + sociCmd.Args = append(sociCmd.Args, "--address", gOpts.Address) + } + if gOpts.Namespace != "" { + sociCmd.Args = append(sociCmd.Args, "--namespace", gOpts.Namespace) + } + // #endregion + + // Global flags have to be put before subcommand before soci upgrades to urfave v3. + // https://github.com/urfave/cli/issues/1113 + sociCmd.Args = append(sociCmd.Args, "create") + + if allPlatform { + sociCmd.Args = append(sociCmd.Args, "--all-platforms", strconv.FormatBool(allPlatform)) + } + if len(platforms) > 0 { + sociCmd.Args = append(sociCmd.Args, "--platform") + sociCmd.Args = append(sociCmd.Args, strings.Join(platforms, ",")) + } + if sOpts.SpanSize != -1 { + sociCmd.Args = append(sociCmd.Args, "--span-size", strconv.FormatInt(sOpts.SpanSize, 10)) + } + if sOpts.MinLayerSize != -1 { + sociCmd.Args = append(sociCmd.Args, "--min-layer-size", strconv.FormatInt(sOpts.MinLayerSize, 10)) + } + // --timeout, --debug, --content-store + sociCmd.Args = append(sociCmd.Args, rawRef) + + logrus.Debugf("running %s %v", sociExecutable, sociCmd.Args) + + err = processSociIO(sociCmd) + if err != nil { + return err + } + + return sociCmd.Wait() +} + +// PushSoci pushes a SOCI index(`rawRef`) +// `hostsDirs` are used to resolve image `rawRef` +func PushSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, platforms []string) error { + logrus.Debugf("pushing SOCI index: %s", rawRef) + + sociExecutable, err := exec.LookPath("soci") + if err != nil { + logrus.WithError(err).Error("soci executable not found in path $PATH") + logrus.Info("you might consider installing soci from: https://github.com/awslabs/soci-snapshotter/blob/main/docs/install.md") + return err + } + + sociCmd := exec.Command(sociExecutable) + sociCmd.Env = os.Environ() + + // #region for global flags. + if gOpts.Address != "" { + sociCmd.Args = append(sociCmd.Args, "--address", gOpts.Address) + } + if gOpts.Namespace != "" { + sociCmd.Args = append(sociCmd.Args, "--namespace", gOpts.Namespace) + } + // #endregion + + // Global flags have to be put before subcommand before soci upgrades to urfave v3. + // https://github.com/urfave/cli/issues/1113 + sociCmd.Args = append(sociCmd.Args, "push") + + if allPlatform { + sociCmd.Args = append(sociCmd.Args, "--all-platforms", strconv.FormatBool(allPlatform)) + } + if len(platforms) > 0 { + sociCmd.Args = append(sociCmd.Args, "--platform") + sociCmd.Args = append(sociCmd.Args, strings.Join(platforms, ",")) + } + if gOpts.InsecureRegistry { + sociCmd.Args = append(sociCmd.Args, "--skip-verify") + sociCmd.Args = append(sociCmd.Args, "--plain-http") + } + if len(gOpts.HostsDir) > 0 { + sociCmd.Args = append(sociCmd.Args, "--hosts-dir") + sociCmd.Args = append(sociCmd.Args, strings.Join(gOpts.HostsDir, ",")) + } + sociCmd.Args = append(sociCmd.Args, rawRef) + + logrus.Debugf("running %s %v", sociExecutable, sociCmd.Args) + + err = processSociIO(sociCmd) + if err != nil { + return err + } + return sociCmd.Wait() +} + +func processSociIO(sociCmd *exec.Cmd) error { + stdout, err := sociCmd.StdoutPipe() + if err != nil { + logrus.Warn("soci: " + err.Error()) + } + stderr, err := sociCmd.StderrPipe() + if err != nil { + logrus.Warn("soci: " + err.Error()) + } + if err := sociCmd.Start(); err != nil { + // only return err if it's critical (soci command failed to start.) + return err + } + + scanner := bufio.NewScanner(stdout) + for scanner.Scan() { + logrus.Info("soci: " + scanner.Text()) + } + if err := scanner.Err(); err != nil { + logrus.Warn("soci: " + err.Error()) + } + + errScanner := bufio.NewScanner(stderr) + for errScanner.Scan() { + logrus.Info("soci: " + errScanner.Text()) + } + if err := errScanner.Err(); err != nil { + logrus.Warn("soci: " + err.Error()) + } + + return nil +} diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index f74785eb74e..adbc5fbc775 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -60,6 +60,7 @@ var ( const ( FedoraESGZImage = "ghcr.io/stargz-containers/fedora:30-esgz" // eStargz FfmpegSociImage = "public.ecr.aws/soci-workshop-examples/ffmpeg:latest" // SOCI + UbuntuImage = "public.ecr.aws/docker/library/ubuntu:23.10" // Large enough for testing soci index creation ) type delayOnceReader struct { From 6db2c459a2807746edfa81ff7ebe3680fec31d03 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 18 Sep 2023 20:42:14 +0900 Subject: [PATCH 0136/1066] update containerd (1.7.6) Fix e4a2ceb72895345b2a1b1e9ab8d8dad54fbd385e Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cc480741ca2..3c3ef5095b5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.3 +ARG CONTAINERD_VERSION=v1.7.6 ARG RUNC_VERSION=v1.1.9 ARG CNI_PLUGINS_VERSION=v1.3.0 From 98e87997f5a37f3e50da66188f14dac363b9909a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 23:01:03 +0000 Subject: [PATCH 0137/1066] build(deps): bump gotest.tools/v3 from 3.5.0 to 3.5.1 Bumps [gotest.tools/v3](https://github.com/gotestyourself/gotest.tools) from 3.5.0 to 3.5.1. - [Release notes](https://github.com/gotestyourself/gotest.tools/releases) - [Commits](https://github.com/gotestyourself/gotest.tools/compare/v3.5.0...v3.5.1) --- updated-dependencies: - dependency-name: gotest.tools/v3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3b0dac53af7..97a03cdd02e 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,7 @@ require ( golang.org/x/term v0.12.0 golang.org/x/text v0.13.0 gopkg.in/yaml.v3 v3.0.1 - gotest.tools/v3 v3.5.0 + gotest.tools/v3 v3.5.1 ) require ( diff --git a/go.sum b/go.sum index a73eb0c54b6..6fbf9c50d44 100644 --- a/go.sum +++ b/go.sum @@ -458,8 +458,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= -gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= From 65334cc7e10dc4be6eefccfe7374edc162651dfe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 23:01:18 +0000 Subject: [PATCH 0138/1066] build(deps): bump github.com/klauspost/compress from 1.16.7 to 1.17.0 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.16.7 to 1.17.0. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.16.7...v1.17.0) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3b0dac53af7..8be675d9b5b 100644 --- a/go.mod +++ b/go.mod @@ -87,7 +87,7 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.16.7 + github.com/klauspost/compress v1.17.0 github.com/klauspost/cpuid/v2 v2.1.1 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/go.sum b/go.sum index a73eb0c54b6..05ab592a6f1 100644 --- a/go.sum +++ b/go.sum @@ -166,8 +166,8 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0= From 42cfd14468c1aa5f7c4f16c9a2cbe009fa92152c Mon Sep 17 00:00:00 2001 From: Ziwen Ning Date: Mon, 18 Sep 2023 18:33:58 -0700 Subject: [PATCH 0139/1066] docs: add SOCI snapshotter guideline in README.md Co-Authored-By: Zheao Li Signed-off-by: Ziwen Ning --- README.md | 2 +- docs/soci.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 docs/soci.md diff --git a/README.md b/README.md index 70377760f80..81c9d8cefb7 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,7 @@ Also, `nerdctl` might be potentially useful for debugging Kubernetes clusters, b Major: -- On-demand image pulling (lazy-pulling) using [Stargz](./docs/stargz.md)/[Nydus](./docs/nydus.md)/[OverlayBD](./docs/overlaybd.md) Snapshotter: `nerdctl --snapshotter=stargz|nydus|overlaybd run IMAGE` . +- On-demand image pulling (lazy-pulling) using [Stargz](./docs/stargz.md)/[Nydus](./docs/nydus.md)/[OverlayBD](./docs/overlaybd.md)/[SOCI](./docs/soci.md) Snapshotter: `nerdctl --snapshotter=stargz|nydus|overlaybd|soci run IMAGE` . - [Image encryption and decryption using ocicrypt (imgcrypt)](./docs/ocicrypt.md): `nerdctl image (encrypt|decrypt) SRC DST` - [P2P image distribution using IPFS](./docs/ipfs.md): `nerdctl run ipfs://CID` . P2P image distribution (IPFS) is completely optional. Your host is NOT connected to any P2P network, unless you opt in to [install and run IPFS daemon](https://docs.ipfs.io/install/). diff --git a/docs/soci.md b/docs/soci.md new file mode 100644 index 00000000000..b6c70a86d11 --- /dev/null +++ b/docs/soci.md @@ -0,0 +1,47 @@ +# Lazy-pulling using SOCI Snapshotter + +SOCI Snapshotter is a containerd snapshotter plugin. It enables standard OCI images to be lazily loaded without requiring a build-time conversion step. "SOCI" is short for "Seekable OCI", and is pronounced "so-CHEE". + +See https://github.com/awslabs/soci-snapshotter to learn further information. + +## Prerequisites + +- Install containerd remote snapshotter plugin (`soci`) from https://github.com/awslabs/soci-snapshotter/blob/main/docs/getting-started.md + +- Add the following to `/etc/containerd/config.toml`: +```toml +[proxy_plugins] + [proxy_plugins.soci] + type = "snapshot" + address = "/run/soci-snapshotter-grpc/soci-snapshotter-grpc.sock" +``` + +- Launch `containerd` and `soci-snapshotter` + +## Enable SOCI for `nerdctl run` and `nerdctl pull` + +| :zap: Requirement | nerdctl >= 1.5.0 | +| ----------------- |------------------| + +- Run `nerdctl` with `--snapshotter=soci` +```console +nerdctl run --it --rm --snapshotter=soci public.ecr.aws/soci-workshop-examples/ffmpeg:latest +``` + +- You can also only pull the image with SOCI without running the container. +```console +nerdctl pull --snapshotter=soci public.ecr.aws/soci-workshop-examples/ffmpeg:latest +``` + +For images that already have SOCI indices, see https://gallery.ecr.aws/soci-workshop-examples + +## Enable SOCI for `nerdctl push` + +| :zap: Requirement | nerdctl >= 1.6.0 | +| ----------------- |------------------| + +- Push the image with SOCI index. Adding `--snapshotter=soci` command to `nerdctl pull`, `nerdctl` will create the SOCI index and push the index to same destination as the image. +```console +nerdctl push --snapshotter=soci push --soci-span-size=2097152 --soci-min-layer-size=20971520 public.ecr.aws/my-registry/my-repo:latest +``` +--soci-span-size and --soci-min-layer-size are two properties to customize the SOCI index. See [Command Reference](https://github.com/containerd/nerdctl/blob/377b2077bb616194a8ef1e19ccde32aa1ffd6c84/docs/command-reference.md?plain=1#L773) for further details. From 357113b4dea385befe7be40d0336a8375bc6ae91 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 18 Sep 2023 19:53:45 +0900 Subject: [PATCH 0140/1066] nerdctl version: skip inspecting rootless daemon if the daemon is not running Fix issue 2455 Signed-off-by: Akihiro Suda --- cmd/nerdctl/main_linux.go | 4 ++-- cmd/nerdctl/version.go | 26 ++++++++++++++++++++------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/cmd/nerdctl/main_linux.go b/cmd/nerdctl/main_linux.go index 1fa33e6ca73..d4c81209421 100644 --- a/cmd/nerdctl/main_linux.go +++ b/cmd/nerdctl/main_linux.go @@ -37,10 +37,10 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { return true } switch commands[1] { - // completion, login, logout: false, because it shouldn't require the daemon to be running + // completion, login, logout, version: false, because it shouldn't require the daemon to be running // apparmor: false, because it requires the initial mount namespace to access /sys/kernel/security // cp, compose cp: false, because it requires the initial mount namespace to inspect file owners - case "", "completion", "login", "logout", "apparmor", "cp": + case "", "completion", "login", "logout", "apparmor", "cp", "version": return false case "container": if len(commands) < 3 { diff --git a/cmd/nerdctl/version.go b/cmd/nerdctl/version.go index f74a9d44846..3ce1cfe28ba 100644 --- a/cmd/nerdctl/version.go +++ b/cmd/nerdctl/version.go @@ -23,11 +23,12 @@ import ( "os" "text/template" - "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -66,7 +67,17 @@ func versionAction(cmd *cobra.Command, args []string) error { } } - v, vErr := versionInfo(cmd, globalOptions) + address := globalOptions.Address + // rootless `nerdctl version` runs in the host namespaces, so the address is different + if rootlessutil.IsRootless() { + address, err = rootlessutil.RootlessContainredSockAddress() + if err != nil { + logrus.WithError(err).Warning("failed to inspect the rootless containerd socket address") + address = "" + } + } + + v, vErr := versionInfo(cmd, globalOptions.Namespace, address) if tmpl != nil { var b bytes.Buffer if err := tmpl.Execute(&b, v); err != nil { @@ -102,13 +113,16 @@ func versionAction(cmd *cobra.Command, args []string) error { return vErr } -// versionInfo may return partial VersionInfo on error -func versionInfo(cmd *cobra.Command, globalOptions types.GlobalCommandOptions) (dockercompat.VersionInfo, error) { - +// versionInfo may return partial VersionInfo on error. +// Address can be empty to skip inspecting the server. +func versionInfo(cmd *cobra.Command, ns, address string) (dockercompat.VersionInfo, error) { v := dockercompat.VersionInfo{ Client: infoutil.ClientVersion(), } - client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) + if address == "" { + return v, nil + } + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), ns, address) if err != nil { return v, err } From c407ceb53e8ddb248212484ea1ba833ff54ce727 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Sep 2023 22:08:14 +0000 Subject: [PATCH 0141/1066] build(deps): bump github.com/compose-spec/compose-go Bumps [github.com/compose-spec/compose-go](https://github.com/compose-spec/compose-go) from 1.18.4 to 1.19.0. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v1.18.4...v1.19.0) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f18ce36c2e1..9a7a5c52973 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.11.0 github.com/awslabs/soci-snapshotter v0.4.0 - github.com/compose-spec/compose-go v1.18.4 + github.com/compose-spec/compose-go v1.19.0 github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 diff --git a/go.sum b/go.sum index 850157786e4..87200f4b88e 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go v1.18.4 h1:yLYfsc3ATAYZVAJcXyx/V847/JVBmf3pfKfR13mXU4s= -github.com/compose-spec/compose-go v1.18.4/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= +github.com/compose-spec/compose-go v1.19.0 h1:t68gAcwStDg0hy2kFvqHJIksf6xkqRnlSKfL45/ETqo= +github.com/compose-spec/compose-go v1.19.0/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= github.com/containerd/accelerated-container-image v0.6.7 h1:QDO12lgUubiUq0ogMzcL6CdSxkzFOX7vVaSIXAJ9EaM= github.com/containerd/accelerated-container-image v0.6.7/go.mod h1:a7MYTlNhR4+GGpXD7wuNSgxrwC2wE2rgUfCvef+FQzg= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= From 20f929d1b11f464f831ebbc830a1a00484959583 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 21 Sep 2023 17:13:56 +0000 Subject: [PATCH 0142/1066] add featrue network filter Signed-off-by: Kay Yan --- cmd/nerdctl/network_list.go | 7 +- cmd/nerdctl/network_list_linux_test.go | 76 ++++++++++++++++++++++ docs/command-reference.md | 2 +- pkg/api/types/network_types.go | 2 + pkg/cmd/network/list.go | 88 +++++++++++++++++++++++--- 5 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 cmd/nerdctl/network_list_linux_test.go diff --git a/cmd/nerdctl/network_list.go b/cmd/nerdctl/network_list.go index c45b1e6f7b1..73d2dac2807 100644 --- a/cmd/nerdctl/network_list.go +++ b/cmd/nerdctl/network_list.go @@ -33,7 +33,7 @@ func newNetworkLsCommand() *cobra.Command { SilenceErrors: true, } cmd.Flags().BoolP("quiet", "q", false, "Only display network IDs") - // Alias "-f" is reserved for "--filter" + cmd.Flags().StringSliceP("filter", "f", []string{}, "Provide filter values (e.g. \"name=default\")") cmd.Flags().String("format", "", "Format the output using the given Go template, e.g, '{{json .}}'") cmd.RegisterFlagCompletionFunc("format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"json", "table", "wide"}, cobra.ShellCompDirectiveNoFileComp @@ -54,10 +54,15 @@ func networkLsAction(cmd *cobra.Command, args []string) error { if err != nil { return err } + filters, err := cmd.Flags().GetStringSlice("filter") + if err != nil { + return err + } return network.List(cmd.Context(), types.NetworkListOptions{ GOptions: globalOptions, Quiet: quiet, Format: format, + Filters: filters, Stdout: cmd.OutOrStdout(), }) } diff --git a/cmd/nerdctl/network_list_linux_test.go b/cmd/nerdctl/network_list_linux_test.go new file mode 100644 index 00000000000..5bbb5e2f9b8 --- /dev/null +++ b/cmd/nerdctl/network_list_linux_test.go @@ -0,0 +1,76 @@ +/* + 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 ( + "errors" + "fmt" + "strings" + "testing" + + "github.com/containerd/nerdctl/pkg/testutil" +) + +func TestNetworkLsFilter(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + tID := testutil.Identifier(t) + + var net1, net2 = tID + "net-1", tID + "net-2" + var label1 = tID + "=label-1" + netID1 := base.Cmd("network", "create", "--label="+label1, net1).Out() + defer base.Cmd("network", "rm", "-f", netID1).Run() + + netID2 := base.Cmd("network", "create", net2).Out() + defer base.Cmd("network", "rm", "-f", netID2).Run() + + base.Cmd("network", "ls", "--quiet", "--filter", "label="+tID).AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 1 { + return errors.New("expected at least 1 lines") + } + netNames := map[string]struct{}{ + netID1[:12]: {}, + } + + for _, name := range lines { + _, ok := netNames[name] + if !ok { + return fmt.Errorf("unexpected netume %s found", name) + } + } + return nil + }) + + base.Cmd("network", "ls", "--quiet", "--filter", "name="+net2).AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 1 { + return errors.New("expected at least 1 lines") + } + netNames := map[string]struct{}{ + netID2[:12]: {}, + } + + for _, name := range lines { + _, ok := netNames[name] + if !ok { + return fmt.Errorf("unexpected netume %s found", name) + } + } + return nil + }) +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 31f5e0d52ff..057681e7af0 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1008,7 +1008,7 @@ Flags: - :nerd_face: `--format=wide`: Alias of `--format=table` - :nerd_face: `--format=json`: Alias of `--format='{{json .}}'` -Unimplemented `docker network ls` flags: `--filter`, `--no-trunc` +Unimplemented `docker network ls` flags: `--no-trunc` ### :whale: nerdctl network inspect diff --git a/pkg/api/types/network_types.go b/pkg/api/types/network_types.go index 4a65ff2122d..a3f15e7d69e 100644 --- a/pkg/api/types/network_types.go +++ b/pkg/api/types/network_types.go @@ -52,6 +52,8 @@ type NetworkListOptions struct { Quiet bool // Format the output using the given Go template, e.g, '{{json .}}', 'wide' Format string + // Filter matches network based on given conditions + Filters []string } // NetworkPruneOptions specifies options for `nerdctl network prune`. diff --git a/pkg/cmd/network/list.go b/pkg/cmd/network/list.go index e7f7f952b13..a045900ff35 100644 --- a/pkg/cmd/network/list.go +++ b/pkg/cmd/network/list.go @@ -21,6 +21,7 @@ import ( "context" "errors" "fmt" + "strings" "text/tabwriter" "text/template" @@ -42,6 +43,7 @@ func List(ctx context.Context, options types.NetworkListOptions) error { quiet := options.Quiet format := options.Format w := options.Stdout + filters := options.Filters var tmpl *template.Template switch format { @@ -71,6 +73,21 @@ func List(ctx context.Context, options types.NetworkListOptions) error { if err != nil { return err } + + labelFilterFuncs, nameFilterFuncs, err := getNetworkFilterFuncs(filters) + if err != nil { + return err + } + if len(filters) > 0 { + filtered := make([]*netutil.NetworkConfig, 0) + for _, net := range netConfigs { + if networkMatchesFilter(net, labelFilterFuncs, nameFilterFuncs) { + filtered = append(filtered, net) + } + } + netConfigs = filtered + } + pp := make([]networkPrintable, len(netConfigs)) for i, n := range netConfigs { p := networkPrintable{ @@ -90,14 +107,16 @@ func List(ctx context.Context, options types.NetworkListOptions) error { } // append pseudo networks - pp = append(pp, []networkPrintable{ - { - Name: "host", - }, - { - Name: "none", - }, - }...) + if len(filters) == 0 { // filter a pseudo networks is meanless + pp = append(pp, []networkPrintable{ + { + Name: "host", + }, + { + Name: "none", + }, + }...) + } for _, p := range pp { if tmpl != nil { @@ -121,3 +140,56 @@ func List(ctx context.Context, options types.NetworkListOptions) error { } return nil } + +func getNetworkFilterFuncs(filters []string) ([]func(*map[string]string) bool, []func(string) bool, error) { + labelFilterFuncs := make([]func(*map[string]string) bool, 0) + nameFilterFuncs := make([]func(string) bool, 0) + + for _, filter := range filters { + if strings.HasPrefix(filter, "name") || strings.HasPrefix(filter, "label") { + subs := strings.SplitN(filter, "=", 2) + if len(subs) < 2 { + continue + } + switch subs[0] { + case "name": + nameFilterFuncs = append(nameFilterFuncs, func(name string) bool { + return strings.Contains(name, subs[1]) + }) + case "label": + v, k, hasValue := "", subs[1], false + if subs := strings.SplitN(subs[1], "=", 2); len(subs) == 2 { + hasValue = true + k, v = subs[0], subs[1] + } + labelFilterFuncs = append(labelFilterFuncs, func(labels *map[string]string) bool { + if labels == nil { + return false + } + val, ok := (*labels)[k] + if !ok || (hasValue && val != v) { + return false + } + return true + }) + } + continue + } + } + return labelFilterFuncs, nameFilterFuncs, nil +} + +func networkMatchesFilter(net *netutil.NetworkConfig, labelFilterFuncs []func(*map[string]string) bool, nameFilterFuncs []func(string) bool) bool { + for _, labelFilterFunc := range labelFilterFuncs { + if !labelFilterFunc(net.NerdctlLabels) { + return false + } + } + for _, nameFilterFunc := range nameFilterFuncs { + if !nameFilterFunc(net.Name) { + return false + } + } + + return true +} From 1b5a98677a9a133a407be308e0fcc3f9db47f045 Mon Sep 17 00:00:00 2001 From: tanghao Date: Sat, 16 Sep 2023 16:20:29 +0800 Subject: [PATCH 0143/1066] add missing flags for compose ps Signed-off-by: tanghao --- cmd/nerdctl/compose_create_linux_test.go | 14 +-- cmd/nerdctl/compose_down_linux_test.go | 2 +- cmd/nerdctl/compose_kill_linux_test.go | 2 +- cmd/nerdctl/compose_pause_linux_test.go | 2 +- cmd/nerdctl/compose_ps.go | 130 +++++++++++++++++++++- cmd/nerdctl/compose_ps_linux_test.go | 87 ++++++++++++++- cmd/nerdctl/compose_restart_linux_test.go | 7 +- cmd/nerdctl/compose_stop_linux_test.go | 4 +- docs/command-reference.md | 14 ++- 9 files changed, 232 insertions(+), 30 deletions(-) diff --git a/cmd/nerdctl/compose_create_linux_test.go b/cmd/nerdctl/compose_create_linux_test.go index 7935d437c36..5e5ce315ec7 100644 --- a/cmd/nerdctl/compose_create_linux_test.go +++ b/cmd/nerdctl/compose_create_linux_test.go @@ -24,10 +24,6 @@ import ( ) func TestComposeCreate(t *testing.T) { - // docker-compose v1 depecreated this command - // docker-compose v2 reimplemented this command - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` version: '3.1' @@ -46,7 +42,7 @@ services: // 1.1 `compose create` should create service container (in `created` status) base.ComposeCmd("-f", comp.YAMLFullPath(), "create").AssertOK() - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc0").AssertOutContainsAny("Created", "created") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc0", "-a").AssertOutContainsAny("Created", "created") // 1.2 created container can be started by `compose start` base.ComposeCmd("-f", comp.YAMLFullPath(), "start").AssertOK() } @@ -78,8 +74,8 @@ services: // `compose create` should create containers for both services and their dependencies base.ComposeCmd("-f", comp.YAMLFullPath(), "create", "svc0").AssertOK() - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc0").AssertOutContainsAny("Created", "created") - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc1").AssertOutContainsAny("Created", "created") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc0", "-a").AssertOutContainsAny("Created", "created") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc1", "-a").AssertOutContainsAny("Created", "created") } func TestComposeCreatePull(t *testing.T) { @@ -111,7 +107,7 @@ services: base.ComposeCmd("-f", comp.YAMLFullPath(), "create").AssertOK() base.Cmd("rmi", "-f", testutil.AlpineImage).Run() base.ComposeCmd("-f", comp.YAMLFullPath(), "create", "--pull", "always").AssertOK() - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc0").AssertOutContainsAny("Created", "created") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc0", "-a").AssertOutContainsAny("Created", "created") } func TestComposeCreateBuild(t *testing.T) { @@ -148,5 +144,5 @@ services: // `compose create --build` should succeed: image is built and container is created base.ComposeCmd("-f", comp.YAMLFullPath(), "create", "--build").AssertOK() base.ComposeCmd("-f", comp.YAMLFullPath(), "images", "svc0").AssertOutContains(imageSvc0) - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc0").AssertOutContainsAny("Created", "created") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc0", "-a").AssertOutContainsAny("Created", "created") } diff --git a/cmd/nerdctl/compose_down_linux_test.go b/cmd/nerdctl/compose_down_linux_test.go index 5b3943f3782..64c55479408 100644 --- a/cmd/nerdctl/compose_down_linux_test.go +++ b/cmd/nerdctl/compose_down_linux_test.go @@ -99,5 +99,5 @@ services: defer base.ComposeCmd("-p", projectName, "-f", compFull.YAMLFullPath(), "down", "-v").Run() base.ComposeCmd("-p", projectName, "-f", compOrphan.YAMLFullPath(), "down", "--remove-orphans").AssertOK() - base.ComposeCmd("-p", projectName, "-f", compFull.YAMLFullPath(), "ps").AssertOutNotContains(orphanContainer) + base.ComposeCmd("-p", projectName, "-f", compFull.YAMLFullPath(), "ps", "-a").AssertOutNotContains(orphanContainer) } diff --git a/cmd/nerdctl/compose_kill_linux_test.go b/cmd/nerdctl/compose_kill_linux_test.go index 3d948ebadb8..cdcc6245e41 100644 --- a/cmd/nerdctl/compose_kill_linux_test.go +++ b/cmd/nerdctl/compose_kill_linux_test.go @@ -73,6 +73,6 @@ volumes: base.ComposeCmd("-f", comp.YAMLFullPath(), "kill", "db").AssertOK() time.Sleep(3 * time.Second) // Docker Compose v1: "Exit 137", v2: "exited (137)" - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db").AssertOutContainsAny(" 137", "(137)") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db", "-a").AssertOutContainsAny(" 137", "(137)") base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "wordpress").AssertOutContainsAny("Up", "running") } diff --git a/cmd/nerdctl/compose_pause_linux_test.go b/cmd/nerdctl/compose_pause_linux_test.go index aaccca155bd..e6fe615ec4d 100644 --- a/cmd/nerdctl/compose_pause_linux_test.go +++ b/cmd/nerdctl/compose_pause_linux_test.go @@ -52,7 +52,7 @@ services: // pause a service should (only) pause its own container base.ComposeCmd("-f", comp.YAMLFullPath(), "pause", "svc0").AssertOK() - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc0").AssertOutContainsAny("Paused", "paused") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc0", "-a").AssertOutContainsAny("Paused", "paused") base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "svc1").AssertOutContainsAny("Up", "running") // unpause should be able to recover the paused service container diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose_ps.go index 54f0ba1e596..88c4437720b 100644 --- a/cmd/nerdctl/compose_ps.go +++ b/cmd/nerdctl/compose_ps.go @@ -19,9 +19,13 @@ package main import ( "context" "fmt" + "strings" "text/tabwriter" + "time" "github.com/containerd/containerd" + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/runtime/restart" gocni "github.com/containerd/go-cni" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/compose" @@ -42,7 +46,12 @@ func newComposePsCommand() *cobra.Command { SilenceUsage: true, SilenceErrors: true, } - composePsCommand.Flags().String("format", "", "Format the output. Supported values: [json]") + composePsCommand.Flags().String("format", "table", "Format the output. Supported values: [table|json]") + composePsCommand.Flags().String("filter", "", "Filter matches containers based on given conditions") + composePsCommand.Flags().StringArray("status", []string{}, "Filter services by status. Values: [paused | restarting | removing | running | dead | created | exited]") + composePsCommand.Flags().BoolP("quiet", "q", false, "Only display container IDs") + composePsCommand.Flags().Bool("services", false, "Display services") + composePsCommand.Flags().BoolP("all", "a", false, "Show all containers (default shows just running)") return composePsCommand } @@ -71,8 +80,40 @@ func composePsAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - if format != "json" && format != "" { - return fmt.Errorf("unsupported format %s, supported formats are: [json]", format) + if format != "json" && format != "table" { + return fmt.Errorf("unsupported format %s, supported formats are: [table|json]", format) + } + status, err := cmd.Flags().GetStringArray("status") + if err != nil { + return err + } + quiet, err := cmd.Flags().GetBool("quiet") + if err != nil { + return err + } + displayServices, err := cmd.Flags().GetBool("services") + if err != nil { + return err + } + filter, err := cmd.Flags().GetString("filter") + if err != nil { + return err + } + if filter != "" { + splited := strings.SplitN(filter, "=", 2) + if len(splited) != 2 { + return fmt.Errorf("invalid argument \"%s\" for \"-f, --filter\": bad format of filter (expected name=value)", filter) + } + // currently only the 'status' filter is supported + if splited[0] != "status" { + return fmt.Errorf("invalid filter '%s'", splited[0]) + } + status = append(status, splited[1]) + } + + all, err := cmd.Flags().GetBool("all") + if err != nil { + return err } client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) @@ -97,6 +138,41 @@ func composePsAction(cmd *cobra.Command, args []string) error { return err } + if !all { + var upContainers []containerd.Container + for _, container := range containers { + // cStatus := formatter.ContainerStatus(ctx, c) + cStatus, err := containerutil.ContainerStatus(ctx, container) + if err != nil { + continue + } + if cStatus.Status == containerd.Running { + upContainers = append(upContainers, container) + } + } + containers = upContainers + } + + if len(status) != 0 { + var filterdContainers []containerd.Container + for _, container := range containers { + cStatus := statusForFilter(ctx, container) + for _, s := range status { + if cStatus == s { + filterdContainers = append(filterdContainers, container) + } + } + } + containers = filterdContainers + } + + if quiet { + for _, c := range containers { + fmt.Fprintln(cmd.OutOrStdout(), c.ID()) + } + return nil + } + containersPrintable := make([]composeContainerPrintable, len(containers)) eg, ctx := errgroup.WithContext(ctx) for i, container := range containers { @@ -121,6 +197,12 @@ func composePsAction(cmd *cobra.Command, args []string) error { return err } + if displayServices { + for _, p := range containersPrintable { + fmt.Fprintln(cmd.OutOrStdout(), p.Service) + } + return nil + } if format == "json" { outJSON, err := formatter.ToJSON(containersPrintable, "", "") if err != nil { @@ -198,9 +280,11 @@ func composeContainerPrintableJSON(ctx context.Context, container containerd.Con if err == nil { // show exitCode only when container is exited/stopped if status.Status == containerd.Stopped { + state = "exited" exitCode = status.ExitStatus + } else { + state = string(status.Status) } - state = string(status.Status) } else { state = string(containerd.Unknown) } @@ -255,3 +339,41 @@ func formatPublishers(labelMap map[string]string) []PortPublisher { } return dockerPorts } + +// statusForFilter returns the status value to be matched with the 'status' filter +func statusForFilter(ctx context.Context, c containerd.Container) string { + // Just in case, there is something wrong in server. + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + task, err := c.Task(ctx, nil) + if err != nil { + // NOTE: NotFound doesn't mean that container hasn't started. + // In docker/CRI-containerd plugin, the task will be deleted + // when it exits. So, the status will be "created" for this + // case. + if errdefs.IsNotFound(err) { + return string(containerd.Created) + } + return string(containerd.Unknown) + } + + status, err := task.Status(ctx) + if err != nil { + return string(containerd.Unknown) + } + labels, err := c.Labels(ctx) + if err != nil { + return string(containerd.Unknown) + } + + switch s := status.Status; s { + case containerd.Stopped: + if labels[restart.StatusLabel] == string(containerd.Running) && restart.Reconcile(status, labels) { + return "restarting" + } + return "exited" + default: + return string(s) + } +} diff --git a/cmd/nerdctl/compose_ps_linux_test.go b/cmd/nerdctl/compose_ps_linux_test.go index 7fdda4a47ae..453829bbba4 100644 --- a/cmd/nerdctl/compose_ps_linux_test.go +++ b/cmd/nerdctl/compose_ps_linux_test.go @@ -21,13 +21,92 @@ import ( "fmt" "strings" "testing" + "time" + "github.com/containerd/nerdctl/pkg/tabutil" "github.com/containerd/nerdctl/pkg/testutil" + "gotest.tools/v3/assert" ) +func TestComposePs(t *testing.T) { + base := testutil.NewBase(t) + var dockerComposeYAML = fmt.Sprintf(` +version: '3.1' + +services: + wordpress: + image: %s + container_name: wordpress_container + ports: + - 8080:80 + environment: + WORDPRESS_DB_HOST: db + WORDPRESS_DB_USER: exampleuser + WORDPRESS_DB_PASSWORD: examplepass + WORDPRESS_DB_NAME: exampledb + volumes: + - wordpress:/var/www/html + db: + image: %s + container_name: db_container + environment: + MYSQL_DATABASE: exampledb + MYSQL_USER: exampleuser + MYSQL_PASSWORD: examplepass + MYSQL_RANDOM_ROOT_PASSWORD: '1' + volumes: + - db:/var/lib/mysql + alpine: + image: %s + container_name: alpine_container + +volumes: + wordpress: + db: +`, testutil.WordpressImage, testutil.MariaDBImage, testutil.AlpineImage) + comp := testutil.NewComposeDir(t, dockerComposeYAML) + defer comp.CleanUp() + projectName := comp.ProjectName() + t.Logf("projectName=%q", projectName) + + base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "-d").AssertOK() + defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() + + assertHandler := func(expectedName, expectedImage string) func(stdout string) error { + return func(stdout string) error { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 2 { + return fmt.Errorf("expected at least 2 lines, got %d", len(lines)) + } + + tab := tabutil.NewReader("NAME\tIMAGE\tCOMMAND\tSERVICE\tSTATUS\tPORTS") + err := tab.ParseHeader(lines[0]) + if err != nil { + return fmt.Errorf("failed to parse header: %v", err) + } + + container, _ := tab.ReadRow(lines[1], "NAME") + assert.Equal(t, container, expectedName) + + image, _ := tab.ReadRow(lines[1], "IMAGE") + assert.Equal(t, image, expectedImage) + + return nil + } + + } + + time.Sleep(3 * time.Second) + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "wordpress").AssertOutWithFunc(assertHandler("wordpress_container", testutil.WordpressImage)) + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db").AssertOutWithFunc(assertHandler("db_container", testutil.MariaDBImage)) + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps").AssertOutNotContains(testutil.AlpineImage) + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "alpine", "-a").AssertOutWithFunc(assertHandler("alpine_container", testutil.AlpineImage)) + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "-a", "--filter", "status=exited").AssertOutWithFunc(assertHandler("alpine_container", testutil.AlpineImage)) + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "--services", "-a").AssertOutContainsAll("wordpress\n", "db\n", "alpine\n") +} + func TestComposePsJSON(t *testing.T) { - // `--format` is only supported in docker compose v2. - // Currently, CI is using docker compose v1. + // docker parses unknown 'format' as a Go template and won't output an error testutil.DockerIncompatible(t) base := testutil.NewBase(t) @@ -101,8 +180,8 @@ volumes: AssertOutWithFunc(assertHandler("wordpress", 1, `"Service":"wordpress"`, `"State":"running"`, `"TargetPort":80`, `"PublishedPort":8080`)) // check wordpress is stopped base.ComposeCmd("-f", comp.YAMLFullPath(), "stop", "wordpress").AssertOK() - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "--format", "json", "wordpress"). - AssertOutWithFunc(assertHandler("wordpress", 1, `"Service":"wordpress"`, `"State":"stopped"`)) + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "--format", "json", "wordpress", "-a"). + AssertOutWithFunc(assertHandler("wordpress", 1, `"Service":"wordpress"`, `"State":"exited"`)) // check wordpress is removed base.ComposeCmd("-f", comp.YAMLFullPath(), "rm", "-f", "wordpress").AssertOK() base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "--format", "json", "wordpress"). diff --git a/cmd/nerdctl/compose_restart_linux_test.go b/cmd/nerdctl/compose_restart_linux_test.go index 8de3513fd41..ed1d2bd1466 100644 --- a/cmd/nerdctl/compose_restart_linux_test.go +++ b/cmd/nerdctl/compose_restart_linux_test.go @@ -24,9 +24,6 @@ import ( ) func TestComposeRestart(t *testing.T) { - // docker-compose v2 hides exited containers in `compose ps`, and shows - // them if `-a` is passed, which is not supported yet by `nerdctl compose`. - testutil.DockerIncompatible(t) base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` version: '3.1' @@ -68,13 +65,13 @@ volumes: // stop and restart a single service. base.ComposeCmd("-f", comp.YAMLFullPath(), "stop", "db").AssertOK() - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db").AssertOutContainsAny("Exit", "exited") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db", "-a").AssertOutContainsAny("Exit", "exited") base.ComposeCmd("-f", comp.YAMLFullPath(), "restart", "db").AssertOK() base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db").AssertOutContainsAny("Up", "running") // stop one service and restart all (also check `--timeout` arg). base.ComposeCmd("-f", comp.YAMLFullPath(), "stop", "db").AssertOK() - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db").AssertOutContainsAny("Exit", "exited") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db", "-a").AssertOutContainsAny("Exit", "exited") base.ComposeCmd("-f", comp.YAMLFullPath(), "restart", "--timeout", "5").AssertOK() base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db").AssertOutContainsAny("Up", "running") base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "wordpress").AssertOutContainsAny("Up", "running") diff --git a/cmd/nerdctl/compose_stop_linux_test.go b/cmd/nerdctl/compose_stop_linux_test.go index cadff7f30fd..35377ad5da0 100644 --- a/cmd/nerdctl/compose_stop_linux_test.go +++ b/cmd/nerdctl/compose_stop_linux_test.go @@ -70,11 +70,11 @@ volumes: // stop should (only) stop the given service. base.ComposeCmd("-f", comp.YAMLFullPath(), "stop", "db").AssertOK() - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db").AssertOutContainsAny("Exit", "exited") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "db", "-a").AssertOutContainsAny("Exit", "exited") base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "wordpress").AssertOutContainsAny("Up", "running") // `--timeout` arg should work properly. base.ComposeCmd("-f", comp.YAMLFullPath(), "stop", "--timeout", "5", "wordpress").AssertOK() - base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "wordpress").AssertOutContainsAny("Exit", "exited") + base.ComposeCmd("-f", comp.YAMLFullPath(), "ps", "wordpress", "-a").AssertOutContainsAny("Exit", "exited") } diff --git a/docs/command-reference.md b/docs/command-reference.md index 057681e7af0..e9a9a0675d4 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1490,9 +1490,17 @@ List containers of services Usage: `nerdctl compose ps [OPTIONS] [SERVICE...]` -Unimplemented `docker-compose ps` (V1) flags: `--quiet`, `--services`, `--filter`, `--all` - -Unimplemented `docker compose ps` (V2) flags: `--status` +- :whale: `-a, --all`: Show all containers (default shows just running) +- :whale: `-q, --quiet`: Only display container IDs +- :whale: `--format`: Format the output + - :whale: `--format=table` (default): Table + - :whale: `--format=json'`: JSON +- :whale: `-f, --filter`: Filter containers based on given conditions + - :whale: `--filter status=`: One of `created, running, paused, + restarting, exited, pausing, unknown`. Note that `removing, dead` are + not supported and will be ignored +- :whale: `--services`: Print the service names, one per line +- :whale: `--status`: Filter containers by status. Values: [paused | restarting | running | created | exited | pausing | unknown] ### :whale: nerdctl compose pull From 4b5129b5542b89b84a6fb82eced68dbed81ae825 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 22:43:31 +0000 Subject: [PATCH 0144/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.11.0 to 0.11.1 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.11.0 to 0.11.1. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.11.0...v0.11.1) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9a7a5c52973..e1d5b913cda 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 - github.com/Microsoft/hcsshim v0.11.0 + github.com/Microsoft/hcsshim v0.11.1 github.com/awslabs/soci-snapshotter v0.4.0 github.com/compose-spec/compose-go v1.19.0 github.com/containerd/accelerated-container-image v0.6.7 diff --git a/go.sum b/go.sum index 87200f4b88e..3a060eb859b 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 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.0 h1:7EFNIY4igHEXUdj1zXgAyU3fLc7QfOKHbkldRVTBdiM= -github.com/Microsoft/hcsshim v0.11.0/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= +github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= github.com/awslabs/soci-snapshotter v0.4.0 h1:dA9lOYbzSUaYMahB8qXQZTVXUszhc0w8rwjRs6EPd24= github.com/awslabs/soci-snapshotter v0.4.0/go.mod h1:+ST8F4E/b6b6pnFBJKprdvzkxyXODMs0FC2TmclkgJc= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= From a9fb4c563450db41f37edb049735320a0b5d19e4 Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Fri, 22 Sep 2023 17:59:29 +0800 Subject: [PATCH 0145/1066] chore: Comment should with an optional leading article Signed-off-by: guoguangwu --- .../container_network_manager.go | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 77e8dfaeabc..e8db23cd545 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -83,23 +83,23 @@ func withCustomHosts(src string) func(context.Context, oci.Client, *containers.C } } -// types.NetworkOptionsManager is an interface for reading/setting networking +// NetworkOptionsManager types.NetworkOptionsManager is an interface for reading/setting networking // options for containers based on the provided command flags. type NetworkOptionsManager interface { - // Returns a copy of the internal types.NetworkOptions. + // NetworkOptions Returns a copy of the internal types.NetworkOptions. NetworkOptions() types.NetworkOptions - // Verifies that the internal network settings are correct. + // VerifyNetworkOptions Verifies that the internal network settings are correct. VerifyNetworkOptions(context.Context) error - // Performs setup actions required for the container with the given ID. + // SetupNetworking Performs setup actions required for the container with the given ID. SetupNetworking(context.Context, string) error - // Performs any required cleanup actions for the given container. + // CleanupNetworking Performs any required cleanup actions for the given container. // Should only be called to revert any setup steps performed in SetupNetworking. CleanupNetworking(context.Context, containerd.Container) error - // Returns the set of NetworkingOptions which should be set as labels on the container. + // InternalNetworkingOptionLabels Returns the set of NetworkingOptions which should be set as labels on the container. // // These options can potentially differ from the actual networking options // that the NetworkOptionsManager was initially instantiated with. @@ -107,12 +107,12 @@ type NetworkOptionsManager interface { // `--net=container:myContainer` => `--net=container:`. InternalNetworkingOptionLabels(context.Context) (types.NetworkOptions, error) - // Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent + // ContainerNetworkingOpts Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent // the network specs which need to be applied to the container with the given ID. ContainerNetworkingOpts(context.Context, string) ([]oci.SpecOpts, []containerd.NewContainerOpts, error) } -// Returns a types.NetworkOptionsManager based on the provided command's flags. +// NewNetworkingOptionsManager Returns a types.NetworkOptionsManager based on the provided command's flags. func NewNetworkingOptionsManager(globalOptions types.GlobalCommandOptions, netOpts types.NetworkOptions) (NetworkOptionsManager, error) { netType, err := nettype.Detect(netOpts.NetworkSlice) if err != nil { @@ -142,34 +142,34 @@ type noneNetworkManager struct { netOpts types.NetworkOptions } -// Returns a copy of the internal types.NetworkOptions. +// NetworkOptions Returns a copy of the internal types.NetworkOptions. func (m *noneNetworkManager) NetworkOptions() types.NetworkOptions { return m.netOpts } -// Verifies that the internal network settings are correct. +// VerifyNetworkOptions Verifies that the internal network settings are correct. func (m *noneNetworkManager) VerifyNetworkOptions(_ context.Context) error { // No options to verify if no network settings are provided. return nil } -// Performs setup actions required for the container with the given ID. +// SetupNetworking Performs setup actions required for the container with the given ID. func (m *noneNetworkManager) SetupNetworking(_ context.Context, _ string) error { return nil } -// Performs any required cleanup actions for the given container. +// CleanupNetworking Performs any required cleanup actions for the given container. // Should only be called to revert any setup steps performed in SetupNetworking. func (m *noneNetworkManager) CleanupNetworking(_ context.Context, _ containerd.Container) error { return nil } -// Returns the set of NetworkingOptions which should be set as labels on the container. +// InternalNetworkingOptionLabels Returns the set of NetworkingOptions which should be set as labels on the container. func (m *noneNetworkManager) InternalNetworkingOptionLabels(_ context.Context) (types.NetworkOptions, error) { return m.netOpts, nil } -// Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent +// ContainerNetworkingOpts Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent // the network specs which need to be applied to the container with the given ID. func (m *noneNetworkManager) ContainerNetworkingOpts(_ context.Context, _ string) ([]oci.SpecOpts, []containerd.NewContainerOpts, error) { // No options to return if no network settings are provided. @@ -182,12 +182,12 @@ type containerNetworkManager struct { netOpts types.NetworkOptions } -// Returns a copy of the internal types.NetworkOptions. +// NetworkOptions Returns a copy of the internal types.NetworkOptions. func (m *containerNetworkManager) NetworkOptions() types.NetworkOptions { return m.netOpts } -// Verifies that the internal network settings are correct. +// VerifyNetworkOptions Verifies that the internal network settings are correct. func (m *containerNetworkManager) VerifyNetworkOptions(_ context.Context) error { // TODO: check host OS, not client-side OS. if runtime.GOOS != "linux" { @@ -233,14 +233,14 @@ func (m *containerNetworkManager) getContainerNetworkFilePaths(containerID strin return hostnamePath, resolvConfPath, etcHostsPath, nil } -// Performs setup actions required for the container with the given ID. +// SetupNetworking Performs setup actions required for the container with the given ID. func (m *containerNetworkManager) SetupNetworking(_ context.Context, _ string) error { // NOTE: container networking simply reuses network config files from the // bridged container so there are no setup/teardown steps required. return nil } -// Performs any required cleanup actions for the given container. +// CleanupNetworking Performs any required cleanup actions for the given container. // Should only be called to revert any setup steps performed in SetupNetworking. func (m *containerNetworkManager) CleanupNetworking(_ context.Context, _ containerd.Container) error { // NOTE: container networking simply reuses network config files from the @@ -284,7 +284,7 @@ func (m *containerNetworkManager) getNetworkingContainerForArgument(ctx context. return foundContainer, nil } -// Returns the set of NetworkingOptions which should be set as labels on the container. +// InternalNetworkingOptionLabels Returns the set of NetworkingOptions which should be set as labels on the container. func (m *containerNetworkManager) InternalNetworkingOptionLabels(ctx context.Context) (types.NetworkOptions, error) { opts := m.netOpts if m.netOpts.NetworkSlice == nil || len(m.netOpts.NetworkSlice) != 1 { @@ -300,7 +300,7 @@ func (m *containerNetworkManager) InternalNetworkingOptionLabels(ctx context.Con return opts, nil } -// Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent +// ContainerNetworkingOpts Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent // the network specs which need to be applied to the container with the given ID. func (m *containerNetworkManager) ContainerNetworkingOpts(ctx context.Context, _ string) ([]oci.SpecOpts, []containerd.NewContainerOpts, error) { opts := []oci.SpecOpts{} @@ -348,12 +348,12 @@ type hostNetworkManager struct { netOpts types.NetworkOptions } -// Returns a copy of the internal types.NetworkOptions. +// NetworkOptions Returns a copy of the internal types.NetworkOptions. func (m *hostNetworkManager) NetworkOptions() types.NetworkOptions { return m.netOpts } -// Verifies that the internal network settings are correct. +// VerifyNetworkOptions Verifies that the internal network settings are correct. func (m *hostNetworkManager) VerifyNetworkOptions(_ context.Context) error { // TODO: check host OS, not client-side OS. if runtime.GOOS == "windows" { @@ -367,20 +367,20 @@ func (m *hostNetworkManager) VerifyNetworkOptions(_ context.Context) error { return validateUtsSettings(m.netOpts) } -// Performs setup actions required for the container with the given ID. +// SetupNetworking Performs setup actions required for the container with the given ID. func (m *hostNetworkManager) SetupNetworking(_ context.Context, _ string) error { // NOTE: there are no setup steps required for host networking. return nil } -// Performs any required cleanup actions for the given container. +// CleanupNetworking Performs any required cleanup actions for the given container. // Should only be called to revert any setup steps performed in SetupNetworking. func (m *hostNetworkManager) CleanupNetworking(_ context.Context, _ containerd.Container) error { // NOTE: there are no setup steps required for host networking. return nil } -// Returns the set of NetworkingOptions which should be set as labels on the container. +// InternalNetworkingOptionLabels Returns the set of NetworkingOptions which should be set as labels on the container. func (m *hostNetworkManager) InternalNetworkingOptionLabels(_ context.Context) (types.NetworkOptions, error) { opts := m.netOpts // Cannot have a MAC address in host networking mode. @@ -388,7 +388,7 @@ func (m *hostNetworkManager) InternalNetworkingOptionLabels(_ context.Context) ( return opts, nil } -// Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent +// ContainerNetworkingOpts Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent // the network specs which need to be applied to the container with the given ID. func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containerID string) ([]oci.SpecOpts, []containerd.NewContainerOpts, error) { @@ -432,7 +432,7 @@ type cniNetworkManager struct { netNs *netns.NetNS } -// Returns a copy of the internal types.NetworkOptions. +// NetworkOptions Returns a copy of the internal types.NetworkOptions. func (m *cniNetworkManager) NetworkOptions() types.NetworkOptions { return m.netOpts } @@ -504,7 +504,7 @@ func verifyNetworkTypes(env *netutil.CNIEnv, networkSlice []string, supportedTyp return res, nil } -// Returns the NetworkOptions used in a container's creation from its spec.Annotations. +// NetworkOptionsFromSpec Returns the NetworkOptions used in a container's creation from its spec.Annotations. func NetworkOptionsFromSpec(spec *specs.Spec) (types.NetworkOptions, error) { opts := types.NetworkOptions{} From 3b644b19078333a16888f497a20323a287f072f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 22:37:43 +0000 Subject: [PATCH 0146/1066] build(deps): bump actions/checkout from 4.0.0 to 4.1.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.0.0...v4.1.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 20 +++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 5c5c483a555..f1672c0699f 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 680c8c45ff5..576f90e6e1b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 - uses: actions/setup-go@v4 with: go-version: 1.21.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 484d31da6d4..5c2c921b3b7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -88,7 +88,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -141,7 +141,7 @@ jobs: CONTAINERD_VERSION: "${{ matrix.containerd }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -158,7 +158,7 @@ jobs: matrix: go-version: ["1.20.x", "1.21.x"] steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -173,7 +173,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 30 steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -209,7 +209,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -218,7 +218,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 with: repository: containerd/containerd ref: v1.7.6 @@ -243,7 +243,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.0 - uses: actions/cache@v3 with: path: /root/.vagrant.d From 7291147c28f5f62590a2d008e30ba83df46e5338 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 22:51:33 +0000 Subject: [PATCH 0147/1066] build(deps): bump github.com/tidwall/gjson from 1.16.0 to 1.17.0 Bumps [github.com/tidwall/gjson](https://github.com/tidwall/gjson) from 1.16.0 to 1.17.0. - [Commits](https://github.com/tidwall/gjson/compare/v1.16.0...v1.17.0) --- updated-dependencies: - dependency-name: github.com/tidwall/gjson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e1d5b913cda..902889197bc 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/tidwall/gjson v1.16.0 + github.com/tidwall/gjson v1.17.0 github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 diff --git a/go.sum b/go.sum index 3a060eb859b..a9e32389048 100644 --- a/go.sum +++ b/go.sum @@ -285,8 +285,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg= -github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= +github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= From 004a05a8e12c1e79da90acaa60cf195f247df051 Mon Sep 17 00:00:00 2001 From: Henry Wang Date: Fri, 22 Sep 2023 21:41:34 +0000 Subject: [PATCH 0148/1066] Support zstd (non-chunked) conversion Signed-off-by: Henry Wang --- cmd/nerdctl/image_convert.go | 20 +++++ cmd/nerdctl/image_convert_test.go | 14 ++++ docs/command-reference.md | 2 + pkg/api/types/image_types.go | 7 ++ pkg/cmd/image/convert.go | 16 +++- pkg/imgutil/converter/zstd.go | 122 ++++++++++++++++++++++++++++++ 6 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 pkg/imgutil/converter/zstd.go diff --git a/cmd/nerdctl/image_convert.go b/cmd/nerdctl/image_convert.go index b65565fae26..e2ed0fe3e74 100644 --- a/cmd/nerdctl/image_convert.go +++ b/cmd/nerdctl/image_convert.go @@ -60,6 +60,11 @@ func newImageConvertCommand() *cobra.Command { imageConvertCommand.Flags().Bool("estargz-keep-diff-id", false, "Convert to esgz without changing diffID (cannot be used in conjunction with '--estargz-record-in'. must be specified with '--estargz-external-toc')") // #endregion + // #region zstd flags + imageConvertCommand.Flags().Bool("zstd", false, "Convert legacy tar(.gz) layers to zstd. Should be used in conjunction with '--oci'") + imageConvertCommand.Flags().Int("zstd-compression-level", 3, "zstd compression level") + // #endregion + // #region zstd:chunked flags imageConvertCommand.Flags().Bool("zstdchunked", false, "Convert legacy tar(.gz) layers to zstd:chunked for lazy pulling. Should be used in conjunction with '--oci'") imageConvertCommand.Flags().String("zstdchunked-record-in", "", "Read 'ctr-remote optimize --record-out=' record file (EXPERIMENTAL)") @@ -137,6 +142,17 @@ func processImageConvertOptions(cmd *cobra.Command) (types.ImageConvertOptions, } // #endregion + // #region zstd flags + zstd, err := cmd.Flags().GetBool("zstd") + if err != nil { + return types.ImageConvertOptions{}, err + } + zstdCompressionLevel, err := cmd.Flags().GetInt("zstd-compression-level") + if err != nil { + return types.ImageConvertOptions{}, err + } + // #endregion + // #region zstd:chunked flags zstdchunked, err := cmd.Flags().GetBool("zstdchunked") if err != nil { @@ -227,6 +243,10 @@ func processImageConvertOptions(cmd *cobra.Command) (types.ImageConvertOptions, EstargzExternalToc: estargzExternalTOC, EstargzKeepDiffID: estargzKeepDiffID, // #endregion + // #region zstd flags + Zstd: zstd, + ZstdCompressionLevel: zstdCompressionLevel, + // #endregion // #region zstd:chunked flags ZstdChunked: zstdchunked, ZstdChunkedCompressionLevel: zstdChunkedCompressionLevel, diff --git a/cmd/nerdctl/image_convert_test.go b/cmd/nerdctl/image_convert_test.go index 4853c1070ce..bcca02a2b2c 100644 --- a/cmd/nerdctl/image_convert_test.go +++ b/cmd/nerdctl/image_convert_test.go @@ -38,6 +38,20 @@ func TestImageConvertEStargz(t *testing.T) { testutil.CommonImage, convertedImage).AssertOK() } +func TestImageConvertZstd(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("no windows support yet") + } + testutil.DockerIncompatible(t) + base := testutil.NewBase(t) + convertedImage := testutil.Identifier(t) + ":zstd" + base.Cmd("rmi", convertedImage).Run() + defer base.Cmd("rmi", convertedImage).Run() + base.Cmd("pull", testutil.CommonImage).AssertOK() + base.Cmd("image", "convert", "--zstd", "--oci", "--zstd-compression-level", "3", + testutil.CommonImage, convertedImage).AssertOK() +} + func TestImageConvertZstdChunked(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("no windows support yet") diff --git a/docs/command-reference.md b/docs/command-reference.md index e9a9a0675d4..610bde2e8de 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -878,6 +878,8 @@ Flags: - `--estargz-min-chunk-size=` : The minimal number of bytes of data must be written in one gzip stream (requires stargz-snapshotter >= v0.13.0). Useful for creating a smaller eStargz image (refer to [`./stargz.md`](./stargz.md) for details). - `--estargz-external-toc` : Separate TOC JSON into another image (called \"TOC image\"). The name of TOC image is the original + \"-esgztoc\" suffix. Both eStargz and the TOC image should be pushed to the same registry. (requires stargz-snapshotter >= v0.13.0) Useful for creating a smaller eStargz image (refer to [`./stargz.md`](./stargz.md) for details). :warning: This flag is experimental and subject to change. - `--estargz-keep-diff-id`: Convert to esgz without changing diffID (cannot be used in conjunction with '--estargz-record-in'. must be specified with '--estargz-external-toc') +- `--zstd` : Use zstd compression instead of gzip. Should be used in conjunction with '--oci' +- `--zstd-compression-level=` : zstd compression level (default: 3) - `--zstdchunked` : Use zstd compression instead of gzip (a.k.a zstd:chunked). Should be used in conjunction with '--oci' - `--zstdchunked-record-in=` : read `ctr-remote optimize --record-out=` record file. :warning: This flag is experimental and subject to change. - `--zstdchunked-compression-level=`: zstd:chunked compression level (default: 3) diff --git a/pkg/api/types/image_types.go b/pkg/api/types/image_types.go index d18a3c6692e..ea59098e6e8 100644 --- a/pkg/api/types/image_types.go +++ b/pkg/api/types/image_types.go @@ -80,6 +80,13 @@ type ImageConvertOptions struct { EstargzKeepDiffID bool // #endregion + // #region zstd flags + // Zstd convert legacy tar(.gz) layers to zstd. Should be used in conjunction with '--oci' + Zstd bool + // ZstdCompressionLevel zstd compression level + ZstdCompressionLevel int + // #endregion + // #region zstd:chunked flags // ZstdChunked convert legacy tar(.gz) layers to zstd:chunked for lazy pulling. Should be used in conjunction with '--oci' ZstdChunked bool diff --git a/pkg/cmd/image/convert.go b/pkg/cmd/image/convert.go index 75d8d98a958..995bb102e52 100644 --- a/pkg/cmd/image/convert.go +++ b/pkg/cmd/image/convert.go @@ -74,15 +74,19 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa convertOpts = append(convertOpts, converter.WithPlatform(platMC)) estargz := options.Estargz + zstd := options.Zstd zstdchunked := options.ZstdChunked overlaybd := options.Overlaybd nydus := options.Nydus var finalize func(ctx context.Context, cs content.Store, ref string, desc *ocispec.Descriptor) (*images.Image, error) - if estargz || zstdchunked || overlaybd || nydus { + if estargz || zstd || zstdchunked || overlaybd || nydus { convertCount := 0 if estargz { convertCount++ } + if zstd { + convertCount++ + } if zstdchunked { convertCount++ } @@ -106,6 +110,12 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa return err } convertType = "estargz" + case zstd: + convertFunc, err = getZstdConverter(options) + if err != nil { + return err + } + convertType = "zstd" case zstdchunked: convertFunc, err = getZstdchunkedConverter(options) if err != nil { @@ -256,6 +266,10 @@ func getESGZConvertOpts(options types.ImageConvertOptions) ([]estargz.Option, er return esgzOpts, nil } +func getZstdConverter(options types.ImageConvertOptions) (converter.ConvertFunc, error) { + return converterutil.ZstdLayerConvertFunc(options) +} + func getZstdchunkedConverter(options types.ImageConvertOptions) (converter.ConvertFunc, error) { esgzOpts := []estargz.Option{ diff --git a/pkg/imgutil/converter/zstd.go b/pkg/imgutil/converter/zstd.go new file mode 100644 index 00000000000..dc68b16bae9 --- /dev/null +++ b/pkg/imgutil/converter/zstd.go @@ -0,0 +1,122 @@ +/* + 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 converter + +import ( + "context" + "fmt" + "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/nerdctl/pkg/api/types" + "github.com/klauspost/compress/zstd" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/sirupsen/logrus" +) + +// ZstdLayerConvertFunc converts legacy tar.gz layers into zstd layers with +// the specified compression level. +func ZstdLayerConvertFunc(options types.ImageConvertOptions) (converter.ConvertFunc, error) { + return func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) { + if !images.IsLayerType(desc.MediaType) { + // No conversion. No need to return an error here. + return nil, nil + } + uncompressedDesc := &desc + if !uncompress.IsUncompressedType(desc.MediaType) { + var err error + uncompressedDesc, err = uncompress.LayerConvertFunc(ctx, cs, desc) + if err != nil { + return nil, err + } + if uncompressedDesc == nil { + return nil, fmt.Errorf("unexpectedly got the same blob after compression (%s, %q)", desc.Digest, desc.MediaType) + } + defer func() { + if err := cs.Delete(ctx, uncompressedDesc.Digest); err != nil { + logrus.WithError(err).WithField("uncompressedDesc", uncompressedDesc).Warn("failed to remove tmp uncompressed layer") + } + }() + logrus.Debugf("zstd: uncompressed %s into %s", desc.Digest, uncompressedDesc.Digest) + } + + info, err := cs.Info(ctx, desc.Digest) + if err != nil { + return nil, err + } + readerAt, err := cs.ReaderAt(ctx, *uncompressedDesc) + if err != nil { + return nil, err + } + defer readerAt.Close() + sr := io.NewSectionReader(readerAt, 0, uncompressedDesc.Size) + ref := fmt.Sprintf("convert-zstd-from-%s", desc.Digest) + w, err := content.OpenWriter(ctx, cs, content.WithRef(ref)) + if err != nil { + return nil, err + } + defer w.Close() + + // Reset the writing position + // Old writer possibly remains without aborted + // (e.g. conversion interrupted by a signal) + if err := w.Truncate(0); err != nil { + return nil, err + } + + pr, pw := io.Pipe() + enc, err := zstd.NewWriter(pw, zstd.WithEncoderLevel(zstd.EncoderLevelFromZstd(options.ZstdCompressionLevel))) + if err != nil { + return nil, err + } + go func() { + if _, err := io.Copy(enc, sr); err != nil { + pr.CloseWithError(err) + return + } + if err = enc.Close(); err != nil { + pr.CloseWithError(err) + return + } + if err = pw.Close(); err != nil { + pr.CloseWithError(err) + return + } + }() + + n, err := io.Copy(w, pr) + if err != nil { + return nil, err + } + + if err = w.Commit(ctx, 0, "", content.WithLabels(info.Labels)); err != nil && !errdefs.IsAlreadyExists(err) { + return nil, err + } + if err := w.Close(); err != nil { + return nil, err + } + newDesc := desc + newDesc.Digest = w.Digest() + newDesc.Size = n + newDesc.MediaType = ocispec.MediaTypeImageLayerZstd + return &newDesc, nil + }, nil +} From 8ce38135380bd85cf307c346eee76e7e96412748 Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Mon, 25 Sep 2023 09:42:57 +0800 Subject: [PATCH 0149/1066] fix: client close connection Signed-off-by: guoguangwu fix: NewNetworkingOptionsManager is modified to take a client Signed-off-by: guoguangwu --- cmd/nerdctl/container_create.go | 2 +- cmd/nerdctl/container_run.go | 4 +-- pkg/cmd/container/prune.go | 2 +- pkg/cmd/container/remove.go | 6 ++-- .../container_network_manager.go | 28 +++++++++---------- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/cmd/nerdctl/container_create.go b/cmd/nerdctl/container_create.go index 788429086fd..60b7de34d3a 100644 --- a/cmd/nerdctl/container_create.go +++ b/cmd/nerdctl/container_create.go @@ -427,7 +427,7 @@ func createAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to load networking flags: %s", err) } - netManager, err := containerutil.NewNetworkingOptionsManager(createOpt.GOptions, netFlags) + netManager, err := containerutil.NewNetworkingOptionsManager(createOpt.GOptions, netFlags, client) if err != nil { return err } diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 1784161ed98..61df9c573b0 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -321,7 +321,7 @@ func runAction(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to load networking flags: %s", err) } - netManager, err := containerutil.NewNetworkingOptionsManager(createOpt.GOptions, netFlags) + netManager, err := containerutil.NewNetworkingOptionsManager(createOpt.GOptions, netFlags, client) if err != nil { return err } @@ -351,7 +351,7 @@ func runAction(cmd *cobra.Command, args []string) error { logrus.Warnf("failed to clean up container networking: %s", err) } } - if err := container.RemoveContainer(ctx, c, createOpt.GOptions, true, true); err != nil { + if err := container.RemoveContainer(ctx, c, createOpt.GOptions, true, true, client); err != nil { logrus.WithError(err).Warnf("failed to remove container %s", id) } }() diff --git a/pkg/cmd/container/prune.go b/pkg/cmd/container/prune.go index b53f9039dea..af827e51a76 100644 --- a/pkg/cmd/container/prune.go +++ b/pkg/cmd/container/prune.go @@ -36,7 +36,7 @@ func Prune(ctx context.Context, client *containerd.Client, options types.Contain var deleted []string for _, c := range containers { - if err = RemoveContainer(ctx, c, options.GOptions, false, true); err == nil { + if err = RemoveContainer(ctx, c, options.GOptions, false, true, client); err == nil { deleted = append(deleted, c.ID()) continue } diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 81a7d851ccb..bf8dc691060 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -69,7 +69,7 @@ func Remove(ctx context.Context, client *containerd.Client, containers []string, if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - if err := RemoveContainer(ctx, found.Container, options.GOptions, options.Force, options.Volumes); err != nil { + if err := RemoveContainer(ctx, found.Container, options.GOptions, options.Force, options.Volumes, client); err != nil { if errors.As(err, &ErrContainerStatus{}) { err = fmt.Errorf("%s. unpause/stop container first or force removal", err) } @@ -89,7 +89,7 @@ func Remove(ctx context.Context, client *containerd.Client, containers []string, } // RemoveContainer removes a container from containerd store. -func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions types.GlobalCommandOptions, force bool, removeAnonVolumes bool) (retErr error) { +func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions types.GlobalCommandOptions, force bool, removeAnonVolumes bool, client *containerd.Client) (retErr error) { // defer the storage of remove error in the dedicated label defer func() { if retErr != nil { @@ -186,7 +186,7 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions return fmt.Errorf("failed to load container networking options from specs: %s", err) } - networkManager, err := containerutil.NewNetworkingOptionsManager(globalOptions, netOpts) + networkManager, err := containerutil.NewNetworkingOptionsManager(globalOptions, netOpts, client) if err != nil { return fmt.Errorf("failed to instantiate network options manager: %s", err) } diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index e8db23cd545..01eba80ed22 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -113,7 +113,7 @@ type NetworkOptionsManager interface { } // NewNetworkingOptionsManager Returns a types.NetworkOptionsManager based on the provided command's flags. -func NewNetworkingOptionsManager(globalOptions types.GlobalCommandOptions, netOpts types.NetworkOptions) (NetworkOptionsManager, error) { +func NewNetworkingOptionsManager(globalOptions types.GlobalCommandOptions, netOpts types.NetworkOptions, client *containerd.Client) (NetworkOptionsManager, error) { netType, err := nettype.Detect(netOpts.NetworkSlice) if err != nil { return nil, err @@ -122,13 +122,13 @@ func NewNetworkingOptionsManager(globalOptions types.GlobalCommandOptions, netOp var manager NetworkOptionsManager switch netType { case nettype.None: - manager = &noneNetworkManager{globalOptions, netOpts} + manager = &noneNetworkManager{globalOptions, netOpts, client} case nettype.Host: - manager = &hostNetworkManager{globalOptions, netOpts} + manager = &hostNetworkManager{globalOptions, netOpts, client} case nettype.Container: - manager = &containerNetworkManager{globalOptions, netOpts} + manager = &containerNetworkManager{globalOptions, netOpts, client} case nettype.CNI: - manager = &cniNetworkManager{globalOptions, netOpts, nil} + manager = &cniNetworkManager{globalOptions, netOpts, nil, client} default: return nil, fmt.Errorf("unexpected container networking type: %q", netType) } @@ -140,6 +140,7 @@ func NewNetworkingOptionsManager(globalOptions types.GlobalCommandOptions, netOp type noneNetworkManager struct { globalOptions types.GlobalCommandOptions netOpts types.NetworkOptions + client *containerd.Client } // NetworkOptions Returns a copy of the internal types.NetworkOptions. @@ -180,6 +181,7 @@ func (m *noneNetworkManager) ContainerNetworkingOpts(_ context.Context, _ string type containerNetworkManager struct { globalOptions types.GlobalCommandOptions netOpts types.NetworkOptions + client *containerd.Client } // NetworkOptions Returns a copy of the internal types.NetworkOptions. @@ -249,19 +251,13 @@ func (m *containerNetworkManager) CleanupNetworking(_ context.Context, _ contain } // Searches for and returns the networking container for the given network argument. -func (m *containerNetworkManager) getNetworkingContainerForArgument(ctx context.Context, containerNetArg string) (containerd.Container, error) { +func (m *containerNetworkManager) getNetworkingContainerForArgument(ctx context.Context, containerNetArg string, client *containerd.Client) (containerd.Container, error) { netItems := strings.Split(containerNetArg, ":") if len(netItems) < 2 { return nil, fmt.Errorf("container networking argument format must be 'container:', got: %q", containerNetArg) } containerName := netItems[1] - client, ctxt, cancel, err := clientutil.NewClient(ctx, m.globalOptions.Namespace, m.globalOptions.Address) - if err != nil { - return nil, err - } - defer cancel() - var foundContainer containerd.Container walker := &containerwalker.ContainerWalker{ Client: client, @@ -273,7 +269,7 @@ func (m *containerNetworkManager) getNetworkingContainerForArgument(ctx context. return nil }, } - n, err := walker.Walk(ctxt, containerName) + n, err := walker.Walk(ctx, containerName) if err != nil { return nil, err } @@ -291,7 +287,7 @@ func (m *containerNetworkManager) InternalNetworkingOptionLabels(ctx context.Con return opts, fmt.Errorf("conflicting options: exactly one network specification is allowed when using '--network=container:'") } - container, err := m.getNetworkingContainerForArgument(ctx, m.netOpts.NetworkSlice[0]) + container, err := m.getNetworkingContainerForArgument(ctx, m.netOpts.NetworkSlice[0], m.client) if err != nil { return opts, err } @@ -306,7 +302,7 @@ func (m *containerNetworkManager) ContainerNetworkingOpts(ctx context.Context, _ opts := []oci.SpecOpts{} cOpts := []containerd.NewContainerOpts{} - container, err := m.getNetworkingContainerForArgument(ctx, m.netOpts.NetworkSlice[0]) + container, err := m.getNetworkingContainerForArgument(ctx, m.netOpts.NetworkSlice[0], m.client) if err != nil { return nil, nil, err } @@ -346,6 +342,7 @@ func (m *containerNetworkManager) ContainerNetworkingOpts(ctx context.Context, _ type hostNetworkManager struct { globalOptions types.GlobalCommandOptions netOpts types.NetworkOptions + client *containerd.Client } // NetworkOptions Returns a copy of the internal types.NetworkOptions. @@ -430,6 +427,7 @@ type cniNetworkManager struct { globalOptions types.GlobalCommandOptions netOpts types.NetworkOptions netNs *netns.NetNS + client *containerd.Client } // NetworkOptions Returns a copy of the internal types.NetworkOptions. From 72665a07c7bad8945b3fdb60ab3b3bb987d4425e Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Mon, 25 Sep 2023 17:04:46 +0000 Subject: [PATCH 0150/1066] update toml to v2 Signed-off-by: Kay Yan --- cmd/nerdctl/main.go | 4 ++-- go.mod | 3 ++- go.sum | 3 +++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index ccb1ba6de2e..3efcba76046 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -32,7 +32,7 @@ import ( "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/version" "github.com/fatih/color" - "github.com/pelletier/go-toml" + "github.com/pelletier/go-toml/v2" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -141,7 +141,7 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, if r, err := os.Open(tomlPath); err == nil { logrus.Debugf("Loading config from %q", tomlPath) defer r.Close() - dec := toml.NewDecoder(r).Strict(true) // set Strict to detect typo + dec := toml.NewDecoder(r).DisallowUnknownFields() // set Strict to detect typo if err := dec.Decode(cfg); err != nil { return nil, fmt.Errorf("failed to load nerdctl config (not daemon config) from %q (Hint: don't mix up daemon's `config.toml` with `nerdctl.toml`): %w", tomlPath, err) } diff --git a/go.mod b/go.mod index 902889197bc..52dffe90877 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc5 github.com/opencontainers/runtime-spec v1.1.0 - github.com/pelletier/go-toml v1.9.5 + github.com/pelletier/go-toml/v2 v2.1.0 github.com/rootless-containers/bypass4netns v0.3.0 github.com/rootless-containers/rootlesskit v1.1.1 github.com/sirupsen/logrus v1.9.3 @@ -108,6 +108,7 @@ require ( github.com/multiformats/go-varint v0.0.6 // indirect github.com/opencontainers/runc v1.1.7 // indirect github.com/opencontainers/selinux v1.11.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect github.com/philhofer/fwd v1.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect diff --git a/go.sum b/go.sum index a9e32389048..9b6a08c18f8 100644 --- a/go.sum +++ b/go.sum @@ -243,6 +243,8 @@ github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaL github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -285,6 +287,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= From 88188be6345ec7dbc806bbb3979d3838c224ec2e Mon Sep 17 00:00:00 2001 From: Gavin Inglis Date: Tue, 26 Sep 2023 11:42:54 -0700 Subject: [PATCH 0151/1066] docs: minor fixes to soci documentation Signed-off-by: Gavin Inglis --- docs/soci.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/soci.md b/docs/soci.md index b6c70a86d11..8ba5035bee8 100644 --- a/docs/soci.md +++ b/docs/soci.md @@ -6,7 +6,7 @@ See https://github.com/awslabs/soci-snapshotter to learn further information. ## Prerequisites -- Install containerd remote snapshotter plugin (`soci`) from https://github.com/awslabs/soci-snapshotter/blob/main/docs/getting-started.md +- Install containerd remote snapshotter plugin (`soci-snapshotter-grpc`) from https://github.com/awslabs/soci-snapshotter/blob/main/docs/getting-started.md - Add the following to `/etc/containerd/config.toml`: ```toml @@ -16,7 +16,7 @@ See https://github.com/awslabs/soci-snapshotter to learn further information. address = "/run/soci-snapshotter-grpc/soci-snapshotter-grpc.sock" ``` -- Launch `containerd` and `soci-snapshotter` +- Launch `containerd` and `soci-snapshotter-grpc` ## Enable SOCI for `nerdctl run` and `nerdctl pull` @@ -25,7 +25,7 @@ See https://github.com/awslabs/soci-snapshotter to learn further information. - Run `nerdctl` with `--snapshotter=soci` ```console -nerdctl run --it --rm --snapshotter=soci public.ecr.aws/soci-workshop-examples/ffmpeg:latest +nerdctl run -it --rm --snapshotter=soci public.ecr.aws/soci-workshop-examples/ffmpeg:latest ``` - You can also only pull the image with SOCI without running the container. @@ -40,7 +40,7 @@ For images that already have SOCI indices, see https://gallery.ecr.aws/soci-work | :zap: Requirement | nerdctl >= 1.6.0 | | ----------------- |------------------| -- Push the image with SOCI index. Adding `--snapshotter=soci` command to `nerdctl pull`, `nerdctl` will create the SOCI index and push the index to same destination as the image. +- Push the image with SOCI index. Adding `--snapshotter=soci` arg to `nerdctl pull`, `nerdctl` will create the SOCI index and push the index to same destination as the image. ```console nerdctl push --snapshotter=soci push --soci-span-size=2097152 --soci-min-layer-size=20971520 public.ecr.aws/my-registry/my-repo:latest ``` From e230c3cf31ec0ead206eaad115afc8fbfe633ae5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 22:59:12 +0000 Subject: [PATCH 0152/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.12.0 to 0.13.0. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.12.0...v0.13.0) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 52dffe90877..b517b655473 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/containerd/continuity v0.4.2 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 - github.com/containerd/nydus-snapshotter v0.12.0 + github.com/containerd/nydus-snapshotter v0.13.0 github.com/containerd/stargz-snapshotter v0.14.3 github.com/containerd/stargz-snapshotter/estargz v0.14.3 github.com/containerd/stargz-snapshotter/ipfs v0.14.3 diff --git a/go.sum b/go.sum index 9b6a08c18f8..11fa118155d 100644 --- a/go.sum +++ b/go.sum @@ -46,8 +46,8 @@ github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9 github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= github.com/containerd/imgcrypt v1.1.8 h1:ZS7TuywcRNLoHpU0g+v4/PsKynl6TYlw5xDVWWoIyFA= github.com/containerd/imgcrypt v1.1.8/go.mod h1:x6QvFIkMyO2qGIY2zXc88ivEzcbgvLdWjoZyGqDap5U= -github.com/containerd/nydus-snapshotter v0.12.0 h1:cpMu3eq+jQjEFKrm+1T5rI74nCthKF7WMxS37DxSYoM= -github.com/containerd/nydus-snapshotter v0.12.0/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= +github.com/containerd/nydus-snapshotter v0.13.0 h1:hUqn0hbIivaG75clrNTpA904Ybp5tVtDLy/8j93zX/4= +github.com/containerd/nydus-snapshotter v0.13.0/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= github.com/containerd/stargz-snapshotter v0.14.3/go.mod h1:j2Ya4JeA5gMZJr8BchSkPjlcCEh++auAxp4nidPI6N0= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= From 6b5c43e2b09e2fc201209c3a0ce72ef5d14304b6 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 29 Sep 2023 04:23:24 +0900 Subject: [PATCH 0153/1066] CNI: prioritize `/opt/cni/bin` over `/usr/lib/cni` When the both of `/opt/cni/bin` and `/usr/lib/cni` are present, the latter one is likely to be a distro package and likely to be older than `/opt/cni/bin`. Signed-off-by: Akihiro Suda --- pkg/defaults/defaults_linux.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/defaults/defaults_linux.go b/pkg/defaults/defaults_linux.go index c931c13893f..44541803d8e 100644 --- a/pkg/defaults/defaults_linux.go +++ b/pkg/defaults/defaults_linux.go @@ -47,6 +47,7 @@ func DataRoot() string { func CNIPath() string { candidates := []string{ + gocni.DefaultCNIDir, // /opt/cni/bin "/usr/local/libexec/cni", "/usr/local/lib/cni", "/usr/libexec/cni", // Fedora @@ -59,9 +60,9 @@ func CNIPath() string { } candidates = append([]string{ // NOTE: These user paths are not defined in XDG + filepath.Join(home, "opt/cni/bin"), filepath.Join(home, ".local/libexec/cni"), filepath.Join(home, ".local/lib/cni"), - filepath.Join(home, "opt/cni/bin"), }, candidates...) } From c1fd6782c222b4ed35e7ca23db8a19ec83e45d4b Mon Sep 17 00:00:00 2001 From: Eric Chan Date: Thu, 28 Sep 2023 09:42:26 +0800 Subject: [PATCH 0154/1066] Fix port allocate iptables regex Fix issues: Conflicts arise when multiple containers use -p :xxx to automatically assign ports #2537 Signed-off-by: Eric Chan Co-Authored-By: Akihiro Suda --- pkg/portutil/iptable/iptables.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pkg/portutil/iptable/iptables.go b/pkg/portutil/iptable/iptables.go index 1d90ccb7f24..2c5daf01cef 100644 --- a/pkg/portutil/iptable/iptables.go +++ b/pkg/portutil/iptable/iptables.go @@ -19,6 +19,7 @@ package iptable import ( "regexp" "strconv" + "strings" ) // ParseIPTableRules takes a slice of iptables rules as input and returns a slice of @@ -27,16 +28,18 @@ func ParseIPTableRules(rules []string) []uint64 { ports := []uint64{} // Regex to match the '--dports' option followed by the port number - dportRegex := regexp.MustCompile(`--dports (\d+)`) + dportRegex := regexp.MustCompile(`--dports ((,?\d+)+)`) for _, rule := range rules { matches := dportRegex.FindStringSubmatch(rule) if len(matches) > 1 { - port64, err := strconv.ParseUint(matches[1], 10, 16) - if err != nil { - continue + for _, _match := range strings.Split(matches[1], ",") { + port64, err := strconv.ParseUint(_match, 10, 16) + if err != nil { + continue + } + ports = append(ports, port64) } - ports = append(ports, port64) } } From 34f73335d43be333cb5eaffaae1b71ac81f646fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 22:25:02 +0000 Subject: [PATCH 0155/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.0 to 0.13.1. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.0...v0.13.1) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b517b655473..d9c95fdcb3c 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/containerd/continuity v0.4.2 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 - github.com/containerd/nydus-snapshotter v0.13.0 + github.com/containerd/nydus-snapshotter v0.13.1 github.com/containerd/stargz-snapshotter v0.14.3 github.com/containerd/stargz-snapshotter/estargz v0.14.3 github.com/containerd/stargz-snapshotter/ipfs v0.14.3 diff --git a/go.sum b/go.sum index 11fa118155d..93931f9b31f 100644 --- a/go.sum +++ b/go.sum @@ -46,8 +46,8 @@ github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9 github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= github.com/containerd/imgcrypt v1.1.8 h1:ZS7TuywcRNLoHpU0g+v4/PsKynl6TYlw5xDVWWoIyFA= github.com/containerd/imgcrypt v1.1.8/go.mod h1:x6QvFIkMyO2qGIY2zXc88ivEzcbgvLdWjoZyGqDap5U= -github.com/containerd/nydus-snapshotter v0.13.0 h1:hUqn0hbIivaG75clrNTpA904Ybp5tVtDLy/8j93zX/4= -github.com/containerd/nydus-snapshotter v0.13.0/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= +github.com/containerd/nydus-snapshotter v0.13.1 h1:5XNkCZ9ivLXCcyx3Jbbfh/fntkcls69uBg0x9VE8zlk= +github.com/containerd/nydus-snapshotter v0.13.1/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= github.com/containerd/stargz-snapshotter v0.14.3/go.mod h1:j2Ya4JeA5gMZJr8BchSkPjlcCEh++auAxp4nidPI6N0= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= From fdf4b2c0c972eecc8d7087e9c04d663fdbe83753 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Oct 2023 22:35:57 +0000 Subject: [PATCH 0156/1066] build(deps): bump golang.org/x/sys from 0.12.0 to 0.13.0 Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.12.0 to 0.13.0. - [Commits](https://github.com/golang/sys/compare/v0.12.0...v0.13.0) --- updated-dependencies: - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b517b655473..b116d63453b 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( golang.org/x/crypto v0.13.0 golang.org/x/net v0.15.0 golang.org/x/sync v0.3.0 - golang.org/x/sys v0.12.0 + golang.org/x/sys v0.13.0 golang.org/x/term v0.12.0 golang.org/x/text v0.13.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 11fa118155d..6ef4fc4885a 100644 --- a/go.sum +++ b/go.sum @@ -391,8 +391,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= From 980019a23b6c8cce024dbfe3e4eb699bec3cacae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Oct 2023 15:59:34 +0000 Subject: [PATCH 0157/1066] build(deps): bump golang.org/x/term from 0.12.0 to 0.13.0 Bumps [golang.org/x/term](https://github.com/golang/term) from 0.12.0 to 0.13.0. - [Commits](https://github.com/golang/term/compare/v0.12.0...v0.13.0) --- updated-dependencies: - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b116d63453b..b474c6206b6 100644 --- a/go.mod +++ b/go.mod @@ -55,7 +55,7 @@ require ( golang.org/x/net v0.15.0 golang.org/x/sync v0.3.0 golang.org/x/sys v0.13.0 - golang.org/x/term v0.12.0 + golang.org/x/term v0.13.0 golang.org/x/text v0.13.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 diff --git a/go.sum b/go.sum index 6ef4fc4885a..9e1cb1005f4 100644 --- a/go.sum +++ b/go.sum @@ -394,8 +394,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 11a43ac468ff0aad2630e8689ff1d0919d40871f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Oct 2023 16:02:49 +0000 Subject: [PATCH 0158/1066] build(deps): bump golang.org/x/sync from 0.3.0 to 0.4.0 Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.3.0 to 0.4.0. - [Commits](https://github.com/golang/sync/compare/v0.3.0...v0.4.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b116d63453b..ba8f60b98b3 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/yuchanns/srslog v1.1.0 golang.org/x/crypto v0.13.0 golang.org/x/net v0.15.0 - golang.org/x/sync v0.3.0 + golang.org/x/sync v0.4.0 golang.org/x/sys v0.13.0 golang.org/x/term v0.12.0 golang.org/x/text v0.13.0 diff --git a/go.sum b/go.sum index 6ef4fc4885a..effcfc381a5 100644 --- a/go.sum +++ b/go.sum @@ -363,8 +363,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 6664661cc546851c62437c6427c67ed439358074 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 Oct 2023 14:25:51 +0000 Subject: [PATCH 0159/1066] build(deps): bump golang.org/x/crypto from 0.13.0 to 0.14.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.13.0 to 0.14.0. - [Commits](https://github.com/golang/crypto/compare/v0.13.0...v0.14.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bd3bf6c6b93..450572f425f 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 - golang.org/x/crypto v0.13.0 + golang.org/x/crypto v0.14.0 golang.org/x/net v0.15.0 golang.org/x/sync v0.4.0 golang.org/x/sys v0.13.0 diff --git a/go.sum b/go.sum index b2364b83048..feb94e50dff 100644 --- a/go.sum +++ b/go.sum @@ -330,8 +330,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= From 3006f23e8848519ea45766adb541c5377a8e62c2 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 9 Oct 2023 07:48:00 +0900 Subject: [PATCH 0160/1066] release.yml: migrate from `hub` to `gh` Signed-off-by: Akihiro Suda --- .github/workflows/release.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 576f90e6e1b..2129a87e2fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,11 +26,8 @@ jobs: run: (cd _output; sha256sum SHA256SUMS) - name: "Prepare the release note" run: | - tag="${GITHUB_REF##*/}" shasha=$(sha256sum _output/SHA256SUMS | awk '{print $1}') cat <<-EOF | tee /tmp/release-note.txt - ${tag} - $(hack/generate-release-note.sh) - - - The binaries were built automatically on GitHub Actions. @@ -45,6 +42,4 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | tag="${GITHUB_REF##*/}" - asset_flags=() - for f in _output/*; do asset_flags+=("-a" "$f"); done - hub release create "${asset_flags[@]}" -F /tmp/release-note.txt --draft "${tag}" + gh release create -F /tmp/release-note.txt --draft --title "${tag}" "${tag}" _output/* From d5dd50ce08d766cb132646c8f7e432678da59ddc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 Oct 2023 22:56:52 +0000 Subject: [PATCH 0161/1066] build(deps): bump golang.org/x/net from 0.15.0 to 0.16.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.15.0 to 0.16.0. - [Commits](https://github.com/golang/net/compare/v0.15.0...v0.16.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 450572f425f..dc77c5518f6 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 golang.org/x/crypto v0.14.0 - golang.org/x/net v0.15.0 + golang.org/x/net v0.16.0 golang.org/x/sync v0.4.0 golang.org/x/sys v0.13.0 golang.org/x/term v0.13.0 diff --git a/go.sum b/go.sum index feb94e50dff..5adf4f701d1 100644 --- a/go.sum +++ b/go.sum @@ -354,8 +354,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 93cb48023c2a1db00859e1b0473eb4a3c7f71f43 Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Mon, 9 Oct 2023 11:12:17 +0800 Subject: [PATCH 0162/1066] chore: Comment should with an optional leading article Signed-off-by: guoguangwu --- pkg/buildkitutil/buildkitutil.go | 2 +- pkg/cmd/login/login.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/buildkitutil/buildkitutil.go b/pkg/buildkitutil/buildkitutil.go index 113bac0f64b..12893233b85 100644 --- a/pkg/buildkitutil/buildkitutil.go +++ b/pkg/buildkitutil/buildkitutil.go @@ -185,7 +185,7 @@ func WriteTempDockerfile(rc io.Reader) (dockerfileDir string, err error) { return dockerfileDir, nil } -// Buildkit file returns the values for the following buildctl args +// BuildKitFile returns the values for the following buildctl args // --localfilename=dockerfile={absDir} // --opt=filename={file} func BuildKitFile(dir, inputfile string) (absDir string, file string, err error) { diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index f4f49b0df2e..5bc8ce7389f 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -113,9 +113,9 @@ func Login(ctx context.Context, options types.LoginCommandOptions, stdout io.Wri return nil } -// Code from github.com/docker/cli/cli/command (v20.10.3) -// GetDefaultAuthConfig gets the default auth config given a serverAddress -// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it +// GetDefaultAuthConfig gets the default auth config given a serverAddress. +// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it. +// Code from github.com/docker/cli/cli/command (v20.10.3). func GetDefaultAuthConfig(checkCredStore bool, serverAddress string, isDefaultRegistry bool) (*registry.AuthConfig, error) { if !isDefaultRegistry { var err error From abec5ef0d0376dd76d9d4bbe9f2d8161b814fec4 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 10 Oct 2023 06:55:07 +0900 Subject: [PATCH 0163/1066] containerd/containerd/log -> containerd/log Signed-off-by: Akihiro Suda --- cmd/nerdctl/container_update.go | 2 +- go.mod | 1 + go.sum | 2 ++ pkg/cmd/namespace/remove.go | 2 +- pkg/cmd/system/events.go | 2 +- pkg/consoleutil/consoleutil_unix.go | 2 +- pkg/consoleutil/consoleutil_windows.go | 2 +- pkg/imgutil/jobs/jobs.go | 2 +- pkg/imgutil/pull/pull.go | 2 +- pkg/imgutil/push/push.go | 2 +- pkg/logging/cri_logger.go | 2 +- 11 files changed, 12 insertions(+), 9 deletions(-) diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index 50f530e8ed4..5708aa0e310 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -25,8 +25,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" "github.com/containerd/containerd/pkg/cri/util" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" nerdctlContainer "github.com/containerd/nerdctl/pkg/cmd/container" diff --git a/go.mod b/go.mod index dc77c5518f6..560727d96d4 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/containerd/continuity v0.4.2 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 + github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.13.1 github.com/containerd/stargz-snapshotter v0.14.3 github.com/containerd/stargz-snapshotter/estargz v0.14.3 diff --git a/go.sum b/go.sum index 5adf4f701d1..cf10a6249b9 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,8 @@ github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9 github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= github.com/containerd/imgcrypt v1.1.8 h1:ZS7TuywcRNLoHpU0g+v4/PsKynl6TYlw5xDVWWoIyFA= github.com/containerd/imgcrypt v1.1.8/go.mod h1:x6QvFIkMyO2qGIY2zXc88ivEzcbgvLdWjoZyGqDap5U= +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.1 h1:5XNkCZ9ivLXCcyx3Jbbfh/fntkcls69uBg0x9VE8zlk= github.com/containerd/nydus-snapshotter v0.13.1/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= diff --git a/pkg/cmd/namespace/remove.go b/pkg/cmd/namespace/remove.go index 4c1ca7ae29e..25a8720cf84 100644 --- a/pkg/cmd/namespace/remove.go +++ b/pkg/cmd/namespace/remove.go @@ -22,7 +22,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" ) diff --git a/pkg/cmd/system/events.go b/pkg/cmd/system/events.go index 22083bfe2a6..b18955611e1 100644 --- a/pkg/cmd/system/events.go +++ b/pkg/cmd/system/events.go @@ -28,7 +28,7 @@ import ( "github.com/containerd/containerd" _ "github.com/containerd/containerd/api/events" // Register grpc event types "github.com/containerd/containerd/events" - "github.com/containerd/containerd/log" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/typeurl/v2" diff --git a/pkg/consoleutil/consoleutil_unix.go b/pkg/consoleutil/consoleutil_unix.go index 17421a6fed4..49cea373bbf 100644 --- a/pkg/consoleutil/consoleutil_unix.go +++ b/pkg/consoleutil/consoleutil_unix.go @@ -24,7 +24,7 @@ import ( "os/signal" "github.com/containerd/console" - "github.com/containerd/containerd/log" + "github.com/containerd/log" "golang.org/x/sys/unix" ) diff --git a/pkg/consoleutil/consoleutil_windows.go b/pkg/consoleutil/consoleutil_windows.go index ee823786f2a..c8ebf8ee726 100644 --- a/pkg/consoleutil/consoleutil_windows.go +++ b/pkg/consoleutil/consoleutil_windows.go @@ -21,7 +21,7 @@ import ( "time" "github.com/containerd/console" - "github.com/containerd/containerd/log" + "github.com/containerd/log" ) // HandleConsoleResize resizes the console. diff --git a/pkg/imgutil/jobs/jobs.go b/pkg/imgutil/jobs/jobs.go index 47def937a19..d03143d956e 100644 --- a/pkg/imgutil/jobs/jobs.go +++ b/pkg/imgutil/jobs/jobs.go @@ -26,9 +26,9 @@ import ( "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/log" "github.com/containerd/containerd/pkg/progress" "github.com/containerd/containerd/remotes" + "github.com/containerd/log" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/imgutil/pull/pull.go b/pkg/imgutil/pull/pull.go index 11a257684c8..bbe18bf792a 100644 --- a/pkg/imgutil/pull/pull.go +++ b/pkg/imgutil/pull/pull.go @@ -23,8 +23,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" - "github.com/containerd/containerd/log" "github.com/containerd/containerd/remotes" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/imgutil/jobs" "github.com/containerd/nerdctl/pkg/platformutil" ocispec "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/pkg/imgutil/push/push.go b/pkg/imgutil/push/push.go index 2829fbdd244..09930a3fa86 100644 --- a/pkg/imgutil/push/push.go +++ b/pkg/imgutil/push/push.go @@ -27,11 +27,11 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" - "github.com/containerd/containerd/log" "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" ocispec "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/pkg/logging/cri_logger.go b/pkg/logging/cri_logger.go index c47606b2aa0..a6381d33976 100644 --- a/pkg/logging/cri_logger.go +++ b/pkg/logging/cri_logger.go @@ -33,7 +33,7 @@ import ( "path/filepath" "time" - "github.com/containerd/containerd/log" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/logging/tail" "github.com/sirupsen/logrus" ) From ea86ea87098ad1bfbe7f0d1a2b4d3e9786f67fb2 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 10 Oct 2023 06:42:30 +0900 Subject: [PATCH 0164/1066] update containerd (1.7.7) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 22 +++++++++++----------- Dockerfile | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5c2c921b3b7..a34d94e642e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,11 +77,11 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.22 + containerd: v1.6.24 - ubuntu: 20.04 - containerd: v1.7.6 + containerd: v1.7.7 - ubuntu: 22.04 - containerd: v1.7.6 + containerd: v1.7.7 - ubuntu: 22.04 containerd: main env: @@ -113,25 +113,25 @@ jobs: # ubuntu-22.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.22 + containerd: v1.6.24 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.6 + containerd: v1.7.7 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.6 + containerd: v1.7.7 target: test-integration-rootless - ubuntu: 22.04 containerd: main target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.6.22 + containerd: v1.6.24 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.6 + containerd: v1.7.7 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.6 + containerd: v1.7.7 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main @@ -221,7 +221,7 @@ jobs: - uses: actions/checkout@v4.1.0 with: repository: containerd/containerd - ref: v1.7.6 + ref: v1.7.7 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -229,7 +229,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.6 + ctrdVersion: 1.7.7 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index 3c3ef5095b5..2691033f7bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.6 +ARG CONTAINERD_VERSION=v1.7.7 ARG RUNC_VERSION=v1.1.9 ARG CNI_PLUGINS_VERSION=v1.3.0 From 869dec831c82d1623ab10c845a1a06ec1f4c69b7 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 10 Oct 2023 06:46:16 +0900 Subject: [PATCH 0165/1066] update slirp4netns (1.2.2) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.1 | 6 ------ Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.2 | 7 +++++++ 3 files changed, 8 insertions(+), 7 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.2 diff --git a/Dockerfile b/Dockerfile index 2691033f7bf..ec12cf6aa43 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.14.3 ARG IMGCRYPT_VERSION=v1.1.8 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v1.1.1 -ARG SLIRP4NETNS_VERSION=v1.2.1 +ARG SLIRP4NETNS_VERSION=v1.2.2 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.3.0 # Extra deps: FUSE-OverlayFS diff --git a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.1 b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.1 deleted file mode 100644 index 2d6ef565aa6..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.1 +++ /dev/null @@ -1,6 +0,0 @@ -da4d301ffe36a0edf1cc769059c1f89eadd1afeba285636bcb2f250a6cffffed slirp4netns-aarch64 -0a540774fd15bdb39cb07d0b9f1e1968640c822cacf879abf0d1a3966f98d30d slirp4netns-armv7l -b8c8a1747524ae79c9df9fa21c5d436dca7e5a777de552f8b5dabb1c9a60b941 slirp4netns-ppc64le -de4c50f9ee29bef7c756d8487ed1ae5694825d853ba96908de23eea6f806431a slirp4netns-riscv64 -55fe4b10e7279ba4d780091d3a259ff080dc974811e060753599e0d2ba8520a5 slirp4netns-s390x -cb1d7b7f9bc946c6179efdb8e069d5ee673c3f135668da6bf54f2ed689981833 slirp4netns-x86_64 diff --git a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.2 b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.2 new file mode 100644 index 00000000000..651745bffc8 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.2 @@ -0,0 +1,7 @@ +d269b4788a54e6bcc0669a80704ec75e4f6be7c827846b57163b9da3d4efdefe SOURCE_DATE_EPOCH +f7d4913ff27f017e22a5aa66a233f0d403549539a6fab594cbbad258f965af1a slirp4netns-aarch64 +091cb02fae4af0c43596fecdde2eac0cb76c7c5c30963c4b87fc282cb9489571 slirp4netns-armv7l +228144e9ba9f19905ffbe95767fed10361e620f01f0867c8d1162cf60807b37e slirp4netns-ppc64le +5898887f3ababd4e4886932535d5167a87d7497cd2851e259cae566b1b6d636a slirp4netns-riscv64 +9cf1d1880b8016bd47023a32582655e2f5f96a0ff266faeb932fbf4ef6159dee slirp4netns-s390x +2b59dd438ec1814dcd00c3106c0288ca174c3fe9a178f3400baa06818edaae8d slirp4netns-x86_64 From 02a59fc5e8a81eefa0e6f82a2a0d8420dc32e3d2 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 10 Oct 2023 06:49:18 +0900 Subject: [PATCH 0166/1066] update containerd-fuse-overlayfs (1.0.7) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.6 | 6 ------ Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.7 | 6 ++++++ 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.6 create mode 100644 Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.7 diff --git a/Dockerfile b/Dockerfile index ec12cf6aa43..5c27512c03e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ ARG SLIRP4NETNS_VERSION=v1.2.2 ARG BYPASS4NETNS_VERSION=v0.3.0 # Extra deps: FUSE-OverlayFS ARG FUSE_OVERLAYFS_VERSION=v1.13 -ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.6 +ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.7 # Extra deps: IPFS ARG KUBO_VERSION=v0.22.0 # Extra deps: Init diff --git a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.6 b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.6 deleted file mode 100644 index f5731f42f9d..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.6 +++ /dev/null @@ -1,6 +0,0 @@ -2fbf5532021a558a965358e765c21b4dbe891e00ac68d18ab088d3cea4a41613 containerd-fuse-overlayfs-1.0.6-linux-amd64.tar.gz -9d983f341b7fb980bb7728851aaab41f706cbc55387940800fabcd7f01b33f24 containerd-fuse-overlayfs-1.0.6-linux-arm-v7.tar.gz -27c40aea2dc37fc59dae790c87193190a8360a310fa8df16fcbec165a46d6163 containerd-fuse-overlayfs-1.0.6-linux-arm64.tar.gz -ad92ee6c7ecbf7b1f2b78f13eccf5ca82fc5349ef93d9116bef49b6767fbc146 containerd-fuse-overlayfs-1.0.6-linux-ppc64le.tar.gz -971243ff3da618dbdcc28ef243ed08e834f7acfc164feebd7d25502938d5cae8 containerd-fuse-overlayfs-1.0.6-linux-riscv64.tar.gz -691c07478f009858cbba66300a0da689fe60daf7fbc13609759ff8ef14ac2a97 containerd-fuse-overlayfs-1.0.6-linux-s390x.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.7 b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.7 new file mode 100644 index 00000000000..82244bc54c7 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.7 @@ -0,0 +1,6 @@ +d9c1a8d511a0697e4262250d54fda79acab86cc7fba20623c5960dbd679c1581 containerd-fuse-overlayfs-1.0.7-linux-amd64.tar.gz +e365cdff6b81e2e3cd8ec27e074aa416a4379f7601c83f6d647b64cb81d8c56e containerd-fuse-overlayfs-1.0.7-linux-arm-v7.tar.gz +013ae62d06a840016437772b6f7206781040528eef04d541a1d3a8b48ec2a70b containerd-fuse-overlayfs-1.0.7-linux-arm64.tar.gz +ef4e93f892dd63f5fff8c5602fd188b38717242ae3a0d9944f4facbfb974d65b containerd-fuse-overlayfs-1.0.7-linux-ppc64le.tar.gz +cd56a229dda55764c237483198e0373d87d8d4d8381167b57265408057d64269 containerd-fuse-overlayfs-1.0.7-linux-riscv64.tar.gz +300d16911403a094ccc610730c34eaa313b0f0df1150015c76a4ea0e85fc9ed3 containerd-fuse-overlayfs-1.0.7-linux-s390x.tar.gz From 98d5724e2a1d8fe0db8b6b71932252fd8f06a318 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 10 Oct 2023 06:51:46 +0900 Subject: [PATCH 0167/1066] update Kubo (0.23.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/kubo-v0.22.0 | 3 --- Dockerfile.d/SHA256SUMS.d/kubo-v0.23.0 | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/kubo-v0.22.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/kubo-v0.23.0 diff --git a/Dockerfile b/Dockerfile index 5c27512c03e..9b369858df4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ ARG BYPASS4NETNS_VERSION=v0.3.0 ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.7 # Extra deps: IPFS -ARG KUBO_VERSION=v0.22.0 +ARG KUBO_VERSION=v0.23.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug diff --git a/Dockerfile.d/SHA256SUMS.d/kubo-v0.22.0 b/Dockerfile.d/SHA256SUMS.d/kubo-v0.22.0 deleted file mode 100644 index 449d89bb7ff..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/kubo-v0.22.0 +++ /dev/null @@ -1,3 +0,0 @@ -# From https://github.com/ipfs/kubo/releases -d708b484d93e95832105968cfe5b2dff592706d18dbfe41d87df8fcb20512baf kubo_v0.22.0_linux-amd64.tar.gz -505fd3dff8419b81e9e755297a2c614169d86d25b7bd8e3b0af49d1fd771b0c3 kubo_v0.22.0_linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/kubo-v0.23.0 b/Dockerfile.d/SHA256SUMS.d/kubo-v0.23.0 new file mode 100644 index 00000000000..f43a829064d --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/kubo-v0.23.0 @@ -0,0 +1,3 @@ +# From https://github.com/ipfs/kubo/releases +b78d209ce9b5797534348c6939d305b8758b0e4bc3abae532b63d15d9cddb9c6 kubo_v0.23.0_linux-amd64.tar.gz +0de1bf8564f563b77e7bef620f357c0787b2fad37378c8cdb789a55959e5b543 kubo_v0.23.0_linux-arm64.tar.gz From e590756c02e0d1dfb42aeab16e749dd6092d6190 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 10 Oct 2023 06:52:04 +0900 Subject: [PATCH 0168/1066] update gotestsum (1.10.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9b369858df4..6763145415b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ ARG BUILDG_VERSION=v0.4.1 ARG GO_VERSION=1.21 ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 -ARG GOTESTSUM_VERSION=v1.10.1 +ARG GOTESTSUM_VERSION=v1.11.0 ARG NYDUS_VERSION=v2.2.3 ARG SOCI_SNAPSHOTTER_VERSION=0.4.0 From b6d76eaee83a6fc2291024cfcb1de89e3243095a Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 10 Oct 2023 11:09:26 +0900 Subject: [PATCH 0169/1066] dockerconfigresolver: nullify DefaultTLS when DefaultScheme == "http" Workaround for containerd/containerd issue 9208 Signed-off-by: Akihiro Suda --- pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go index db9bd7b265f..6bac7c92240 100644 --- a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go +++ b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go @@ -136,6 +136,10 @@ func NewHostOptions(ctx context.Context, refHostname string, optFuncs ...Opt) (* ho.DefaultScheme = "http" } } + if ho.DefaultScheme == "http" { + // https://github.com/containerd/containerd/issues/9208 + ho.DefaultTLS = nil + } return &ho, nil } From 3b6cf7014b41bfb073a35dd37064d87c83f132c3 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 10 Oct 2023 11:10:32 +0900 Subject: [PATCH 0170/1066] go.mod: github.com/containerd/containerd v1.7.7 Signed-off-by: Akihiro Suda --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 560727d96d4..115b3eb729b 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v0.6.7 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 - github.com/containerd/containerd v1.7.6 + github.com/containerd/containerd v1.7.7 github.com/containerd/continuity v0.4.2 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 diff --git a/go.sum b/go.sum index cf10a6249b9..4f1ff1c7a07 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKk github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.6 h1:oNAVsnhPoy4BTPQivLgTzI9Oleml9l/+eYIDYXRCYo8= -github.com/containerd/containerd v1.7.6/go.mod h1:SY6lrkkuJT40BVNO37tlYTSnKJnP5AXBc0fhx0q+TJ4= +github.com/containerd/containerd v1.7.7 h1:QOC2K4A42RQpcrZyptP6z9EJZnlHfHJUfZrAAHe15q4= +github.com/containerd/containerd v1.7.7/go.mod h1:3c4XZv6VeT9qgf9GMTxNTMFxGJrGpI2vz1yk4ye+YY8= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= From 3b09b4cb211f2c4b354525048142076bc6970ca2 Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Tue, 10 Oct 2023 14:45:25 +0800 Subject: [PATCH 0171/1066] fix: call client close Signed-off-by: guoguangwu --- pkg/cmd/builder/build.go | 6 ++++-- pkg/cmd/container/stats.go | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 378cd1267ae..90f3dfa75a8 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -131,8 +131,10 @@ func loadImage(ctx context.Context, in io.Reader, namespace, address, snapshotte if err != nil { return err } - defer cancel() - + defer func() { + cancel() + client.Close() + }() r := &readCounter{Reader: in} imgs, err := client.Import(ctx, r, containerd.WithDigestRef(archive.DigestTranslator(snapshotter)), containerd.WithSkipDigestRef(func(name string) bool { return name != "" }), containerd.WithImportPlatform(platMC)) if err != nil { diff --git a/pkg/cmd/container/stats.go b/pkg/cmd/container/stats.go index bdc09ed99a2..7b916c1a7db 100644 --- a/pkg/cmd/container/stats.go +++ b/pkg/cmd/container/stats.go @@ -343,7 +343,10 @@ func collect(ctx context.Context, globalOptions types.GlobalCommandOptions, s *s s.SetError(err) return } - defer cancel() + defer func() { + cancel() + client.Close() + }() container, err := client.LoadContainer(ctx, id) if err != nil { s.SetError(err) From a2cfe916a614b302ea6f1576fc4dc4ebcd9a5a3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 22:27:42 +0000 Subject: [PATCH 0172/1066] build(deps): bump golang.org/x/net from 0.16.0 to 0.17.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.16.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.16.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 115b3eb729b..1a9a5d59783 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 golang.org/x/crypto v0.14.0 - golang.org/x/net v0.16.0 + golang.org/x/net v0.17.0 golang.org/x/sync v0.4.0 golang.org/x/sys v0.13.0 golang.org/x/term v0.13.0 diff --git a/go.sum b/go.sum index 4f1ff1c7a07..3d7763409a8 100644 --- a/go.sum +++ b/go.sum @@ -356,8 +356,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= -golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From ff0fa841f56563275ca87fc514db14543885d8d7 Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Wed, 11 Oct 2023 20:02:39 +0800 Subject: [PATCH 0173/1066] chore: unnecessary code Signed-off-by: guoguangwu --- cmd/nerdctl/builder.go | 4 +--- cmd/nerdctl/builder_build.go | 3 --- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index e758fa303e2..17908550ca4 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -115,9 +115,7 @@ func builderDebugAction(cmd *cobra.Command, args []string) error { return err } buildgArgs := []string{"debug"} - if err != nil { - return err - } else if globalOptions.Debug { + if globalOptions.Debug { buildgArgs = append([]string{"--debug"}, buildgArgs...) } diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index 29ed9440036..567648f86b1 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -93,9 +93,6 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu if buildContext == "-" || strings.Contains(buildContext, "://") { return types.BuilderBuildOptions{}, fmt.Errorf("unsupported build context: %q", buildContext) } - if err != nil { - return types.BuilderBuildOptions{}, err - } output, err := cmd.Flags().GetString("output") if err != nil { return types.BuilderBuildOptions{}, err From 5a874813d74d9101b3ecd0e1d06f2e8d4c49e30b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:47:31 +0000 Subject: [PATCH 0174/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.1 to 0.13.2. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.1...v0.13.2) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1a9a5d59783..61ee19d8de6 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.1 + github.com/containerd/nydus-snapshotter v0.13.2 github.com/containerd/stargz-snapshotter v0.14.3 github.com/containerd/stargz-snapshotter/estargz v0.14.3 github.com/containerd/stargz-snapshotter/ipfs v0.14.3 diff --git a/go.sum b/go.sum index 3d7763409a8..e61ce6bc3fe 100644 --- a/go.sum +++ b/go.sum @@ -48,8 +48,8 @@ github.com/containerd/imgcrypt v1.1.8 h1:ZS7TuywcRNLoHpU0g+v4/PsKynl6TYlw5xDVWWo github.com/containerd/imgcrypt v1.1.8/go.mod h1:x6QvFIkMyO2qGIY2zXc88ivEzcbgvLdWjoZyGqDap5U= 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.1 h1:5XNkCZ9ivLXCcyx3Jbbfh/fntkcls69uBg0x9VE8zlk= -github.com/containerd/nydus-snapshotter v0.13.1/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= +github.com/containerd/nydus-snapshotter v0.13.2 h1:Wjc59CetOv9TxtQIvSBY1wrjHxwD48gHR/TxyEeRTmI= +github.com/containerd/nydus-snapshotter v0.13.2/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= github.com/containerd/stargz-snapshotter v0.14.3/go.mod h1:j2Ya4JeA5gMZJr8BchSkPjlcCEh++auAxp4nidPI6N0= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= From 5d4f0325756304f6b52bde6924f00c9c98f92ad3 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 13 Oct 2023 07:53:41 +0900 Subject: [PATCH 0175/1066] nerdctl compose: fix --env-file Fix issue 2566 This was a regression in PR 2472 (v1.6.0) Signed-off-by: Akihiro Suda --- cmd/nerdctl/compose_config_test.go | 21 +++++++++++++++++++++ pkg/composer/composer.go | 10 ++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/compose_config_test.go b/cmd/nerdctl/compose_config_test.go index 4f519a46c99..705d467cb8f 100644 --- a/cmd/nerdctl/compose_config_test.go +++ b/cmd/nerdctl/compose_config_test.go @@ -130,3 +130,24 @@ services: base.ComposeCmd("--project-directory", comp.Dir(), "config", "--services").AssertOutContainsAll("hello1\n", "hello2\n") base.ComposeCmd("--project-directory", comp.Dir(), "config").AssertOutContains("alpine:3.14") } + +func TestComposeConfigWithEnvFile(t *testing.T) { + base := testutil.NewBase(t) + + const dockerComposeYAML = ` +services: + hello: + image: ${image} +` + + comp := testutil.NewComposeDir(t, dockerComposeYAML) + defer comp.CleanUp() + + envFile := filepath.Join(comp.Dir(), "env") + const envFileContent = ` +image: hello-world +` + assert.NilError(t, os.WriteFile(envFile, []byte(envFileContent), 0644)) + + base.ComposeCmd("-f", comp.YAMLFullPath(), "--env-file", envFile, "config").AssertOutContains("image: hello-world") +} diff --git a/pkg/composer/composer.go b/pkg/composer/composer.go index a01fc41576e..67a533dc2ac 100644 --- a/pkg/composer/composer.go +++ b/pkg/composer/composer.go @@ -70,16 +70,18 @@ func New(o Options, client *containerd.Client) (*Composer, error) { optionsFn = append(optionsFn, composecli.WithOsEnv, composecli.WithWorkingDirectory(o.ProjectDirectory), - composecli.WithConfigFileEnv, - composecli.WithDefaultConfigPath, - composecli.WithDotEnv, - composecli.WithName(o.Project), ) if o.EnvFile != "" { optionsFn = append(optionsFn, composecli.WithEnvFiles(o.EnvFile), ) } + optionsFn = append(optionsFn, + composecli.WithConfigFileEnv, + composecli.WithDefaultConfigPath, + composecli.WithDotEnv, + composecli.WithName(o.Project), + ) projectOptions, err := composecli.NewProjectOptions(o.ConfigPaths, optionsFn...) if err != nil { From bc62b220ec37b4c283a0c7b1e79466de04dd769f Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Fri, 13 Oct 2023 10:35:26 +0800 Subject: [PATCH 0176/1066] fix: typo Signed-off-by: guoguangwu --- .../nerdctl-ipfs-registry-kubernetes/ipfs-cluster/README.md | 2 +- .../ipfs-stargz-snapshotter/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/README.md b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/README.md index c56f74ae7b7..b8549e06238 100644 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/README.md +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/README.md @@ -55,7 +55,7 @@ $ docker exec -it kind-worker /bin/bash The image added to `kind-worker` is shared to other nodes via IPFS. You can run this image on the nodes using the following manifest. -CID of the pushed image is printed when `nerdctl push` is succeded (we assume that the image is added to IPFS as CID `bafkreictyyoysj56v772xbfhyfrcvmgmfpa4vodmqaroz53ytvai7nof6u`). +CID of the pushed image is printed when `nerdctl push` is succeeded (we assume that the image is added to IPFS as CID `bafkreictyyoysj56v772xbfhyfrcvmgmfpa4vodmqaroz53ytvai7nof6u`). ```console $ cat < Date: Fri, 13 Oct 2023 22:23:27 +0000 Subject: [PATCH 0177/1066] build(deps): bump github.com/containerd/accelerated-container-image Bumps [github.com/containerd/accelerated-container-image](https://github.com/containerd/accelerated-container-image) from 0.6.7 to 1.0.0. - [Release notes](https://github.com/containerd/accelerated-container-image/releases) - [Commits](https://github.com/containerd/accelerated-container-image/compare/v0.6.7...v1.0.0) --- updated-dependencies: - dependency-name: github.com/containerd/accelerated-container-image dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 61ee19d8de6..f4d5729d8c6 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Microsoft/hcsshim v0.11.1 github.com/awslabs/soci-snapshotter v0.4.0 github.com/compose-spec/compose-go v1.19.0 - github.com/containerd/accelerated-container-image v0.6.7 + github.com/containerd/accelerated-container-image v1.0.0 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.7.7 diff --git a/go.sum b/go.sum index e61ce6bc3fe..3d67a507892 100644 --- a/go.sum +++ b/go.sum @@ -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.19.0 h1:t68gAcwStDg0hy2kFvqHJIksf6xkqRnlSKfL45/ETqo= github.com/compose-spec/compose-go v1.19.0/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= -github.com/containerd/accelerated-container-image v0.6.7 h1:QDO12lgUubiUq0ogMzcL6CdSxkzFOX7vVaSIXAJ9EaM= -github.com/containerd/accelerated-container-image v0.6.7/go.mod h1:a7MYTlNhR4+GGpXD7wuNSgxrwC2wE2rgUfCvef+FQzg= +github.com/containerd/accelerated-container-image v1.0.0 h1:BWc+VNimtSXUCiegKWhqcHxN9GV4ve3kJEL1968AWF8= +github.com/containerd/accelerated-container-image v1.0.0/go.mod h1:LYLT4rKKzJn9Ts0I8uk1pivFmqil/Y3WZT0u+9zb6BA= 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.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= From 63d446f18119bd0fedf903aea29089bb46a8e017 Mon Sep 17 00:00:00 2001 From: TinaMor Date: Tue, 3 Oct 2023 21:03:42 +0300 Subject: [PATCH 0178/1066] Use https://github.com/containerd/log for logging This commit replace direct dependencies on github.com/sirupsen/logrus and github.com/containerd/containerd/log with https://github.com/containerd/log. logrus.SetOutput() is retained since not all logrus API are provided. Signed-off-by: Christine Murimi --- cmd/nerdctl/builder.go | 4 +- cmd/nerdctl/compose_ps.go | 4 +- cmd/nerdctl/compose_run_linux_test.go | 6 +-- cmd/nerdctl/compose_up_linux_test.go | 4 +- cmd/nerdctl/container_run.go | 10 ++-- cmd/nerdctl/container_update.go | 3 +- cmd/nerdctl/image_history.go | 4 +- cmd/nerdctl/login.go | 4 +- cmd/nerdctl/main.go | 20 +++---- cmd/nerdctl/main_unix.go | 4 +- cmd/nerdctl/namespace.go | 10 ++-- cmd/nerdctl/system_prune.go | 4 +- cmd/nerdctl/system_prune_linux_test.go | 4 +- cmd/nerdctl/version.go | 4 +- pkg/apparmorutil/apparmorutil_linux.go | 8 +-- pkg/buildkitutil/buildkitutil.go | 14 ++--- pkg/clientutil/client.go | 6 +-- pkg/cmd/apparmor/load_linux.go | 4 +- pkg/cmd/apparmor/unload_linux.go | 4 +- pkg/cmd/builder/build.go | 20 +++---- pkg/cmd/builder/prune.go | 4 +- pkg/cmd/container/attach.go | 6 +-- pkg/cmd/container/commit.go | 6 +-- pkg/cmd/container/create.go | 14 ++--- pkg/cmd/container/exec.go | 4 +- pkg/cmd/container/inspect.go | 4 +- pkg/cmd/container/kill.go | 4 +- pkg/cmd/container/list.go | 8 +-- pkg/cmd/container/list_util.go | 8 +-- pkg/cmd/container/logs.go | 6 +-- pkg/cmd/container/prune.go | 4 +- pkg/cmd/container/remove.go | 18 +++---- pkg/cmd/container/run_cgroup_linux.go | 12 ++--- pkg/cmd/container/run_linux.go | 4 +- pkg/cmd/container/run_mount.go | 8 +-- pkg/cmd/container/run_runtime.go | 4 +- pkg/cmd/container/run_security_linux.go | 8 +-- pkg/cmd/container/stats.go | 4 +- pkg/cmd/image/convert.go | 16 +++--- pkg/cmd/image/inspect.go | 4 +- pkg/cmd/image/list.go | 16 +++--- pkg/cmd/image/prune.go | 6 +-- pkg/cmd/image/push.go | 22 ++++---- pkg/cmd/image/remove.go | 6 +-- pkg/cmd/ipfs/registry_serve.go | 4 +- pkg/cmd/login/login.go | 10 ++-- pkg/cmd/network/inspect.go | 4 +- pkg/cmd/network/prune.go | 4 +- pkg/cmd/system/info.go | 6 +-- pkg/cmd/volume/list.go | 8 +-- pkg/composer/build.go | 7 ++- pkg/composer/composer.go | 10 ++-- pkg/composer/container.go | 4 +- pkg/composer/copy.go | 4 +- pkg/composer/create.go | 12 ++--- pkg/composer/down.go | 13 +++-- pkg/composer/exec.go | 4 +- pkg/composer/kill.go | 4 +- pkg/composer/logs.go | 17 +++--- pkg/composer/pull.go | 7 ++- pkg/composer/push.go | 7 ++- pkg/composer/restart.go | 7 ++- pkg/composer/rm.go | 13 +++-- pkg/composer/run.go | 12 ++--- pkg/composer/serviceparser/build.go | 8 +-- pkg/composer/serviceparser/serviceparser.go | 53 +++++++++---------- pkg/composer/stop.go | 11 ++-- pkg/composer/up.go | 7 ++- pkg/composer/up_network.go | 13 +++-- pkg/composer/up_service.go | 20 +++---- pkg/composer/up_volume.go | 7 ++- pkg/consoleutil/detach.go | 4 +- pkg/containerinspector/containerinspector.go | 10 ++-- .../container_network_manager_linux.go | 4 +- pkg/containerutil/containerutil.go | 14 ++--- pkg/containerutil/cp_linux.go | 12 ++--- pkg/defaults/defaults_linux.go | 6 +-- pkg/dnsutil/hostsstore/updater.go | 6 +-- pkg/formatter/formatter.go | 4 +- pkg/imageinspector/imageinspector.go | 10 ++-- pkg/imgutil/commit/commit.go | 17 +++--- pkg/imgutil/converter/zstd.go | 6 +-- .../dockerconfigresolver.go | 16 +++--- pkg/imgutil/filtering.go | 6 +-- pkg/imgutil/imgutil.go | 22 ++++---- pkg/imgutil/snapshotter.go | 4 +- pkg/infoutil/infoutil.go | 14 ++--- pkg/inspecttypes/dockercompat/dockercompat.go | 4 +- pkg/ipfs/image.go | 6 +-- pkg/ipfs/registry.go | 16 +++--- pkg/lockutil/lockutil_unix.go | 4 +- pkg/lockutil/lockutil_windows.go | 4 +- pkg/logging/cri_logger.go | 13 +++-- pkg/logging/fluentd_logger.go | 6 +-- pkg/logging/journald_logger.go | 8 +-- pkg/logging/json_logger.go | 8 +-- pkg/logging/jsonfile/jsonfile.go | 17 +++--- pkg/logging/log_viewer.go | 6 +-- pkg/logging/logging.go | 4 +- pkg/logging/syslog_logger.go | 4 +- pkg/mountutil/mountutil.go | 7 ++- pkg/mountutil/mountutil_freebsd.go | 4 +- pkg/mountutil/mountutil_linux.go | 8 +-- pkg/mountutil/mountutil_windows.go | 4 +- pkg/netutil/netutil.go | 10 ++-- pkg/netutil/netutil_unix.go | 12 ++--- pkg/ocihook/ocihook.go | 9 ++-- pkg/ocihook/ocihook_linux.go | 5 +- pkg/portutil/portutil.go | 4 +- pkg/resolvconf/resolvconf.go | 8 +-- pkg/rootlessutil/parent_linux.go | 6 +-- pkg/signalutil/signals.go | 10 ++-- pkg/signutil/cosignutil.go | 30 +++++------ pkg/signutil/notationutil.go | 30 +++++------ pkg/signutil/signutil.go | 6 +-- pkg/snapshotterutil/sociutil.go | 28 +++++----- pkg/tarutil/tarutil.go | 6 +-- pkg/taskutil/taskutil.go | 12 ++--- 118 files changed, 525 insertions(+), 542 deletions(-) diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index 17908550ca4..5b8357c2fa2 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -22,9 +22,9 @@ import ( "os/exec" "strings" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/buildkitutil" "github.com/containerd/nerdctl/pkg/defaults" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -75,7 +75,7 @@ func builderPruneAction(cmd *cobra.Command, _ []string) error { } buildctlArgs := buildkitutil.BuildctlBaseArgs(buildkitHost) buildctlArgs = append(buildctlArgs, "prune") - logrus.Debugf("running %s %v", buildctlBinary, buildctlArgs) + log.L.Debugf("running %s %v", buildctlBinary, buildctlArgs) buildctlCmd := exec.Command(buildctlBinary, buildctlArgs...) buildctlCmd.Env = os.Environ() buildctlCmd.Stdout = cmd.OutOrStdout() diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose_ps.go index 88c4437720b..e9e569584fb 100644 --- a/cmd/nerdctl/compose_ps.go +++ b/cmd/nerdctl/compose_ps.go @@ -27,13 +27,13 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime/restart" gocni "github.com/containerd/go-cni" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/compose" "github.com/containerd/nerdctl/pkg/containerutil" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/portutil" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" ) @@ -335,7 +335,7 @@ func formatPublishers(labelMap map[string]string) []PortPublisher { dockerPorts = append(dockerPorts, mapper(p)) } } else { - logrus.Error(err.Error()) + log.L.Error(err.Error()) } return dockerPorts } diff --git a/cmd/nerdctl/compose_run_linux_test.go b/cmd/nerdctl/compose_run_linux_test.go index a464e53418a..f0778e74e82 100644 --- a/cmd/nerdctl/compose_run_linux_test.go +++ b/cmd/nerdctl/compose_run_linux_test.go @@ -23,10 +23,10 @@ import ( "testing" "time" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/pkg/testutil/testregistry" - "github.com/sirupsen/logrus" "gotest.tools/v3/assert" ) @@ -94,7 +94,7 @@ services: stdoutContent := result.Stdout() + result.Stderr() assert.Assert(psCmd.Base.T, result.ExitCode == 0, stdoutContent) if strings.Contains(stdoutContent, containerName) { - logrus.Errorf("test failed, the container %s is not removed", stdoutContent) + log.L.Errorf("test failed, the container %s is not removed", stdoutContent) t.Fail() return } @@ -316,7 +316,7 @@ services: container := base.InspectContainer(containerName) if container.Config == nil { - logrus.Errorf("test failed, cannot fetch container config") + log.L.Errorf("test failed, cannot fetch container config") t.Fail() } assert.Equal(t, container.Config.Labels["foo"], "rab") diff --git a/cmd/nerdctl/compose_up_linux_test.go b/cmd/nerdctl/compose_up_linux_test.go index c6b5c34773a..481bbc5b16e 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/cmd/nerdctl/compose_up_linux_test.go @@ -24,10 +24,10 @@ import ( "testing" "time" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/docker/go-connections/nat" - "github.com/sirupsen/logrus" "github.com/containerd/nerdctl/pkg/testutil" "github.com/containerd/nerdctl/pkg/testutil/nettestutil" @@ -194,7 +194,7 @@ networks: stdoutContent := result.Stdout() + result.Stderr() assert.Assert(inspectCmd.Base.T, result.ExitCode == 0, stdoutContent) if !strings.Contains(stdoutContent, staticIP) { - logrus.Errorf("test failed, the actual container ip is %s", stdoutContent) + log.L.Errorf("test failed, the actual container ip is %s", stdoutContent) t.Fail() return } diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 61df9c573b0..5f2d60aeb7e 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -22,6 +22,7 @@ import ( "runtime" "github.com/containerd/console" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/container" @@ -34,7 +35,6 @@ import ( "github.com/containerd/nerdctl/pkg/netutil" "github.com/containerd/nerdctl/pkg/signalutil" "github.com/containerd/nerdctl/pkg/taskutil" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -348,11 +348,11 @@ func runAction(cmd *cobra.Command, args []string) error { // network setup/cleanup from the main nerdctl executable. if runtime.GOOS == "windows" { if err := netManager.CleanupNetworking(ctx, c); err != nil { - logrus.Warnf("failed to clean up container networking: %s", err) + log.L.Warnf("failed to clean up container networking: %s", err) } } if err := container.RemoveContainer(ctx, c, createOpt.GOptions, true, true, client); err != nil { - logrus.WithError(err).Warnf("failed to remove container %s", id) + log.L.WithError(err).Warnf("failed to remove container %s", id) } }() } @@ -387,7 +387,7 @@ func runAction(cmd *cobra.Command, args []string) error { } if createOpt.TTY { if err := consoleutil.HandleConsoleResize(ctx, task, con); err != nil { - logrus.WithError(err).Error("console resize") + log.L.WithError(err).Error("console resize") } } else { sigC := signalutil.ForwardAllSignals(ctx, task) @@ -415,7 +415,7 @@ func runAction(cmd *cobra.Command, args []string) error { case status := <-statusC: if createOpt.Rm { if _, taskDeleteErr := task.Delete(ctx); taskDeleteErr != nil { - logrus.Error(taskDeleteErr) + log.L.Error(taskDeleteErr) } } code, _, err := status.Result() diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index 5708aa0e310..73b39588271 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -36,7 +36,6 @@ import ( "github.com/containerd/typeurl/v2" "github.com/docker/go-units" runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -196,7 +195,7 @@ func getUpdateOption(cmd *cobra.Command, globalOptions types.GlobalCommandOption return options, err } if kernelMemStr != "" && cmd.Flag("kernel-memory").Changed { - logrus.Warnf("The --kernel-memory flag is no longer supported. This flag is a noop.") + log.L.Warnf("The --kernel-memory flag is no longer supported. This flag is a noop.") } cpuset, err := cmd.Flags().GetString("cpuset-cpus") if err != nil { diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index c18cd8f08ee..c5e53f0b0a7 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -29,12 +29,12 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/pkg/progress" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/opencontainers/image-spec/identity" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -198,7 +198,7 @@ func printHistory(cmd *cobra.Command, historys []historyPrintable) error { for index := len(historys) - 1; index >= 0; index-- { if err := printer.printHistory(historys[index]); err != nil { - logrus.Warn(err) + log.L.Warn(err) } } diff --git a/cmd/nerdctl/login.go b/cmd/nerdctl/login.go index adb7d31b182..e64dfee1920 100644 --- a/cmd/nerdctl/login.go +++ b/cmd/nerdctl/login.go @@ -21,10 +21,10 @@ import ( "io" "strings" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/cmd/login" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -76,7 +76,7 @@ func loginAction(cmd *cobra.Command, args []string) error { // copied from github.com/docker/cli/cli/command/registry/login.go (v20.10.3) func verifyLoginOptions(cmd *cobra.Command, options *loginOptions) error { if options.password != "" { - logrus.Warn("WARNING! Using --password via the CLI is insecure. Use --password-stdin.") + log.L.Warn("WARNING! Using --password via the CLI is insecure. Use --password-stdin.") if options.passwordStdin { return errors.New("--password and --password-stdin are mutually exclusive") } diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 3efcba76046..be8287db335 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -25,6 +25,7 @@ import ( "strings" "time" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/config" ncdefaults "github.com/containerd/nerdctl/pkg/defaults" "github.com/containerd/nerdctl/pkg/errutil" @@ -34,7 +35,6 @@ import ( "github.com/fatih/color" "github.com/pelletier/go-toml/v2" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -118,7 +118,7 @@ func usage(c *cobra.Command) error { func main() { if err := xmain(); err != nil { errutil.HandleExitCoder(err) - logrus.Fatal(err) + log.L.Fatal(err) } } @@ -139,15 +139,15 @@ func xmain() error { func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, error) { cfg := config.New() if r, err := os.Open(tomlPath); err == nil { - logrus.Debugf("Loading config from %q", tomlPath) + log.L.Debugf("Loading config from %q", tomlPath) defer r.Close() dec := toml.NewDecoder(r).DisallowUnknownFields() // set Strict to detect typo if err := dec.Decode(cfg); err != nil { return nil, fmt.Errorf("failed to load nerdctl config (not daemon config) from %q (Hint: don't mix up daemon's `config.toml` with `nerdctl.toml`): %w", tomlPath, err) } - logrus.Debugf("Loaded config %+v", cfg) + log.L.Debugf("Loaded config %+v", cfg) } else { - logrus.WithError(err).Debugf("Not loading config from %q", tomlPath) + log.L.WithError(err).Debugf("Not loading config from %q", tomlPath) if !errors.Is(err, os.ErrNotExist) { return nil, err } @@ -216,7 +216,7 @@ Config file ($NERDCTL_TOML): %s debug = globalOptions.Debug } if debug { - logrus.SetLevel(logrus.DebugLevel) + log.SetLevel(log.DebugLevel.String()) } address := globalOptions.Address if strings.Contains(address, "://") && !strings.HasPrefix(address, "unix://") { @@ -327,7 +327,7 @@ Config file ($NERDCTL_TOML): %s func globalFlags(cmd *cobra.Command) (string, []string) { args0, err := os.Executable() if err != nil { - logrus.WithError(err).Warnf("cannot call os.Executable(), assuming the executable to be %q", os.Args[0]) + log.L.WithError(err).Warnf("cannot call os.Executable(), assuming the executable to be %q", os.Args[0]) args0 = os.Args[0] } if len(os.Args) < 2 { @@ -396,7 +396,7 @@ func AddIntFlag(cmd *cobra.Command, name string, aliases []string, value int, en if envV, ok := os.LookupEnv(env); ok { v, err := strconv.ParseInt(envV, 10, 64) if err != nil { - logrus.WithError(err).Warnf("Invalid int value for `%s`", env) + log.L.WithError(err).Warnf("Invalid int value for `%s`", env) } value = int(v) } @@ -423,7 +423,7 @@ func AddDurationFlag(cmd *cobra.Command, name string, aliases []string, value ti var err error value, err = time.ParseDuration(envV) if err != nil { - logrus.WithError(err).Warnf("Invalid duration value for `%s`", env) + log.L.WithError(err).Warnf("Invalid duration value for `%s`", env) } } aliasesUsage := fmt.Sprintf("Alias of --%s", name) @@ -501,7 +501,7 @@ func AddPersistentBoolFlag(cmd *cobra.Command, name string, aliases, nonPersiste var err error value, err = strconv.ParseBool(envV) if err != nil { - logrus.WithError(err).Warnf("Invalid boolean value for `%s`", env) + log.L.WithError(err).Warnf("Invalid boolean value for `%s`", env) } } aliasesUsage := fmt.Sprintf("Alias of --%s", name) diff --git a/cmd/nerdctl/main_unix.go b/cmd/nerdctl/main_unix.go index ce8e8f9656a..d85a980ccd4 100644 --- a/cmd/nerdctl/main_unix.go +++ b/cmd/nerdctl/main_unix.go @@ -19,10 +19,10 @@ package main import ( + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -46,7 +46,7 @@ func shellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete s nsService := client.NamespaceService() nsList, err := nsService.List(ctx) if err != nil { - logrus.Warn(err) + log.L.Warn(err) return nil, cobra.ShellCompDirectiveError } var candidates []string diff --git a/cmd/nerdctl/namespace.go b/cmd/nerdctl/namespace.go index 6ede2e28aa3..58a3ca0a0d1 100644 --- a/cmd/nerdctl/namespace.go +++ b/cmd/nerdctl/namespace.go @@ -24,9 +24,9 @@ import ( "text/tabwriter" "github.com/containerd/containerd/namespaces" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/mountutil/volumestore" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -103,24 +103,24 @@ func namespaceLsAction(cmd *cobra.Command, args []string) error { containers, err := client.Containers(ctx) if err != nil { - logrus.Warn(err) + log.L.Warn(err) } numContainers = len(containers) images, err := client.ImageService().List(ctx) if err != nil { - logrus.Warn(err) + log.L.Warn(err) } numImages = len(images) volStore, err := volumestore.Path(dataStore, ns) if err != nil { - logrus.Warn(err) + log.L.Warn(err) } else { volEnts, err := os.ReadDir(volStore) if err != nil { if !os.IsNotExist(err) { - logrus.Warn(err) + log.L.Warn(err) } } numVolumes = len(volEnts) diff --git a/cmd/nerdctl/system_prune.go b/cmd/nerdctl/system_prune.go index eea6031b609..944b2fdcf45 100644 --- a/cmd/nerdctl/system_prune.go +++ b/cmd/nerdctl/system_prune.go @@ -20,10 +20,10 @@ import ( "fmt" "strings" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/system" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -60,7 +60,7 @@ func processSystemPruneOptions(cmd *cobra.Command) (types.SystemPruneOptions, er buildkitHost, err := getBuildkitHost(cmd, globalOptions.Namespace) if err != nil { - logrus.WithError(err).Warn("BuildKit is not running. Build caches will not be pruned.") + log.L.WithError(err).Warn("BuildKit is not running. Build caches will not be pruned.") buildkitHost = "" } diff --git a/cmd/nerdctl/system_prune_linux_test.go b/cmd/nerdctl/system_prune_linux_test.go index 034225b0bb8..24c7b9d481e 100644 --- a/cmd/nerdctl/system_prune_linux_test.go +++ b/cmd/nerdctl/system_prune_linux_test.go @@ -25,9 +25,9 @@ import ( "strings" "testing" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/buildkitutil" "github.com/containerd/nerdctl/pkg/testutil" - "github.com/sirupsen/logrus" ) func TestSystemPrune(t *testing.T) { @@ -79,7 +79,7 @@ func TestSystemPrune(t *testing.T) { buildctlArgs := buildkitutil.BuildctlBaseArgs(host) buildctlArgs = append(buildctlArgs, "du") - logrus.Debugf("running %s %v", buildctlBinary, buildctlArgs) + log.L.Debugf("running %s %v", buildctlBinary, buildctlArgs) buildctlCmd := exec.Command(buildctlBinary, buildctlArgs...) buildctlCmd.Env = os.Environ() stdout := bytes.NewBuffer(nil) diff --git a/cmd/nerdctl/version.go b/cmd/nerdctl/version.go index 3ce1cfe28ba..88eec8c775b 100644 --- a/cmd/nerdctl/version.go +++ b/cmd/nerdctl/version.go @@ -23,12 +23,12 @@ import ( "os" "text/template" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -72,7 +72,7 @@ func versionAction(cmd *cobra.Command, args []string) error { if rootlessutil.IsRootless() { address, err = rootlessutil.RootlessContainredSockAddress() if err != nil { - logrus.WithError(err).Warning("failed to inspect the rootless containerd socket address") + log.L.WithError(err).Warning("failed to inspect the rootless containerd socket address") address = "" } } diff --git a/pkg/apparmorutil/apparmorutil_linux.go b/pkg/apparmorutil/apparmorutil_linux.go index 901940180d0..38ea38c7f2d 100644 --- a/pkg/apparmorutil/apparmorutil_linux.go +++ b/pkg/apparmorutil/apparmorutil_linux.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd/pkg/apparmor" "github.com/containerd/containerd/pkg/userns" - "github.com/sirupsen/logrus" + "github.com/containerd/log" ) // CanLoadNewProfile returns whether the current process can load a new AppArmor profile. @@ -73,7 +73,7 @@ func CanApplySpecificExistingProfile(profileName string) bool { cmd := exec.Command("aa-exec", "-p", profileName, "--", "true") out, err := cmd.CombinedOutput() if err != nil { - logrus.WithError(err).Debugf("failed to run %v: %q", cmd.Args, string(out)) + log.L.WithError(err).Debugf("failed to run %v: %q", cmd.Args, string(out)) return false } return true @@ -101,7 +101,7 @@ func Profiles() ([]Profile, error) { namePath := filepath.Join(profilesPath, ent.Name(), "name") b, err := os.ReadFile(namePath) if err != nil { - logrus.WithError(err).Warnf("failed to read %q", namePath) + log.L.WithError(err).Warnf("failed to read %q", namePath) continue } profile := Profile{ @@ -110,7 +110,7 @@ func Profiles() ([]Profile, error) { modePath := filepath.Join(profilesPath, ent.Name(), "mode") b, err = os.ReadFile(modePath) if err != nil { - logrus.WithError(err).Warnf("failed to read %q", namePath) + log.L.WithError(err).Warnf("failed to read %q", namePath) } else { profile.Mode = strings.TrimSpace(string(b)) } diff --git a/pkg/buildkitutil/buildkitutil.go b/pkg/buildkitutil/buildkitutil.go index 12893233b85..b89170d91ba 100644 --- a/pkg/buildkitutil/buildkitutil.go +++ b/pkg/buildkitutil/buildkitutil.go @@ -35,8 +35,8 @@ import ( "path/filepath" "runtime" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/sirupsen/logrus" ) const ( @@ -65,7 +65,7 @@ func GetBuildkitHost(namespace string) (string, error) { var err error run, err = rootlessutil.XDGRuntimeDir() if err != nil { - logrus.Warn(err) + log.L.Warn(err) run = fmt.Sprintf("/run/user/%d", rootlessutil.ParentEUID()) } } @@ -76,17 +76,17 @@ func GetBuildkitHost(namespace string) (string, error) { hostRel = append(hostRel, "buildkit-default/buildkitd.sock", "buildkit/buildkitd.sock") var errs []error //nolint:prealloc for _, p := range hostRel { - logrus.Debugf("Choosing the buildkit host %q, candidates=%v (in %q)", p, hostRel, run) + log.L.Debugf("Choosing the buildkit host %q, candidates=%v (in %q)", p, hostRel, run) buildkitHost := "unix://" + filepath.Join(run, p) _, err := pingBKDaemon(buildkitHost) if err == nil { - logrus.Debugf("Chosen buildkit host %q", buildkitHost) + log.L.Debugf("Chosen buildkit host %q", buildkitHost) return buildkitHost, nil } errs = append(errs, fmt.Errorf("failed to ping to host %s: %w", buildkitHost, err)) } allErr := errors.Join(errs...) - logrus.WithError(allErr).Error(getHint()) + log.L.WithError(allErr).Error(getHint()) return "", fmt.Errorf("no buildkit host is available, tried %d candidates: %w", len(hostRel), allErr) } @@ -136,7 +136,7 @@ func getHint() string { func PingBKDaemon(buildkitHost string) error { if out, err := pingBKDaemon(buildkitHost); err != nil { if out != "" { - logrus.Error(out) + log.L.Error(out) } return fmt.Errorf(getHint()+": %w", err) } @@ -215,7 +215,7 @@ func BuildKitFile(dir, inputfile string) (absDir string, file string, err error) return "", "", err } if !bytes.Equal(dockerfile, containerfile) { - logrus.Warnf("%s and %s have different contents, building with %s", DefaultDockerfileName, ContainerfileName, DefaultDockerfileName) + log.L.Warnf("%s and %s have different contents, building with %s", DefaultDockerfileName, ContainerfileName, DefaultDockerfileName) } } if dErr != nil { diff --git a/pkg/clientutil/client.go b/pkg/clientutil/client.go index 45013133ad5..5f3aa4e82eb 100644 --- a/pkg/clientutil/client.go +++ b/pkg/clientutil/client.go @@ -27,10 +27,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/opencontainers/go-digest" - "github.com/sirupsen/logrus" ) func NewClient(ctx context.Context, namespace, address string, opts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { @@ -62,9 +62,9 @@ func NewClientWithPlatform(ctx context.Context, namespace, address, platform str warn := fmt.Sprintf("Platform %q seems incompatible with the host platform %q. If you see \"exec format error\", see https://github.com/containerd/nerdctl/blob/main/docs/multi-platform.md", platform, platforms.DefaultString()) if canExecErr != nil { - logrus.WithError(canExecErr).Warn(warn) + log.L.WithError(canExecErr).Warn(warn) } else { - logrus.Warn(warn) + log.L.Warn(warn) } } platformParsed, err := platforms.Parse(platform) diff --git a/pkg/cmd/apparmor/load_linux.go b/pkg/cmd/apparmor/load_linux.go index b8112aa99e0..ed45eaf7da5 100644 --- a/pkg/cmd/apparmor/load_linux.go +++ b/pkg/cmd/apparmor/load_linux.go @@ -18,11 +18,11 @@ package apparmor import ( "github.com/containerd/containerd/contrib/apparmor" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/defaults" - "github.com/sirupsen/logrus" ) func Load() error { - logrus.Infof("Loading profile %q", defaults.AppArmorProfileName) + log.L.Infof("Loading profile %q", defaults.AppArmorProfileName) return apparmor.LoadDefaultProfile(defaults.AppArmorProfileName) } diff --git a/pkg/cmd/apparmor/unload_linux.go b/pkg/cmd/apparmor/unload_linux.go index 8994834efdf..b5e349ae4dd 100644 --- a/pkg/cmd/apparmor/unload_linux.go +++ b/pkg/cmd/apparmor/unload_linux.go @@ -17,11 +17,11 @@ package apparmor import ( + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/apparmorutil" - "github.com/sirupsen/logrus" ) func Unload(target string) error { - logrus.Infof("Unloading profile %q", target) + log.L.Infof("Unloading profile %q", target) return apparmorutil.Unload(target) } diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 90f3dfa75a8..4dc06928e79 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -34,12 +34,12 @@ import ( "github.com/containerd/containerd/images/archive" "github.com/containerd/containerd/platforms" dockerreference "github.com/containerd/containerd/reference/docker" + "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/sirupsen/logrus" ) func Build(ctx context.Context, client *containerd.Client, options types.BuilderBuildOptions) error { @@ -51,7 +51,7 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder defer cleanup() } - logrus.Debugf("running %s %v", buildctlBinary, buildctlArgs) + log.L.Debugf("running %s %v", buildctlBinary, buildctlArgs) buildctlCmd := exec.Command(buildctlBinary, buildctlArgs...) buildctlCmd.Env = os.Environ() @@ -97,7 +97,7 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder } if len(tags) > 1 { - logrus.Debug("Found more than 1 tag") + log.L.Debug("Found more than 1 tag") imageService := client.ImageService() image, err := imageService.Get(ctx, tags[0]) if err != nil { @@ -285,7 +285,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option if ok { buildctlArgs = append(buildctlArgs, fmt.Sprintf("--opt=build-arg:%s=%s", ba, val)) } else { - logrus.Debugf("ignoring unset build arg %q", ba) + log.L.Debugf("ignoring unset build arg %q", ba) } } else if len(arr) > 1 && len(arr[0]) > 0 { buildctlArgs = append(buildctlArgs, "--opt=build-arg:"+ba) @@ -300,7 +300,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option buildctlArgs = append(buildctlArgs, "--export-cache=type=inline") } } else { - logrus.WithError(err).Warnf("invalid BUILDKIT_INLINE_CACHE: %q", bic) + log.L.WithError(err).Warnf("invalid BUILDKIT_INLINE_CACHE: %q", bic) } } } else { @@ -347,7 +347,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option } if !options.Rm { - logrus.Warn("ignoring deprecated flag: '--rm=false'") + log.L.Warn("ignoring deprecated flag: '--rm=false'") } if options.IidFile != "" { @@ -368,7 +368,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option buildctlArgs = append(buildctlArgs, "--opt=force-network-mode="+options.NetworkMode, "--allow=network.host", "--allow=security.insecure") case "", "default": default: - logrus.Debugf("ignoring network build arg %s", options.NetworkMode) + log.L.Debugf("ignoring network build arg %s", options.NetworkMode) } } @@ -384,7 +384,7 @@ func getDigestFromMetaFile(path string) (string, error) { metadata := map[string]json.RawMessage{} if err := json.Unmarshal(data, &metadata); err != nil { - logrus.WithError(err).Errorf("failed to unmarshal metadata file %s", path) + log.L.WithError(err).Errorf("failed to unmarshal metadata file %s", path) return "", err } digestRaw, ok := metadata["containerimage.digest"] @@ -393,7 +393,7 @@ func getDigestFromMetaFile(path string) (string, error) { } var digest string if err := json.Unmarshal(digestRaw, &digest); err != nil { - logrus.WithError(err).Errorf("failed to unmarshal digset") + log.L.WithError(err).Errorf("failed to unmarshal digset") return "", err } return digest, nil @@ -404,7 +404,7 @@ func isImageSharable(buildkitHost, namespace, uuid, snapshotter string, platform if err != nil { return false, err } - logrus.Debugf("worker labels: %+v", labels) + log.L.Debugf("worker labels: %+v", labels) executor, ok := labels["org.mobyproject.buildkit.worker.executor"] if !ok { return false, nil diff --git a/pkg/cmd/builder/prune.go b/pkg/cmd/builder/prune.go index 18ba6dc0b49..0bd970df320 100644 --- a/pkg/cmd/builder/prune.go +++ b/pkg/cmd/builder/prune.go @@ -23,9 +23,9 @@ import ( "io" "os/exec" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/buildkitutil" - "github.com/sirupsen/logrus" ) // Prune will prune all build cache. @@ -40,7 +40,7 @@ func Prune(ctx context.Context, options types.BuilderPruneOptions) ([]buildkitut buildctlArgs = append(buildctlArgs, "--all") } buildctlCmd := exec.Command(buildctlBinary, buildctlArgs...) - logrus.Debugf("running %v", buildctlCmd.Args) + log.G(ctx).Debugf("running %v", buildctlCmd.Args) buildctlCmd.Stderr = options.Stderr stdout, err := buildctlCmd.StdoutPipe() if err != nil { diff --git a/pkg/cmd/container/attach.go b/pkg/cmd/container/attach.go index a84cb8febfe..a4c3944e60a 100644 --- a/pkg/cmd/container/attach.go +++ b/pkg/cmd/container/attach.go @@ -24,12 +24,12 @@ import ( "github.com/containerd/console" "github.com/containerd/containerd" "github.com/containerd/containerd/cio" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/consoleutil" "github.com/containerd/nerdctl/pkg/errutil" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/signalutil" - "github.com/sirupsen/logrus" ) // Attach attaches stdin, stdout, and stderr to a running container. @@ -80,7 +80,7 @@ func Attach(ctx context.Context, client *containerd.Client, req string, options // [1] https://github.com/containerd/containerd/blob/8f756bc8c26465bd93e78d9cd42082b66f276e10/cio/io.go#L358-L359 io := task.IO() if io == nil { - logrus.Errorf("got a nil io") + log.G(ctx).Errorf("got a nil io") return } io.Cancel() @@ -99,7 +99,7 @@ func Attach(ctx context.Context, client *containerd.Client, req string, options } if spec.Process.Terminal { if err := consoleutil.HandleConsoleResize(ctx, task, con); err != nil { - logrus.WithError(err).Error("console resize") + log.G(ctx).WithError(err).Error("console resize") } } sigC := signalutil.ForwardAllSignals(ctx, task) diff --git a/pkg/cmd/container/commit.go b/pkg/cmd/container/commit.go index 1dd6fc3ecc7..b355d1c02a8 100644 --- a/pkg/cmd/container/commit.go +++ b/pkg/cmd/container/commit.go @@ -23,11 +23,11 @@ import ( "strings" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/imgutil/commit" "github.com/containerd/nerdctl/pkg/referenceutil" - "github.com/sirupsen/logrus" ) // Commit will commit a container’s file changes or settings into a new image. @@ -96,7 +96,7 @@ func parseChanges(userChanges []string) (commit.Changes, error) { return commit.Changes{}, fmt.Errorf("malformed json in change flag value %q", change) } if changes.CMD != nil { - logrus.Warn("multiple change flags supplied for the CMD directive, overriding with last supplied") + log.L.Warn("multiple change flags supplied for the CMD directive, overriding with last supplied") } changes.CMD = overrideCMD case entrypointDirective: @@ -105,7 +105,7 @@ func parseChanges(userChanges []string) (commit.Changes, error) { return commit.Changes{}, fmt.Errorf("malformed json in change flag value %q", change) } if changes.Entrypoint != nil { - logrus.Warnf("multiple change flags supplied for the Entrypoint directive, overriding with last supplied") + log.L.Warnf("multiple change flags supplied for the Entrypoint directive, overriding with last supplied") } changes.Entrypoint = overrideEntrypoint default: // TODO: Support the rest of the change directives diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 88246e3d7b3..e2409877288 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -35,6 +35,7 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" gocni "github.com/containerd/go-cni" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/image" @@ -53,7 +54,6 @@ import ( dockercliopts "github.com/docker/cli/opts" dockeropts "github.com/docker/docker/opts" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" ) // Create will create a container. @@ -294,7 +294,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa // perform network setup/teardown in the main nerdctl executable. if containerErr == nil && runtime.GOOS == "windows" { netSetupErr = netManager.SetupNetworking(ctx, id) - logrus.WithError(netSetupErr).Warnf("networking setup error has occurred") + log.G(ctx).WithError(netSetupErr).Warnf("networking setup error has occurred") } if containerErr != nil || netSetupErr != nil { @@ -693,7 +693,7 @@ func generateLogConfig(dataStore string, id string, logDriver string, logOpt []s return } if lu != nil { - logrus.Debugf("generated log driver: %s", lu.String()) + log.L.Debugf("generated log driver: %s", lu.String()) logConfig.LogURI = lu.String() } } @@ -705,21 +705,21 @@ func generateGcFunc(ctx context.Context, container containerd.Container, ns, id, if containerErr == nil { netGcErr := netManager.CleanupNetworking(ctx, container) if netGcErr != nil { - logrus.WithError(netGcErr).Warnf("failed to revert container %q networking settings", id) + log.G(ctx).WithError(netGcErr).Warnf("failed to revert container %q networking settings", id) } } if rmErr := os.RemoveAll(internalLabels.stateDir); rmErr != nil { - logrus.WithError(rmErr).Warnf("failed to remove container %q state dir %q", id, internalLabels.stateDir) + log.G(ctx).WithError(rmErr).Warnf("failed to remove container %q state dir %q", id, internalLabels.stateDir) } if name != "" { var errE error if containerNameStore, errE = namestore.New(dataStore, ns); errE != nil { - logrus.WithError(errE).Warnf("failed to instantiate container name store during cleanup for container %q", id) + log.G(ctx).WithError(errE).Warnf("failed to instantiate container name store during cleanup for container %q", id) } if errE = containerNameStore.Release(name, id); errE != nil { - logrus.WithError(errE).Warnf("failed to release container name store for container %q (%s)", name, id) + log.G(ctx).WithError(errE).Warnf("failed to release container name store for container %q (%s)", name, id) } } } diff --git a/pkg/cmd/container/exec.go b/pkg/cmd/container/exec.go index ac163b85a23..a50f4106e84 100644 --- a/pkg/cmd/container/exec.go +++ b/pkg/cmd/container/exec.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/console" "github.com/containerd/containerd" "github.com/containerd/containerd/cio" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/consoleutil" "github.com/containerd/nerdctl/pkg/flagutil" @@ -33,7 +34,6 @@ import ( "github.com/containerd/nerdctl/pkg/signalutil" "github.com/containerd/nerdctl/pkg/taskutil" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" ) // Exec will find the right running container to run a new command. @@ -113,7 +113,7 @@ func execActionWithContainer(ctx context.Context, client *containerd.Client, con if !options.Detach { if options.TTY { if err := consoleutil.HandleConsoleResize(ctx, process, con); err != nil { - logrus.WithError(err).Error("console resize") + log.G(ctx).WithError(err).Error("console resize") } } else { sigc := signalutil.ForwardAllSignals(ctx, process) diff --git a/pkg/cmd/container/inspect.go b/pkg/cmd/container/inspect.go index 07b5f3dca61..458fd0e60a4 100644 --- a/pkg/cmd/container/inspect.go +++ b/pkg/cmd/container/inspect.go @@ -22,12 +22,12 @@ import ( "time" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/containerinspector" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/sirupsen/logrus" ) // Inspect prints detailed information for each container in `containers`. @@ -44,7 +44,7 @@ func Inspect(ctx context.Context, client *containerd.Client, containers []string err := walker.WalkAll(ctx, containers, true) if len(f.entries) > 0 { if formatErr := formatter.FormatSlice(options.Format, options.Stdout, f.entries); formatErr != nil { - logrus.Error(formatErr) + log.L.Error(formatErr) } } return err diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index 9666faae6cd..6c0f7031752 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -26,11 +26,11 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/containerutil" "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/moby/sys/signal" - "github.com/sirupsen/logrus" ) // Kill kills a list of containers @@ -101,7 +101,7 @@ func killContainer(ctx context.Context, container containerd.Container, signal s // signal will be sent once resume is finished if paused { if err := task.Resume(ctx); err != nil { - logrus.Warnf("cannot unpause container %s: %s", container.ID(), err) + log.G(ctx).Warnf("cannot unpause container %s: %s", container.ID(), err) } } return nil diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index f8a8eb5e03a..c05989365ec 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -28,12 +28,12 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/pkg/progress" + "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/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/labels/k8slabels" - "github.com/sirupsen/logrus" ) // List prints containers according to `options`. @@ -107,7 +107,7 @@ func prepareContainers(ctx context.Context, client *containerd.Client, container info, err := c.Info(ctx, containerd.WithoutRefreshedMetadata) if err != nil { if errdefs.IsNotFound(err) { - logrus.Warn(err) + log.G(ctx).Warn(err) continue } return nil, err @@ -115,7 +115,7 @@ func prepareContainers(ctx context.Context, client *containerd.Client, container spec, err := c.Spec(ctx) if err != nil { if errdefs.IsNotFound(err) { - logrus.Warn(err) + log.G(ctx).Warn(err) continue } return nil, err @@ -170,7 +170,7 @@ func getContainerNetworks(containerLables map[string]string) []string { var networks []string if names, ok := containerLables[labels.Networks]; ok { if err := json.Unmarshal([]byte(names), &networks); err != nil { - logrus.Warn(err) + log.L.Warn(err) } } return networks diff --git a/pkg/cmd/container/list_util.go b/pkg/cmd/container/list_util.go index abe482b71c7..6067405fb87 100644 --- a/pkg/cmd/container/list_util.go +++ b/pkg/cmd/container/list_util.go @@ -25,8 +25,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/sirupsen/logrus" ) func foldContainerFilters(ctx context.Context, containers []containerd.Container, filters []string) (*containerFilterContext, error) { @@ -121,7 +121,7 @@ func (cl *containerFilterContext) foldStatusFilter(_ context.Context, filter, va return containerd.Stopped == stats }) case containerd.ProcessStatus("restarting"), containerd.ProcessStatus("removing"), containerd.ProcessStatus("dead"): - logrus.Warnf("%s is not supported and is ignored", filter) + log.L.Warnf("%s is not supported and is ignored", filter) default: return fmt.Errorf("invalid filter '%s'", filter) } @@ -232,12 +232,12 @@ func (cl *containerFilterContext) matchesTaskFilters(ctx context.Context, contai defer cancel() task, err := container.Task(ctx, nil) if err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) return false } status, err := task.Status(ctx) if err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) return false } return cl.matchesExitedFilter(status) && cl.matchesStatusFilter(status) diff --git a/pkg/cmd/container/logs.go b/pkg/cmd/container/logs.go index c971a15d480..239074c36cd 100644 --- a/pkg/cmd/container/logs.go +++ b/pkg/cmd/container/logs.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/api/types/cri" "github.com/containerd/nerdctl/pkg/clientutil" @@ -32,7 +33,6 @@ import ( "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/labels/k8slabels" "github.com/containerd/nerdctl/pkg/logging" - "github.com/sirupsen/logrus" ) func Logs(ctx context.Context, client *containerd.Client, container string, options types.ContainerLogsOptions) error { @@ -43,7 +43,7 @@ func Logs(ctx context.Context, client *containerd.Client, container string, opti switch options.GOptions.Namespace { case "moby": - logrus.Warn("Currently, `nerdctl logs` only supports containers created with `nerdctl run -d` or CRI") + log.G(ctx).Warn("Currently, `nerdctl logs` only supports containers created with `nerdctl run -d` or CRI") } stopChannel := make(chan os.Signal, 1) @@ -90,7 +90,7 @@ func Logs(ctx context.Context, client *containerd.Client, container string, opti // Setup goroutine to send stop event if container task finishes: go func() { <-waitCh - logrus.Debugf("container task has finished, sending kill signal to log viewer") + log.G(ctx).Debugf("container task has finished, sending kill signal to log viewer") stopChannel <- os.Interrupt }() } diff --git a/pkg/cmd/container/prune.go b/pkg/cmd/container/prune.go index af827e51a76..b0f8f1221ca 100644 --- a/pkg/cmd/container/prune.go +++ b/pkg/cmd/container/prune.go @@ -23,8 +23,8 @@ import ( "strings" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" - "github.com/sirupsen/logrus" ) // Prune remove all stopped containers @@ -43,7 +43,7 @@ func Prune(ctx context.Context, client *containerd.Client, options types.Contain if errors.As(err, &ErrContainerStatus{}) { continue } - logrus.WithError(err).Warnf("failed to remove container %s", c.ID()) + log.G(ctx).WithError(err).Warnf("failed to remove container %s", c.ID()) } if len(deleted) > 0 { diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index bf8dc691060..d0d476fd48d 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -29,6 +29,7 @@ import ( "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/namespaces" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/volume" @@ -37,7 +38,6 @@ import ( "github.com/containerd/nerdctl/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/namestore" - "github.com/sirupsen/logrus" ) var _ error = ErrContainerStatus{} @@ -82,7 +82,7 @@ func Remove(ctx context.Context, client *containerd.Client, containers []string, err := walker.WalkAll(ctx, containers, true) if err != nil && options.Force { - logrus.Error(err) + log.G(ctx).Error(err) return nil } return err @@ -124,16 +124,16 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions return } if err := os.RemoveAll(stateDir); err != nil { - logrus.WithError(retErr).Warnf("failed to remove container state dir %s", stateDir) + log.G(ctx).WithError(retErr).Warnf("failed to remove container state dir %s", stateDir) } // enforce release name here in case the poststop hook name release fails if name != "" { if err := namst.Release(name, id); err != nil { - logrus.WithError(retErr).Warnf("failed to release container name %s", name) + log.G(ctx).WithError(retErr).Warnf("failed to release container name %s", name) } } if err := hostsstore.DeallocHostsFile(dataStore, ns, id); err != nil { - logrus.WithError(retErr).Warnf("failed to remove hosts file for container %q", id) + log.G(ctx).WithError(retErr).Warnf("failed to remove hosts file for container %q", id) } }() @@ -149,7 +149,7 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions } defer func() { if _, err := volStore.Remove(anonVolumes); err != nil { - logrus.WithError(err).Warnf("failed to remove anonymous volumes %v", anonVolumes) + log.G(ctx).WithError(err).Warnf("failed to remove anonymous volumes %v", anonVolumes) } }() } @@ -192,7 +192,7 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions } if err := networkManager.CleanupNetworking(ctx, c); err != nil { - logrus.WithError(retErr).Warnf("failed to clean up container networking: %s", err) + log.G(ctx).WithError(retErr).Warnf("failed to clean up container networking: %s", err) } } @@ -215,7 +215,7 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions return NewStatusError(id, status.Status) } if err := task.Kill(ctx, syscall.SIGKILL); err != nil { - logrus.WithError(err).Warnf("failed to send SIGKILL") + log.G(ctx).WithError(err).Warnf("failed to send SIGKILL") } es, err := task.Wait(ctx) if err == nil { @@ -223,7 +223,7 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions } _, err = task.Delete(ctx, containerd.WithProcessKill) if err != nil && !errdefs.IsNotFound(err) { - logrus.WithError(err).Warnf("failed to delete task %v", id) + log.G(ctx).WithError(err).Warnf("failed to delete task %v", id) } } var delOpts []containerd.DeleteOpts diff --git a/pkg/cmd/container/run_cgroup_linux.go b/pkg/cmd/container/run_cgroup_linux.go index 0bc34f1e94a..87b57035ec9 100644 --- a/pkg/cmd/container/run_cgroup_linux.go +++ b/pkg/cmd/container/run_cgroup_linux.go @@ -25,12 +25,12 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/infoutil" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" ) type customMemoryOptions struct { @@ -41,11 +41,11 @@ type customMemoryOptions struct { func generateCgroupOpts(id string, options types.ContainerCreateOptions) ([]oci.SpecOpts, error) { if options.KernelMemory != "" { - logrus.Warnf("The --kernel-memory flag is no longer supported. This flag is a noop.") + log.L.Warnf("The --kernel-memory flag is no longer supported. This flag is a noop.") } if options.Memory == "" && options.OomKillDisable { - logrus.Warn("Disabling the OOM killer on containers without setting a '-m/--memory' limit may be dangerous.") + log.L.Warn("Disabling the OOM killer on containers without setting a '-m/--memory' limit may be dangerous.") } if options.GOptions.CgroupManager == "none" { @@ -54,11 +54,11 @@ func generateCgroupOpts(id string, options types.ContainerCreateOptions) ([]oci. } if options.CPUs > 0.0 || options.Memory != "" || options.MemorySwap != "" || options.PidsLimit > 0 { - logrus.Warn(`cgroup manager is set to "none", discarding resource limit requests. ` + + log.L.Warn(`cgroup manager is set to "none", discarding resource limit requests. ` + "(Hint: enable cgroup v2 with systemd: https://rootlesscontaine.rs/getting-started/common/cgroup2/)") } if options.CgroupParent != "" { - logrus.Warnf(`cgroup manager is set to "none", ignoring cgroup parent %q`+ + log.L.Warnf(`cgroup manager is set to "none", ignoring cgroup parent %q`+ "(Hint: enable cgroup v2 with systemd: https://rootlesscontaine.rs/getting-started/common/cgroup2/)", options.CgroupParent) } return []oci.SpecOpts{oci.WithCgroup("")}, nil @@ -178,7 +178,7 @@ func generateCgroupOpts(id string, options types.ContainerCreateOptions) ([]oci. opts = append(opts, withUnified(unifieds)) if options.BlkioWeight != 0 && !infoutil.BlockIOWeight(options.GOptions.CgroupManager) { - logrus.Warn("kernel support for cgroup blkio weight missing, weight discarded") + log.L.Warn("kernel support for cgroup blkio weight missing, weight discarded") options.BlkioWeight = 0 } if options.BlkioWeight > 0 && options.BlkioWeight < 10 || options.BlkioWeight > 1000 { diff --git a/pkg/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index cb90dbf694a..5216e9c6548 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -25,6 +25,7 @@ import ( "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" "github.com/containerd/nerdctl/pkg/containerutil" @@ -33,7 +34,6 @@ import ( "github.com/containerd/nerdctl/pkg/strutil" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" ) // WithoutRunMount returns a SpecOpts that unmounts the default tmpfs on "/run" @@ -229,7 +229,7 @@ func setOOMScoreAdj(opts []oci.SpecOpts, oomScoreAdjChanged bool, oomScoreAdj in // (FIXME: find a more robust way to get the current minimum value) const minimum = 100 if oomScoreAdj < minimum { - logrus.Warnf("Limiting oom_score_adj (%d -> %d)", oomScoreAdj, minimum) + log.L.Warnf("Limiting oom_score_adj (%d -> %d)", oomScoreAdj, minimum) oomScoreAdj = minimum } } diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index 251be8ebd7e..be29aa6f164 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -35,6 +35,7 @@ import ( "github.com/containerd/containerd/oci" "github.com/containerd/containerd/pkg/userns" "github.com/containerd/continuity/fs" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/cmd/volume" "github.com/containerd/nerdctl/pkg/idgen" @@ -47,7 +48,6 @@ import ( securejoin "github.com/cyphar/filepath-securejoin" "github.com/opencontainers/image-spec/identity" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" ) // copy from https://github.com/containerd/containerd/blob/v1.6.0-rc.1/pkg/cri/opts/spec_linux.go#L129-L151 @@ -180,7 +180,7 @@ func generateMountOpts(ctx context.Context, client *containerd.Client, ensuredIm // https://github.com/containerd/containerd/commit/791e175c79930a34cfbb2048fbcaa8493fd2c86b unmounter := func(mountPath string) { if uerr := mount.Unmount(mountPath, 0); uerr != nil { - logrus.Debugf("Failed to unmount snapshot %q", tempDir) + log.G(ctx).Debugf("Failed to unmount snapshot %q", tempDir) if err == nil { err = uerr } @@ -259,7 +259,7 @@ func generateMountOpts(ctx context.Context, client *containerd.Client, ensuredIm } anonVolName := idgen.GenerateID() - logrus.Debugf("creating anonymous volume %q, for \"VOLUME %s\"", + log.G(ctx).Debugf("creating anonymous volume %q, for \"VOLUME %s\"", anonVolName, imgVolRaw) anonVol, err := volStore.Create(anonVolName, []string{}) if err != nil { @@ -354,7 +354,7 @@ func copyExistingContents(source, destination string) error { return err } if len(dstList) != 0 { - logrus.Debugf("volume at %q is not initially empty, skipping copying", destination) + log.L.Debugf("volume at %q is not initially empty, skipping copying", destination) return nil } return fs.CopyDir(destination, source) diff --git a/pkg/cmd/container/run_runtime.go b/pkg/cmd/container/run_runtime.go index 20a121d5dad..279a10be629 100644 --- a/pkg/cmd/container/run_runtime.go +++ b/pkg/cmd/container/run_runtime.go @@ -25,8 +25,8 @@ import ( "github.com/containerd/containerd/oci" "github.com/containerd/containerd/plugin" runcoptions "github.com/containerd/containerd/runtime/v2/runc/options" + "github.com/containerd/log" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" ) func generateRuntimeCOpts(cgroupManager, runtimeStr string) ([]containerd.NewContainerOpts, error) { @@ -43,7 +43,7 @@ func generateRuntimeCOpts(cgroupManager, runtimeStr string) ([]containerd.NewCon runtime = runtimeStr if !strings.HasPrefix(runtimeStr, "io.containerd.runc.") { if cgroupManager == "systemd" { - logrus.Warnf("cannot set cgroup manager to %q for runtime %q", cgroupManager, runtimeStr) + log.L.Warnf("cannot set cgroup manager to %q for runtime %q", cgroupManager, runtimeStr) } runtimeOpts = nil } diff --git a/pkg/cmd/container/run_security_linux.go b/pkg/cmd/container/run_security_linux.go index 66f241e966c..2e1b0d19e74 100644 --- a/pkg/cmd/container/run_security_linux.go +++ b/pkg/cmd/container/run_security_linux.go @@ -25,11 +25,11 @@ import ( "github.com/containerd/containerd/contrib/seccomp" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/pkg/cap" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/apparmorutil" "github.com/containerd/nerdctl/pkg/defaults" "github.com/containerd/nerdctl/pkg/maputil" "github.com/containerd/nerdctl/pkg/strutil" - "github.com/sirupsen/logrus" ) var privilegedOpts = []oci.SpecOpts{ @@ -49,7 +49,7 @@ func generateSecurityOpts(privileged bool, securityOptsMap map[string]string) ([ switch k { case "seccomp", "apparmor", "no-new-privileges", "privileged-without-host-devices": default: - logrus.Warnf("unknown security-opt: %q", k) + log.L.Warnf("unknown security-opt: %q", k) } } var opts []oci.SpecOpts @@ -73,7 +73,7 @@ func generateSecurityOpts(privileged bool, securityOptsMap map[string]string) ([ } if aaProfile != "unconfined" { if !canApplyExistingProfile { - logrus.Warnf("the host does not support AppArmor. Ignoring profile %q", aaProfile) + log.L.Warnf("the host does not support AppArmor. Ignoring profile %q", aaProfile) } else { opts = append(opts, apparmor.WithProfile(aaProfile)) } @@ -127,7 +127,7 @@ func canonicalizeCapName(s string) string { s = "CAP_" + s } if !isKnownCapName(s) { - logrus.Warnf("unknown capability name %q", s) + log.L.Warnf("unknown capability name %q", s) // Not a fatal error, because runtime might be aware of this cap } return s diff --git a/pkg/cmd/container/stats.go b/pkg/cmd/container/stats.go index 7b916c1a7db..64811db4c72 100644 --- a/pkg/cmd/container/stats.go +++ b/pkg/cmd/container/stats.go @@ -31,6 +31,7 @@ import ( eventstypes "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/events" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/containerinspector" @@ -42,7 +43,6 @@ import ( "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/statsutil" "github.com/containerd/typeurl/v2" - "github.com/sirupsen/logrus" ) type stats struct { @@ -325,7 +325,7 @@ func Stats(ctx context.Context, client *containerd.Client, containerIds []string } func collect(ctx context.Context, globalOptions types.GlobalCommandOptions, s *statsutil.Stats, waitFirst *sync.WaitGroup, id string, noStream bool) { - logrus.Debugf("collecting stats for %s", s.Container) + log.G(ctx).Debugf("collecting stats for %s", s.Container) var ( getFirst = true u = make(chan error, 1) diff --git a/pkg/cmd/image/convert.go b/pkg/cmd/image/convert.go index 995bb102e52..64007060033 100644 --- a/pkg/cmd/image/convert.go +++ b/pkg/cmd/image/convert.go @@ -31,6 +31,7 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/images/converter/uncompress" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" converterutil "github.com/containerd/nerdctl/pkg/imgutil/converter" @@ -44,7 +45,6 @@ import ( "github.com/containerd/stargz-snapshotter/recorder" "github.com/klauspost/compress/zstd" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" ) func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRawRef string, options types.ImageConvertOptions) error { @@ -163,9 +163,9 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa } if !options.Oci { if nydus || overlaybd { - logrus.Warnf("option --%s should be used in conjunction with --oci, forcibly enabling on oci mediatype for %s conversion", convertType, convertType) + log.G(ctx).Warnf("option --%s should be used in conjunction with --oci, forcibly enabling on oci mediatype for %s conversion", convertType, convertType) } else { - logrus.Warnf("option --%s should be used in conjunction with --oci", convertType) + log.G(ctx).Warnf("option --%s should be used in conjunction with --oci", convertType) } } if options.Uncompress { @@ -254,7 +254,7 @@ func getESGZConvertOpts(options types.ImageConvertOptions) ([]estargz.Option, er return nil, fmt.Errorf("estargz-record-in requires experimental mode to be enabled") } - logrus.Warn("--estargz-record-in flag is experimental and subject to change") + log.L.Warn("--estargz-record-in flag is experimental and subject to change") paths, err := readPathsFromRecordFile(options.EstargzRecordIn) if err != nil { return nil, err @@ -281,7 +281,7 @@ func getZstdchunkedConverter(options types.ImageConvertOptions) (converter.Conve return nil, fmt.Errorf("zstdchunked-record-in requires experimental mode to be enabled") } - logrus.Warn("--zstdchunked-record-in flag is experimental and subject to change") + log.L.Warn("--zstdchunked-record-in flag is experimental and subject to change") paths, err := readPathsFromRecordFile(options.ZstdChunkedRecordIn) if err != nil { return nil, err @@ -356,14 +356,14 @@ func printConvertedImage(stdout io.Writer, options types.ImageConvertOptions, im for i, e := range img.ExtraImages { elems := strings.SplitN(e, "@", 2) if len(elems) < 2 { - logrus.Errorf("extra reference %q doesn't contain digest", e) + log.L.Errorf("extra reference %q doesn't contain digest", e) } else { - logrus.Infof("Extra image(%d) %s", i, elems[0]) + log.L.Infof("Extra image(%d) %s", i, elems[0]) } } elems := strings.SplitN(img.Image, "@", 2) if len(elems) < 2 { - logrus.Errorf("reference %q doesn't contain digest", img.Image) + log.L.Errorf("reference %q doesn't contain digest", img.Image) } else { fmt.Fprintln(stdout, elems[1]) } diff --git a/pkg/cmd/image/inspect.go b/pkg/cmd/image/inspect.go index 16cd258e02a..fcaa46d2f38 100644 --- a/pkg/cmd/image/inspect.go +++ b/pkg/cmd/image/inspect.go @@ -22,12 +22,12 @@ import ( "time" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/pkg/imageinspector" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/sirupsen/logrus" ) // Inspect prints detailed information of each image in `images`. @@ -64,7 +64,7 @@ func Inspect(ctx context.Context, client *containerd.Client, images []string, op err := walker.WalkAll(ctx, images, true) if len(f.entries) > 0 { if formatErr := formatter.FormatSlice(options.Format, options.Stdout, f.entries); formatErr != nil { - logrus.Error(formatErr) + log.G(ctx).Error(formatErr) } } return err diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 5bd0a117005..9a4f927e2f0 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -34,11 +34,11 @@ import ( "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" v1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" ) // ListCommandHandler `List` and print images matching filters in `options`. @@ -174,7 +174,7 @@ func printImages(ctx context.Context, client *containerd.Client, imageList []ima for _, img := range imageList { if err := printer.printImage(ctx, img); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) } } if f, ok := w.(formatter.Flusher); ok { @@ -195,7 +195,7 @@ type imagePrinter struct { func (x *imagePrinter) printImage(ctx context.Context, img images.Image) error { ociPlatforms, err := images.Platforms(ctx, x.contentStore, img.Target) if err != nil { - logrus.WithError(err).Warnf("failed to get the platform list of image %q", img.Name) + log.G(ctx).WithError(err).Warnf("failed to get the platform list of image %q", img.Name) return x.printImageSinglePlatform(ctx, img, platforms.DefaultSpec()) } psm := map[string]struct{}{} @@ -206,7 +206,7 @@ func (x *imagePrinter) printImage(ctx context.Context, img images.Image) error { } psm[platformKey] = struct{}{} if err := x.printImageSinglePlatform(ctx, img, ociPlatform); err != nil { - logrus.WithError(err).Warnf("failed to get platform %q of image %q", platforms.Format(ociPlatform), img.Name) + log.G(ctx).WithError(err).Warnf("failed to get platform %q of image %q", platforms.Format(ociPlatform), img.Name) } } return nil @@ -223,14 +223,14 @@ func makePlatformKey(platform v1.Platform) string { func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images.Image, ociPlatform v1.Platform) error { platMC := platforms.OnlyStrict(ociPlatform) if avail, _, _, _, availErr := images.Check(ctx, x.contentStore, img.Target, platMC); !avail { - logrus.WithError(availErr).Debugf("skipping printing image %q for platform %q", img.Name, platforms.Format(ociPlatform)) + log.G(ctx).WithError(availErr).Debugf("skipping printing image %q for platform %q", img.Name, platforms.Format(ociPlatform)) return nil } image := containerd.NewImageWithPlatform(x.client, img, platMC) desc, err := image.Config(ctx) if err != nil { - logrus.WithError(err).Warnf("failed to get config of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) + log.G(ctx).WithError(err).Warnf("failed to get config of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) } var ( repository string @@ -243,13 +243,13 @@ func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images. blobSize, err := image.Size(ctx) if err != nil { - logrus.WithError(err).Warnf("failed to get blob size of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) + log.G(ctx).WithError(err).Warnf("failed to get blob size of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) } size, err := imgutil.UnpackedImageSize(ctx, x.snapshotter, image) if err != nil { // Warnf is too verbose: https://github.com/containerd/nerdctl/issues/2058 - logrus.WithError(err).Debugf("failed to get unpacked size of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) + log.G(ctx).WithError(err).Debugf("failed to get unpacked size of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) } p := imagePrintable{ diff --git a/pkg/cmd/image/prune.go b/pkg/cmd/image/prune.go index 32733153508..abcee6bd86a 100644 --- a/pkg/cmd/image/prune.go +++ b/pkg/cmd/image/prune.go @@ -23,10 +23,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/opencontainers/go-digest" - "github.com/sirupsen/logrus" ) // Prune will remove all dangling images. If all is specified, will also remove all images not referenced by any container. @@ -70,10 +70,10 @@ func Prune(ctx context.Context, client *containerd.Client, options types.ImagePr for _, image := range filteredImages { digests, err := image.RootFS(ctx, contentStore, platforms.DefaultStrict()) if err != nil { - logrus.WithError(err).Warnf("failed to enumerate rootfs") + log.G(ctx).WithError(err).Warnf("failed to enumerate rootfs") } if err := imageStore.Delete(ctx, image.Name, delOpts...); err != nil { - logrus.WithError(err).Warnf("failed to delete image %s", image.Name) + log.G(ctx).WithError(err).Warnf("failed to delete image %s", image.Name) continue } removedImages[image.Name] = digests diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index 0f49b2ad229..64c3b6cc7c8 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -32,6 +32,7 @@ import ( "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" dockerconfig "github.com/containerd/containerd/remotes/docker/config" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/errutil" "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" @@ -46,7 +47,6 @@ import ( estargzconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" ) // Push pushes an image specified by `rawRef`. @@ -55,7 +55,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options if scheme != "ipfs" { return fmt.Errorf("ipfs scheme is only supported but got %q", scheme) } - logrus.Infof("pushing image %q to IPFS", ref) + log.G(ctx).Infof("pushing image %q to IPFS", ref) var ipfsPath string if options.IpfsAddress != "" { @@ -76,7 +76,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options } c, err := ipfs.Push(ctx, client, ref, layerConvert, options.AllPlatforms, options.Platforms, options.IpfsEnsureImage, ipfsPath) if err != nil { - logrus.WithError(err).Warnf("ipfs push failed") + log.G(ctx).WithError(err).Warnf("ipfs push failed") return err } fmt.Fprintln(options.Stdout, c) @@ -107,7 +107,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options return fmt.Errorf("failed to create a tmp reduced-platform image %q (platform=%v): %w", pushRef, options.Platforms, err) } defer client.ImageService().Delete(ctx, platImg.Name, images.SynchronousDelete()) - logrus.Infof("pushing as a reduced-platform image (%s, %s)", platImg.Target.MediaType, platImg.Target.Digest) + log.G(ctx).Infof("pushing as a reduced-platform image (%s, %s)", platImg.Target.MediaType, platImg.Target.Digest) } if options.Estargz { @@ -117,7 +117,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options return fmt.Errorf("failed to convert to eStargz: %v", err) } defer client.ImageService().Delete(ctx, esgzImg.Name, images.SynchronousDelete()) - logrus.Infof("pushing as an eStargz image (%s, %s)", esgzImg.Target.MediaType, esgzImg.Target.Digest) + log.G(ctx).Infof("pushing as an eStargz image (%s, %s)", esgzImg.Target.MediaType, esgzImg.Target.Digest) } // In order to push images where most layers are the same but the @@ -133,7 +133,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options var dOpts []dockerconfigresolver.Opt if options.GOptions.InsecureRegistry { - logrus.Warnf("skipping verifying HTTPS certs for %q", refDomain) + log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain) dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) } dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(options.GOptions.HostsDir)) @@ -155,7 +155,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options return err } if options.GOptions.InsecureRegistry { - logrus.WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", refDomain) + log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", refDomain) dOpts = append(dOpts, dockerconfigresolver.WithPlainHTTP(true)) resolver, err = dockerconfigresolver.New(ctx, refDomain, dOpts...) if err != nil { @@ -163,8 +163,8 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options } return pushFunc(resolver) } - logrus.WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain) - logrus.Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)") + log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain) + log.G(ctx).Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)") return err } @@ -200,14 +200,14 @@ func eStargzConvertFunc() converter.ConvertFunc { convertToESGZ := estargzconvert.LayerConvertFunc() return func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) { if isReusableESGZ(ctx, cs, desc) { - logrus.Infof("reusing estargz %s without conversion", desc.Digest) + log.L.Infof("reusing estargz %s without conversion", desc.Digest) return nil, nil } newDesc, err := convertToESGZ(ctx, cs, desc) if err != nil { return nil, err } - logrus.Infof("converted %q to %s", desc.MediaType, newDesc.Digest) + log.L.Infof("converted %q to %s", desc.MediaType, newDesc.Digest) return newDesc, err } diff --git a/pkg/cmd/image/remove.go b/pkg/cmd/image/remove.go index f2aab2058e4..0e0c20d8a60 100644 --- a/pkg/cmd/image/remove.go +++ b/pkg/cmd/image/remove.go @@ -25,10 +25,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/containerutil" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" - "github.com/sirupsen/logrus" ) // Remove removes a list of `images`. @@ -78,7 +78,7 @@ func Remove(ctx context.Context, client *containerd.Client, args []string, optio // digests is used only for emulating human-readable output of `docker rmi` digests, err := found.Image.RootFS(ctx, cs, platforms.DefaultStrict()) if err != nil { - logrus.WithError(err).Warning("failed to enumerate rootfs") + log.G(ctx).WithError(err).Warning("failed to enumerate rootfs") } if err := is.Delete(ctx, found.Image.Name, delOpts...); err != nil { @@ -112,7 +112,7 @@ func Remove(ctx context.Context, client *containerd.Client, args []string, optio if !options.Force || fatalErr { return errors.New(msg) } - logrus.Error(msg) + log.G(ctx).Error(msg) } return nil } diff --git a/pkg/cmd/ipfs/registry_serve.go b/pkg/cmd/ipfs/registry_serve.go index 09d214a4633..ede278f115e 100644 --- a/pkg/cmd/ipfs/registry_serve.go +++ b/pkg/cmd/ipfs/registry_serve.go @@ -21,9 +21,9 @@ import ( "os" "path/filepath" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/ipfs" - "github.com/sirupsen/logrus" ) func RegistryServe(options types.IPFSRegistryServeOptions) error { @@ -47,7 +47,7 @@ func RegistryServe(options types.IPFSRegistryServeOptions) error { if err != nil { return err } - logrus.Infof("serving on %v", options.ListenRegistry) + log.L.Infof("serving on %v", options.ListenRegistry) http.Handle("/", h) return http.ListenAndServe(options.ListenRegistry, nil) } diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 5bc8ce7389f..385a9609f44 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -29,6 +29,7 @@ import ( "github.com/containerd/containerd/remotes/docker" "github.com/containerd/containerd/remotes/docker/config" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/errutil" "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" @@ -36,7 +37,6 @@ import ( dockercliconfigtypes "github.com/docker/cli/cli/config/types" "github.com/docker/docker/api/types/registry" "github.com/docker/docker/errdefs" - "github.com/sirupsen/logrus" "golang.org/x/net/context/ctxhttp" "golang.org/x/term" ) @@ -148,7 +148,7 @@ func loginClientSide(ctx context.Context, globalOptions types.GlobalCommandOptio } var dOpts []dockerconfigresolver.Opt if globalOptions.InsecureRegistry { - logrus.Warnf("skipping verifying HTTPS certs for %q", host) + log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", host) dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) } dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(globalOptions.HostsDir)) @@ -158,7 +158,7 @@ func loginClientSide(ctx context.Context, globalOptions types.GlobalCommandOptio if auth.RegistryToken != "" { // Even containerd/CRI does not support RegistryToken as of v1.4.3, // so, nobody is actually using RegistryToken? - logrus.Warnf("RegistryToken (for %q) is not supported yet (FIXME)", host) + log.G(ctx).Warnf("RegistryToken (for %q) is not supported yet (FIXME)", host) } return auth.Username, auth.Password, nil } @@ -180,7 +180,7 @@ func loginClientSide(ctx context.Context, globalOptions types.GlobalCommandOptio if err != nil { return "", err } - logrus.Debugf("len(regHosts)=%d", len(regHosts)) + log.G(ctx).Debugf("len(regHosts)=%d", len(regHosts)) if len(regHosts) == 0 { return "", fmt.Errorf("got empty []docker.RegistryHost for %q", host) } @@ -194,7 +194,7 @@ func loginClientSide(ctx context.Context, globalOptions types.GlobalCommandOptio if err == nil { return identityToken, nil } - logrus.WithError(err).WithField("i", i).Error("failed to call tryLoginWithRegHost") + log.G(ctx).WithError(err).WithField("i", i).Error("failed to call tryLoginWithRegHost") } return "", err } diff --git a/pkg/cmd/network/inspect.go b/pkg/cmd/network/inspect.go index eb226ac1ec4..39c5ffc1aed 100644 --- a/pkg/cmd/network/inspect.go +++ b/pkg/cmd/network/inspect.go @@ -21,13 +21,13 @@ import ( "encoding/json" "fmt" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/idutil/netwalker" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/containerd/nerdctl/pkg/netutil" - "github.com/sirupsen/logrus" ) func Inspect(ctx context.Context, options types.NetworkInspectOptions) error { @@ -72,7 +72,7 @@ func Inspect(ctx context.Context, options types.NetworkInspectOptions) error { err = walker.WalkAll(ctx, options.Networks, true, false) if len(result) > 0 { if formatErr := formatter.FormatSlice(options.Format, options.Stdout, result); formatErr != nil { - logrus.Error(formatErr) + log.G(ctx).Error(formatErr) } } return err diff --git a/pkg/cmd/network/prune.go b/pkg/cmd/network/prune.go index 84b59a8776c..645e6d2362a 100644 --- a/pkg/cmd/network/prune.go +++ b/pkg/cmd/network/prune.go @@ -21,10 +21,10 @@ import ( "fmt" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/netutil" "github.com/containerd/nerdctl/pkg/strutil" - "github.com/sirupsen/logrus" ) func Prune(ctx context.Context, client *containerd.Client, options types.NetworkPruneOptions) error { @@ -55,7 +55,7 @@ func Prune(ctx context.Context, client *containerd.Client, options types.Network continue } if err := e.RemoveNetwork(net); err != nil { - logrus.WithError(err).Errorf("failed to remove network %s", net.Name) + log.G(ctx).WithError(err).Errorf("failed to remove network %s", net.Name) continue } removedNetworks = append(removedNetworks, net.Name) diff --git a/pkg/cmd/system/info.go b/pkg/cmd/system/info.go index d7d1cecc2d0..fb42ffd54d9 100644 --- a/pkg/cmd/system/info.go +++ b/pkg/cmd/system/info.go @@ -25,6 +25,7 @@ import ( "text/template" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -37,7 +38,6 @@ import ( "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/strutil" "github.com/docker/go-units" - "github.com/sirupsen/logrus" ) func Info(ctx context.Context, client *containerd.Client, options types.SystemInfoOptions) error { @@ -162,12 +162,12 @@ func prettyPrintInfoDockerCompat(stdout io.Writer, stderr io.Writer, info *docke for _, s := range info.SecurityOptions { m, err := strutil.ParseCSVMap(s) if err != nil { - logrus.WithError(err).Warnf("unparsable security option %q", s) + log.L.WithError(err).Warnf("unparsable security option %q", s) continue } name := m["name"] if name == "" { - logrus.Warnf("unparsable security option %q", s) + log.L.Warnf("unparsable security option %q", s) continue } fmt.Fprintf(w, " %s\n", name) diff --git a/pkg/cmd/volume/list.go b/pkg/cmd/volume/list.go index 9de1a62efcd..b10ad9d3cca 100644 --- a/pkg/cmd/volume/list.go +++ b/pkg/cmd/volume/list.go @@ -26,10 +26,10 @@ import ( "text/template" "github.com/containerd/containerd/pkg/progress" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/sirupsen/logrus" ) type volumePrintable struct { @@ -44,16 +44,16 @@ type volumePrintable struct { func List(options types.VolumeListOptions) error { if options.Quiet && options.Size { - logrus.Warn("cannot use --size and --quiet together, ignoring --size") + log.L.Warn("cannot use --size and --quiet together, ignoring --size") options.Size = false } sizeFilter := hasSizeFilter(options.Filters) if sizeFilter && options.Quiet { - logrus.Warn("cannot use --filter=size and --quiet together, ignoring --filter=size") + log.L.Warn("cannot use --filter=size and --quiet together, ignoring --filter=size") options.Filters = removeSizeFilters(options.Filters) } if sizeFilter && !options.Size { - logrus.Warn("should use --filter=size and --size together") + log.L.Warn("should use --filter=size and --size together") options.Size = true } diff --git a/pkg/composer/build.go b/pkg/composer/build.go index d389c358157..1fe7b72837c 100644 --- a/pkg/composer/build.go +++ b/pkg/composer/build.go @@ -22,9 +22,8 @@ import ( "os" "github.com/compose-spec/compose-go/types" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" - - "github.com/sirupsen/logrus" ) type BuildOptions struct { @@ -47,7 +46,7 @@ func (c *Composer) Build(ctx context.Context, bo BuildOptions, services []string } func (c *Composer) buildServiceImage(ctx context.Context, image string, b *serviceparser.Build, platform string, bo BuildOptions) error { - logrus.Infof("Building image %s", image) + log.G(ctx).Infof("Building image %s", image) var args []string // nolint: prealloc if platform != "" { @@ -66,7 +65,7 @@ func (c *Composer) buildServiceImage(ctx context.Context, image string, b *servi cmd := c.createNerdctlCmd(ctx, append([]string{"build"}, args...)...) if c.DebugPrintFull { - logrus.Debugf("Running %v", cmd.Args) + log.G(ctx).Debugf("Running %v", cmd.Args) } cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/pkg/composer/composer.go b/pkg/composer/composer.go index 67a533dc2ac..2c5bd4d2e8c 100644 --- a/pkg/composer/composer.go +++ b/pkg/composer/composer.go @@ -27,9 +27,9 @@ import ( compose "github.com/compose-spec/compose-go/types" "github.com/containerd/containerd" "github.com/containerd/containerd/identifiers" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" "github.com/containerd/nerdctl/pkg/reflectutil" - "github.com/sirupsen/logrus" ) // Options groups the command line options recommended for a Compose implementation (ProjectOptions) and extra options for nerdctl @@ -103,8 +103,8 @@ func New(o Options, client *containerd.Client) (*Composer, error) { if o.DebugPrintFull { projectJSON, _ := json.MarshalIndent(project, "", " ") - logrus.Debug("printing project JSON") - logrus.Debugf("%s", projectJSON) + log.L.Debug("printing project JSON") + log.L.Debugf("%s", projectJSON) } if unknown := reflectutil.UnknownNonEmptyFields(project, @@ -117,7 +117,7 @@ func New(o Options, client *containerd.Client) (*Composer, error) { "Secrets", "Configs", "ComposeFiles"); len(unknown) > 0 { - logrus.Warnf("Ignoring: %+v", unknown) + log.L.Warnf("Ignoring: %+v", unknown) } c := &Composer{ @@ -142,7 +142,7 @@ func (c *Composer) createNerdctlCmd(ctx context.Context, args ...string) *exec.C func (c *Composer) runNerdctlCmd(ctx context.Context, args ...string) error { cmd := c.createNerdctlCmd(ctx, args...) if c.DebugPrintFull { - logrus.Debugf("Running %v", cmd.Args) + log.G(ctx).Debugf("Running %v", cmd.Args) } if out, err := cmd.CombinedOutput(); err != nil { return fmt.Errorf("error while executing %v: %q: %w", cmd.Args, string(out), err) diff --git a/pkg/composer/container.go b/pkg/composer/container.go index 3e5f94e9c6d..33b4b699775 100644 --- a/pkg/composer/container.go +++ b/pkg/composer/container.go @@ -21,8 +21,8 @@ import ( "fmt" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/labels" - "github.com/sirupsen/logrus" ) func (c *Composer) Containers(ctx context.Context, services ...string) ([]containerd.Container, error) { @@ -34,7 +34,7 @@ func (c *Composer) Containers(ctx context.Context, services ...string) ([]contai if len(services) == 0 { filters = append(filters, projectLabel) } - logrus.Debugf("filters: %v", filters) + log.G(ctx).Debugf("filters: %v", filters) containers, err := c.client.Containers(ctx, filters...) if err != nil { return nil, err diff --git a/pkg/composer/copy.go b/pkg/composer/copy.go index 837427f523c..76caeead512 100644 --- a/pkg/composer/copy.go +++ b/pkg/composer/copy.go @@ -23,9 +23,9 @@ import ( "strings" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/labels" "github.com/docker/docker/pkg/system" - "github.com/sirupsen/logrus" ) type CopyOptions struct { @@ -110,7 +110,7 @@ func (c *Composer) logCopyMsg(ctx context.Context, container containerd.Containe if direction == toService { msg = msg + fmt.Sprintf("copy %s to %s:%s", srcPath, containerName, dstPath) } - logrus.Info(msg) + log.G(ctx).Info(msg) return nil } diff --git a/pkg/composer/create.go b/pkg/composer/create.go index 7d8773b33d7..7a62f24fa1e 100644 --- a/pkg/composer/create.go +++ b/pkg/composer/create.go @@ -24,9 +24,9 @@ import ( "strings" "github.com/compose-spec/compose-go/types" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" "github.com/containerd/nerdctl/pkg/labels" - "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" ) @@ -163,18 +163,18 @@ func (c *Composer) createServiceContainer(ctx context.Context, service *servicep // delete container if it already exists and force-recreate is enabled if exists { if recreate != RecreateForce { - logrus.Infof("Container %s exists, skipping", container.Name) + log.G(ctx).Infof("Container %s exists, skipping", container.Name) return "", nil } - logrus.Debugf("Container %q already exists and force-created is enabled, deleting", container.Name) + log.G(ctx).Debugf("Container %q already exists and force-created is enabled, deleting", container.Name) delCmd := c.createNerdctlCmd(ctx, "rm", "-f", container.Name) if err = delCmd.Run(); err != nil { return "", fmt.Errorf("could not delete container %q: %s", container.Name, err) } - logrus.Infof("Re-creating container %s", container.Name) + log.G(ctx).Infof("Re-creating container %s", container.Name) } else { - logrus.Infof("Creating container %s", container.Name) + log.G(ctx).Infof("Creating container %s", container.Name) } tempDir, err := os.MkdirTemp(os.TempDir(), "compose-") @@ -193,7 +193,7 @@ func (c *Composer) createServiceContainer(ctx context.Context, service *servicep cmd := c.createNerdctlCmd(ctx, append([]string{"create"}, container.RunArgs...)...) if c.DebugPrintFull { - logrus.Debugf("Running %v", cmd.Args) + log.G(ctx).Debugf("Running %v", cmd.Args) } // FIXME diff --git a/pkg/composer/down.go b/pkg/composer/down.go index 9a7a7cc33b7..2b40e5d9073 100644 --- a/pkg/composer/down.go +++ b/pkg/composer/down.go @@ -20,9 +20,8 @@ import ( "context" "fmt" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/strutil" - - "github.com/sirupsen/logrus" ) type DownOptions struct { @@ -61,7 +60,7 @@ func (c *Composer) Down(ctx context.Context, downOptions DownOptions) error { return fmt.Errorf("error removeing orphaned containers: %s", err) } } else { - logrus.Warnf("found %d orphaned containers: %v, you can run this command with the --remove-orphans flag to clean it up", len(orphans), orphans) + log.G(ctx).Warnf("found %d orphaned containers: %v, you can run this command with the --remove-orphans flag to clean it up", len(orphans), orphans) } } @@ -105,9 +104,9 @@ func (c *Composer) downNetwork(ctx context.Context, shortName string) error { return fmt.Errorf("network %s is in use", fullName) } - logrus.Infof("Removing network %s", fullName) + log.G(ctx).Infof("Removing network %s", fullName) if err := c.runNerdctlCmd(ctx, "network", "rm", fullName); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) } } return nil @@ -128,9 +127,9 @@ func (c *Composer) downVolume(ctx context.Context, shortName string) error { if err != nil { return err } else if volExists { - logrus.Infof("Removing volume %s", fullName) + log.G(ctx).Infof("Removing volume %s", fullName) if err := c.runNerdctlCmd(ctx, "volume", "rm", "-f", fullName); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) } } return nil diff --git a/pkg/composer/exec.go b/pkg/composer/exec.go index 7b267365e18..965287c8008 100644 --- a/pkg/composer/exec.go +++ b/pkg/composer/exec.go @@ -22,7 +22,7 @@ import ( "os" "github.com/containerd/containerd" - "github.com/sirupsen/logrus" + "github.com/containerd/log" ) // ExecOptions stores options passed from users as flags and args. @@ -90,7 +90,7 @@ func (c *Composer) exec(ctx context.Context, container containerd.Container, eo } if c.DebugPrintFull { - logrus.Debugf("Executing %v", cmd.Args) + log.G(ctx).Debugf("Executing %v", cmd.Args) } return cmd.Run() } diff --git a/pkg/composer/kill.go b/pkg/composer/kill.go index fc63a751d4f..04b14a870c0 100644 --- a/pkg/composer/kill.go +++ b/pkg/composer/kill.go @@ -19,7 +19,7 @@ package composer import ( "context" - "github.com/sirupsen/logrus" + "github.com/containerd/log" "golang.org/x/sync/errgroup" ) @@ -42,7 +42,7 @@ func (c *Composer) Kill(ctx context.Context, opts KillOptions, services []string eg.Go(func() error { args := []string{"kill", "-s", opts.Signal, container.ID()} if err := c.runNerdctlCmd(ctx, args...); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) return err } return nil diff --git a/pkg/composer/logs.go b/pkg/composer/logs.go index 23e4ee94e7c..c6109bdb2fb 100644 --- a/pkg/composer/logs.go +++ b/pkg/composer/logs.go @@ -25,11 +25,10 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/pipetagger" "github.com/containerd/nerdctl/pkg/composer/serviceparser" "github.com/containerd/nerdctl/pkg/labels" - - "github.com/sirupsen/logrus" ) type LogsOptions struct { @@ -117,7 +116,7 @@ func (c *Composer) logs(ctx context.Context, containers []containerd.Container, } stderrTagger := pipetagger.New(os.Stderr, stderr, state.logTag, logWidth, lo.NoColor) if c.DebugPrintFull { - logrus.Debugf("Running %v", state.logCmd.Args) + log.G(ctx).Debugf("Running %v", state.logCmd.Args) } if err := state.logCmd.Start(); err != nil { return err @@ -139,21 +138,21 @@ selectLoop: // Wait for Ctrl-C, or `nerdctl compose down` in another terminal select { case sig := <-interruptChan: - logrus.Debugf("Received signal: %s", sig) + log.G(ctx).Debugf("Received signal: %s", sig) break selectLoop case containerName := <-logsEOFChan: if lo.Follow { // When `nerdctl logs -f` has exited, we can assume that the container has exited - logrus.Infof("Container %q exited", containerName) + log.G(ctx).Infof("Container %q exited", containerName) } else { - logrus.Debugf("Logs for container %q reached EOF", containerName) + log.G(ctx).Debugf("Logs for container %q reached EOF", containerName) } logsEOFMap[containerName] = struct{}{} if len(logsEOFMap) == len(containerStates) { if lo.Follow { - logrus.Info("All the containers have exited") + log.G(ctx).Info("All the containers have exited") } else { - logrus.Debug("All the logs reached EOF") + log.G(ctx).Debug("All the logs reached EOF") } break selectLoop } @@ -163,7 +162,7 @@ selectLoop: for _, state := range containerStates { if state.logCmd != nil && state.logCmd.Process != nil { if err := state.logCmd.Process.Kill(); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) } } } diff --git a/pkg/composer/pull.go b/pkg/composer/pull.go index 59bb50a3cc9..62e5c683178 100644 --- a/pkg/composer/pull.go +++ b/pkg/composer/pull.go @@ -22,9 +22,8 @@ import ( "os" "github.com/compose-spec/compose-go/types" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" - - "github.com/sirupsen/logrus" ) type PullOptions struct { @@ -42,7 +41,7 @@ func (c *Composer) Pull(ctx context.Context, po PullOptions, services []string) } func (c *Composer) pullServiceImage(ctx context.Context, image string, platform string, ps *serviceparser.Service, po PullOptions) error { - logrus.Infof("Pulling image %s", image) + log.G(ctx).Infof("Pulling image %s", image) var args []string // nolint: prealloc if platform != "" { @@ -78,7 +77,7 @@ func (c *Composer) pullServiceImage(ctx context.Context, image string, platform cmd := c.createNerdctlCmd(ctx, append([]string{"pull"}, args...)...) if c.DebugPrintFull { - logrus.Debugf("Running %v", cmd.Args) + log.G(ctx).Debugf("Running %v", cmd.Args) } cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout diff --git a/pkg/composer/push.go b/pkg/composer/push.go index ae8c6854e59..eabec25db97 100644 --- a/pkg/composer/push.go +++ b/pkg/composer/push.go @@ -22,9 +22,8 @@ import ( "os" "github.com/compose-spec/compose-go/types" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" - - "github.com/sirupsen/logrus" ) type PushOptions struct { @@ -41,7 +40,7 @@ func (c *Composer) Push(ctx context.Context, po PushOptions, services []string) } func (c *Composer) pushServiceImage(ctx context.Context, image string, platform string, ps *serviceparser.Service, po PushOptions) error { - logrus.Infof("Pushing image %s", image) + log.G(ctx).Infof("Pushing image %s", image) var args []string // nolint: prealloc if platform != "" { @@ -61,7 +60,7 @@ func (c *Composer) pushServiceImage(ctx context.Context, image string, platform cmd := c.createNerdctlCmd(ctx, append([]string{"push"}, args...)...) if c.DebugPrintFull { - logrus.Debugf("Running %v", cmd.Args) + log.G(ctx).Debugf("Running %v", cmd.Args) } cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout diff --git a/pkg/composer/restart.go b/pkg/composer/restart.go index b711925d062..c473cf71eff 100644 --- a/pkg/composer/restart.go +++ b/pkg/composer/restart.go @@ -23,9 +23,8 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/labels" - - "github.com/sirupsen/logrus" ) // RestartOptions stores all option input from `nerdctl compose restart` @@ -61,14 +60,14 @@ func (c *Composer) restartContainers(ctx context.Context, containers []container go func() { defer rsWG.Done() info, _ := container.Info(ctx, containerd.WithoutRefreshedMetadata) - logrus.Infof("Restarting container %s", info.Labels[labels.Name]) + log.G(ctx).Infof("Restarting container %s", info.Labels[labels.Name]) args := []string{"restart"} if opt.Timeout != nil { args = append(args, timeoutArg) } args = append(args, container.ID()) if err := c.runNerdctlCmd(ctx, args...); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) } }() } diff --git a/pkg/composer/rm.go b/pkg/composer/rm.go index 1eec295f466..2ad1b798fb8 100644 --- a/pkg/composer/rm.go +++ b/pkg/composer/rm.go @@ -22,12 +22,11 @@ import ( "sync" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" "github.com/containerd/nerdctl/pkg/formatter" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/strutil" - - "github.com/sirupsen/logrus" ) // RemoveOptions stores all options when removing compose containers: @@ -80,14 +79,14 @@ func (c *Composer) removeContainers(ctx context.Context, containers []containerd if !opt.Stop { cStatus := formatter.ContainerStatus(ctx, container) if strings.HasPrefix(cStatus, "Up") { - logrus.Warnf("Removing container %s failed: container still running.", info.Labels[labels.Name]) + log.G(ctx).Warnf("Removing container %s failed: container still running.", info.Labels[labels.Name]) return } } - logrus.Infof("Removing container %s", info.Labels[labels.Name]) + log.G(ctx).Infof("Removing container %s", info.Labels[labels.Name]) if err := c.runNerdctlCmd(ctx, append(args, container.ID())...); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) } }() } @@ -104,9 +103,9 @@ func (c *Composer) removeContainersFromParsedServices(ctx context.Context, conta rmWG.Add(1) go func() { defer rmWG.Done() - logrus.Infof("Removing container %s", container.Name) + log.G(ctx).Infof("Removing container %s", container.Name) if err := c.runNerdctlCmd(ctx, "rm", "-f", id); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) } }() } diff --git a/pkg/composer/run.go b/pkg/composer/run.go index 0cdba11f8b7..5c065d7f5ef 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -24,9 +24,9 @@ import ( "github.com/compose-spec/compose-go/loader" "github.com/compose-spec/compose-go/types" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" "github.com/containerd/nerdctl/pkg/idgen" - "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" ) @@ -198,7 +198,7 @@ func (c *Composer) Run(ctx context.Context, ro RunOptions) error { return fmt.Errorf("error removing orphaned containers: %s", err) } } else { - logrus.Warnf("found %d orphaned containers: %v, you can run this command with the --remove-orphans flag to clean it up", len(orphans), orphans) + log.G(ctx).Warnf("found %d orphaned containers: %v, you can run this command with the --remove-orphans flag to clean it up", len(orphans), orphans) } } @@ -230,7 +230,7 @@ func (c *Composer) runServices(ctx context.Context, parsedServices []*servicepar services = append(services, ps.Unparsed.Name) if len(ps.Containers) != 1 { - logrus.Warnf("compose run does not support scale but %s is currently %v, automatically it will configure 1", ps.Unparsed.Name, len(ps.Containers)) + log.G(ctx).Warnf("compose run does not support scale but %s is currently %v, automatically it will configure 1", ps.Unparsed.Name, len(ps.Containers)) } if len(ps.Containers) == 0 { @@ -257,14 +257,14 @@ func (c *Composer) runServices(ctx context.Context, parsedServices []*servicepar } if ro.Detach { - logrus.Printf("%s\n", cid) + log.G(ctx).Printf("%s\n", cid) return nil } // TODO: fix it when `nerdctl logs` supports `nerdctl run` without detach // https://github.com/containerd/nerdctl/blob/v0.22.2/pkg/taskutil/taskutil.go#L55 if !ro.Interactive && !ro.Tty { - logrus.Info("Attaching to logs") + log.G(ctx).Info("Attaching to logs") lo := LogsOptions{ Follow: true, NoColor: ro.NoColor, @@ -276,7 +276,7 @@ func (c *Composer) runServices(ctx context.Context, parsedServices []*servicepar } } - logrus.Infof("Stopping containers (forcibly)") // TODO: support gracefully stopping + log.G(ctx).Infof("Stopping containers (forcibly)") // TODO: support gracefully stopping c.stopContainersFromParsedServices(ctx, containers) if ro.Rm { diff --git a/pkg/composer/serviceparser/build.go b/pkg/composer/serviceparser/build.go index e191163ddd9..6859af2e95e 100644 --- a/pkg/composer/serviceparser/build.go +++ b/pkg/composer/serviceparser/build.go @@ -25,17 +25,17 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/reflectutil" securejoin "github.com/cyphar/filepath-securejoin" - "github.com/sirupsen/logrus" ) func parseBuildConfig(c *types.BuildConfig, project *types.Project, imageName string) (*Build, error) { if unknown := reflectutil.UnknownNonEmptyFields(c, "Context", "Dockerfile", "Args", "CacheFrom", "Target", "Labels", "Secrets", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: build: %+v", unknown) + log.L.Warnf("Ignoring: build: %+v", unknown) } if c.Context == "" { @@ -50,7 +50,7 @@ func parseBuildConfig(c *types.BuildConfig, project *types.Project, imageName st b.BuildArgs = append(b.BuildArgs, "-t="+imageName) if c.Dockerfile != "" { if filepath.IsAbs(c.Dockerfile) { - logrus.Warnf("build.dockerfile should be relative path, got %q", c.Dockerfile) + log.L.Warnf("build.dockerfile should be relative path, got %q", c.Dockerfile) b.BuildArgs = append(b.BuildArgs, "-f="+c.Dockerfile) } else { // no need to use securejoin @@ -92,7 +92,7 @@ func parseBuildConfig(c *types.BuildConfig, project *types.Project, imageName st } var src string if filepath.IsAbs(projectSecret.File) { - logrus.Warnf("build.secrets should be relative path, got %q", projectSecret.File) + log.L.Warnf("build.secrets should be relative path, got %q", projectSecret.File) src = projectSecret.File } else { var err error diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index 69d22d45595..cf8c9a2d05c 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -31,9 +31,8 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/containerd/contrib/nvidia" "github.com/containerd/containerd/identifiers" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/reflectutil" - - "github.com/sirupsen/logrus" ) // ComposeExtensionKey defines fields used to implement extension features. @@ -109,14 +108,14 @@ func warnUnknownFields(svc types.ServiceConfig) { "Volumes", "Ulimits", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: service %s: %+v", svc.Name, unknown) + log.L.Warnf("Ignoring: service %s: %+v", svc.Name, unknown) } if svc.BlkioConfig != nil { if unknown := reflectutil.UnknownNonEmptyFields(svc.BlkioConfig, "Weight", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: service %s: blkio_config: %+v", svc.Name, unknown) + log.L.Warnf("Ignoring: service %s: blkio_config: %+v", svc.Name, unknown) } } @@ -124,13 +123,13 @@ func warnUnknownFields(svc types.ServiceConfig) { if unknown := reflectutil.UnknownNonEmptyFields(&dep, "Condition", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: service %s: depends_on: %s: %+v", svc.Name, depName, unknown) + log.L.Warnf("Ignoring: service %s: depends_on: %s: %+v", svc.Name, depName, unknown) } switch dep.Condition { case "", types.ServiceConditionStarted: // NOP default: - logrus.Warnf("Ignoring: service %s: depends_on: %s: condition %s", svc.Name, depName, dep.Condition) + log.L.Warnf("Ignoring: service %s: depends_on: %s: condition %s", svc.Name, depName, dep.Condition) } } @@ -140,34 +139,34 @@ func warnUnknownFields(svc types.ServiceConfig) { "RestartPolicy", "Resources", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: service %s: deploy: %+v", svc.Name, unknown) + log.L.Warnf("Ignoring: service %s: deploy: %+v", svc.Name, unknown) } if svc.Deploy.RestartPolicy != nil { if unknown := reflectutil.UnknownNonEmptyFields(svc.Deploy.RestartPolicy, "Condition", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: service %s: deploy.restart_policy: %+v", svc.Name, unknown) + log.L.Warnf("Ignoring: service %s: deploy.restart_policy: %+v", svc.Name, unknown) } } if unknown := reflectutil.UnknownNonEmptyFields(svc.Deploy.Resources, "Limits", "Reservations", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: service %s: deploy.resources: %+v", svc.Name, unknown) + log.L.Warnf("Ignoring: service %s: deploy.resources: %+v", svc.Name, unknown) } if svc.Deploy.Resources.Limits != nil { if unknown := reflectutil.UnknownNonEmptyFields(svc.Deploy.Resources.Limits, "NanoCPUs", "MemoryBytes", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: service %s: deploy.resources.resources: %+v", svc.Name, unknown) + log.L.Warnf("Ignoring: service %s: deploy.resources.resources: %+v", svc.Name, unknown) } } if svc.Deploy.Resources.Reservations != nil { if unknown := reflectutil.UnknownNonEmptyFields(svc.Deploy.Resources.Reservations, "Devices", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: service %s: deploy.resources.resources.reservations: %+v", svc.Name, unknown) + log.L.Warnf("Ignoring: service %s: deploy.resources.resources.reservations: %+v", svc.Name, unknown) } for i, dev := range svc.Deploy.Resources.Reservations.Devices { if unknown := reflectutil.UnknownNonEmptyFields(dev, @@ -176,7 +175,7 @@ func warnUnknownFields(svc types.ServiceConfig) { "Count", "IDs", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: service %s: deploy.resources.resources.reservations.devices[%d]: %+v", + log.L.Warnf("Ignoring: service %s: deploy.resources.resources.reservations.devices[%d]: %+v", svc.Name, i, unknown) } } @@ -225,13 +224,13 @@ func getReplicas(svc types.ServiceConfig) (int, error) { func getCPULimit(svc types.ServiceConfig) (string, error) { var limit string if svc.CPUS > 0 { - logrus.Warn("cpus is deprecated, use deploy.resources.limits.cpus") + log.L.Warn("cpus is deprecated, use deploy.resources.limits.cpus") limit = fmt.Sprintf("%f", svc.CPUS) } if svc.Deploy != nil && svc.Deploy.Resources.Limits != nil { if nanoCPUs := svc.Deploy.Resources.Limits.NanoCPUs; nanoCPUs != "" { if svc.CPUS > 0 { - logrus.Warnf("deploy.resources.limits.cpus and cpus (deprecated) must not be set together, ignoring cpus=%f", svc.CPUS) + log.L.Warnf("deploy.resources.limits.cpus and cpus (deprecated) must not be set together, ignoring cpus=%f", svc.CPUS) } limit = nanoCPUs } @@ -242,13 +241,13 @@ func getCPULimit(svc types.ServiceConfig) (string, error) { func getMemLimit(svc types.ServiceConfig) (types.UnitBytes, error) { var limit types.UnitBytes if svc.MemLimit > 0 { - logrus.Warn("mem_limit is deprecated, use deploy.resources.limits.memory") + log.L.Warn("mem_limit is deprecated, use deploy.resources.limits.memory") limit = svc.MemLimit } if svc.Deploy != nil && svc.Deploy.Resources.Limits != nil { if memoryBytes := svc.Deploy.Resources.Limits.MemoryBytes; memoryBytes > 0 { if svc.MemLimit > 0 && memoryBytes != svc.MemLimit { - logrus.Warnf("deploy.resources.limits.memory and mem_limit (deprecated) must not be set together, ignoring mem_limit=%d", svc.MemLimit) + log.L.Warnf("deploy.resources.limits.memory and mem_limit (deprecated) must not be set together, ignoring mem_limit=%d", svc.MemLimit) } limit = memoryBytes } @@ -327,13 +326,13 @@ func getRestart(svc types.ServiceConfig) (string, error) { if restartFailurePat.MatchString(svc.Restart) { restartFlag = svc.Restart } else { - logrus.Warnf("Ignoring: service %s: restart=%q (unknown)", svc.Name, svc.Restart) + log.L.Warnf("Ignoring: service %s: restart=%q (unknown)", svc.Name, svc.Restart) } } if svc.Deploy != nil && svc.Deploy.RestartPolicy != nil { if svc.Restart != "" { - logrus.Warnf("deploy.restart_policy and restart must not be set together, ignoring restart=%s", svc.Restart) + log.L.Warnf("deploy.restart_policy and restart must not be set together, ignoring restart=%s", svc.Restart) } switch cond := svc.Deploy.RestartPolicy.Condition; cond { case "", "any": @@ -345,9 +344,9 @@ func getRestart(svc types.ServiceConfig) (string, error) { case "no": return "", fmt.Errorf("deploy.restart_policy.condition: \"no\" is invalid, did you mean \"none\"?") case "on-failure": - logrus.Warnf("Ignoring: service %s: deploy.restart_policy.condition=%q (unimplemented)", svc.Name, cond) + log.L.Warnf("Ignoring: service %s: deploy.restart_policy.condition=%q (unimplemented)", svc.Name, cond) default: - logrus.Warnf("Ignoring: service %s: deploy.restart_policy.condition=%q (unknown)", svc.Name, cond) + log.L.Warnf("Ignoring: service %s: deploy.restart_policy.condition=%q (unknown)", svc.Name, cond) } } @@ -364,7 +363,7 @@ func getNetworks(project *types.Project, svc types.ServiceConfig) ([]networkName var fullNames []networkNamePair // nolint: prealloc if svc.Net != "" { - logrus.Warn("net is deprecated, use network_mode or networks") + log.L.Warn("net is deprecated, use network_mode or networks") if len(svc.Networks) > 0 { return nil, errors.New("networks and net must not be set together") } @@ -448,7 +447,7 @@ func Parse(project *types.Project, svc types.ServiceConfig) (*Service, error) { parsed.Build.Force = true parsed.PullMode = "never" default: - logrus.Warnf("Ignoring: service %s: pull_policy: %q", svc.Name, svc.PullPolicy) + log.L.Warnf("Ignoring: service %s: pull_policy: %q", svc.Name, svc.PullPolicy) } for i := 0; i < replicas; i++ { @@ -726,7 +725,7 @@ func servicePortConfigToFlagP(c types.ServicePortConfig) (string, error) { "Published", "Protocol", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: port: %+v", unknown) + log.L.Warnf("Ignoring: port: %+v", unknown) } switch c.Mode { case "", "ingress": @@ -759,18 +758,18 @@ func serviceVolumeConfigToFlagV(c types.ServiceVolumeConfig, project *types.Proj "Bind", "Volume", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: volume: %+v", unknown) + log.L.Warnf("Ignoring: volume: %+v", unknown) } if c.Bind != nil { // c.Bind is expected to be a non-nil reference to an empty Bind struct if unknown := reflectutil.UnknownNonEmptyFields(c.Bind, "CreateHostPath"); len(unknown) > 0 { - logrus.Warnf("Ignoring: volume: Bind: %+v", unknown) + log.L.Warnf("Ignoring: volume: Bind: %+v", unknown) } } if c.Volume != nil { // c.Volume is expected to be a non-nil reference to an empty Volume struct if unknown := reflectutil.UnknownNonEmptyFields(c.Volume); len(unknown) > 0 { - logrus.Warnf("Ignoring: volume: Volume: %+v", unknown) + log.L.Warnf("Ignoring: volume: Volume: %+v", unknown) } } @@ -829,7 +828,7 @@ func fileReferenceConfigToFlagV(c types.FileReferenceConfig, project *types.Proj if unknown := reflectutil.UnknownNonEmptyFields(&c, "Source", "Target", "UID", "GID", "Mode", ); len(unknown) > 0 { - logrus.Warnf("Ignoring: %s: %+v", objType, unknown) + log.L.Warnf("Ignoring: %s: %+v", objType, unknown) } if err := identifiers.Validate(c.Source); err != nil { diff --git a/pkg/composer/stop.go b/pkg/composer/stop.go index 863563b1d23..6df54863815 100644 --- a/pkg/composer/stop.go +++ b/pkg/composer/stop.go @@ -22,11 +22,10 @@ import ( "sync" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/strutil" - - "github.com/sirupsen/logrus" ) // StopOptions stores all option input from `nerdctl compose stop` @@ -68,14 +67,14 @@ func (c *Composer) stopContainers(ctx context.Context, containers []containerd.C go func() { defer rmWG.Done() info, _ := container.Info(ctx, containerd.WithoutRefreshedMetadata) - logrus.Infof("Stopping container %s", info.Labels[labels.Name]) + log.G(ctx).Infof("Stopping container %s", info.Labels[labels.Name]) args := []string{"stop"} if opt.Timeout != nil { args = append(args, timeoutArg) } args = append(args, container.ID()) if err := c.runNerdctlCmd(ctx, args...); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) } }() } @@ -92,9 +91,9 @@ func (c *Composer) stopContainersFromParsedServices(ctx context.Context, contain rmWG.Add(1) go func() { defer rmWG.Done() - logrus.Infof("Stopping container %s", container.Name) + log.G(ctx).Infof("Stopping container %s", container.Name) if err := c.runNerdctlCmd(ctx, "stop", id); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) } }() } diff --git a/pkg/composer/up.go b/pkg/composer/up.go index c76b305df99..3e65ba89a71 100644 --- a/pkg/composer/up.go +++ b/pkg/composer/up.go @@ -22,10 +22,9 @@ import ( "os" "github.com/compose-spec/compose-go/types" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" "github.com/containerd/nerdctl/pkg/reflectutil" - - "github.com/sirupsen/logrus" ) type UpOptions struct { @@ -98,7 +97,7 @@ func (c *Composer) Up(ctx context.Context, uo UpOptions, services []string) erro return fmt.Errorf("error removing orphaned containers: %s", err) } } else { - logrus.Warnf("found %d orphaned containers: %v, you can run this command with the --remove-orphans flag to clean it up", len(orphans), orphans) + log.G(ctx).Warnf("found %d orphaned containers: %v, you can run this command with the --remove-orphans flag to clean it up", len(orphans), orphans) } } @@ -107,7 +106,7 @@ func (c *Composer) Up(ctx context.Context, uo UpOptions, services []string) erro func validateFileObjectConfig(obj types.FileObjectConfig, shortName, objType string, project *types.Project) error { if unknown := reflectutil.UnknownNonEmptyFields(&obj, "Name", "External", "File"); len(unknown) > 0 { - logrus.Warnf("Ignoring: %s %s: %+v", objType, shortName, unknown) + log.L.Warnf("Ignoring: %s %s: %+v", objType, shortName, unknown) } if obj.External.External || obj.External.Name != "" { return fmt.Errorf("%s %q: external object is not supported", objType, shortName) diff --git a/pkg/composer/up_network.go b/pkg/composer/up_network.go index c9c76e6b7c4..32d35bb7d77 100644 --- a/pkg/composer/up_network.go +++ b/pkg/composer/up_network.go @@ -20,10 +20,9 @@ import ( "context" "fmt" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/reflectutil" - - "github.com/sirupsen/logrus" ) func (c *Composer) upNetwork(ctx context.Context, shortName string) error { @@ -37,7 +36,7 @@ func (c *Composer) upNetwork(ctx context.Context, shortName string) error { } if unknown := reflectutil.UnknownNonEmptyFields(&net, "Name", "Ipam", "Driver", "DriverOpts"); len(unknown) > 0 { - logrus.Warnf("Ignoring: network %s: %+v", shortName, unknown) + log.G(ctx).Warnf("Ignoring: network %s: %+v", shortName, unknown) } // shortName is like "default", fullName is like "compose-wordpress_default" @@ -46,7 +45,7 @@ func (c *Composer) upNetwork(ctx context.Context, shortName string) error { if err != nil { return err } else if !netExists { - logrus.Infof("Creating network %s", fullName) + log.G(ctx).Infof("Creating network %s", fullName) //add metadata labels to network https://github.com/compose-spec/compose-spec/blob/master/spec.md#labels-1 createArgs := []string{ fmt.Sprintf("--label=%s=%s", labels.ComposeProject, c.project.Name), @@ -65,12 +64,12 @@ func (c *Composer) upNetwork(ctx context.Context, shortName string) error { if net.Ipam.Config != nil { if len(net.Ipam.Config) > 1 { - logrus.Warnf("Ignoring: network %s: imam.config %+v", shortName, net.Ipam.Config[1:]) + log.G(ctx).Warnf("Ignoring: network %s: imam.config %+v", shortName, net.Ipam.Config[1:]) } ipamConfig := net.Ipam.Config[0] if unknown := reflectutil.UnknownNonEmptyFields(ipamConfig, "Subnet", "Gateway", "IPRange"); len(unknown) > 0 { - logrus.Warnf("Ignoring: network %s: ipam.config[0]: %+v", shortName, unknown) + log.G(ctx).Warnf("Ignoring: network %s: ipam.config[0]: %+v", shortName, unknown) } if ipamConfig.Subnet != "" { createArgs = append(createArgs, fmt.Sprintf("--subnet=%s", ipamConfig.Subnet)) @@ -86,7 +85,7 @@ func (c *Composer) upNetwork(ctx context.Context, shortName string) error { createArgs = append(createArgs, fullName) if c.DebugPrintFull { - logrus.Debugf("Creating network args: %s", createArgs) + log.G(ctx).Debugf("Creating network args: %s", createArgs) } if err := c.runNerdctlCmd(ctx, append([]string{"network", "create"}, createArgs...)...); err != nil { diff --git a/pkg/composer/up_service.go b/pkg/composer/up_service.go index 729befffd57..32f1e3b52a2 100644 --- a/pkg/composer/up_service.go +++ b/pkg/composer/up_service.go @@ -25,10 +25,10 @@ import ( "strings" "sync" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/composer/serviceparser" "github.com/containerd/nerdctl/pkg/labels" - "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" ) @@ -75,7 +75,7 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars return nil } - logrus.Info("Attaching to logs") + log.G(ctx).Info("Attaching to logs") lo := LogsOptions{ Follow: true, NoColor: uo.NoColor, @@ -85,7 +85,7 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars return err } - logrus.Infof("Stopping containers (forcibly)") // TODO: support gracefully stopping + log.G(ctx).Infof("Stopping containers (forcibly)") // TODO: support gracefully stopping c.stopContainersFromParsedServices(ctx, containers) return nil } @@ -102,10 +102,10 @@ func (c *Composer) ensureServiceImage(ctx context.Context, ps *serviceparser.Ser } // even when c.ImageExists returns true, we need to call c.EnsureImage // because ps.PullMode can be "always". So no return here. - logrus.Debugf("Image %s already exists, not building", ps.Image) + log.G(ctx).Debugf("Image %s already exists, not building", ps.Image) } - logrus.Infof("Ensuring image %s", ps.Image) + log.G(ctx).Infof("Ensuring image %s", ps.Image) return c.EnsureImage(ctx, ps.Image, ps.PullMode, ps.Unparsed.Platform, ps, quiet) } @@ -120,18 +120,18 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse // delete container if it already exists if exists { - logrus.Debugf("Container %q already exists, deleting", container.Name) + log.G(ctx).Debugf("Container %q already exists, deleting", container.Name) delCmd := c.createNerdctlCmd(ctx, "rm", "-f", container.Name) if err = delCmd.Run(); err != nil { return "", fmt.Errorf("could not delete container %q: %s", container.Name, err) } - logrus.Infof("Re-creating container %s", container.Name) + log.G(ctx).Infof("Re-creating container %s", container.Name) } else { - logrus.Infof("Creating container %s", container.Name) + log.G(ctx).Infof("Creating container %s", container.Name) } for _, f := range container.Mkdir { - logrus.Debugf("Creating a directory %q", f) + log.G(ctx).Debugf("Creating a directory %q", f) if err = os.MkdirAll(f, 0o755); err != nil { return "", fmt.Errorf("failed to create a directory %q: %w", f, err) } @@ -159,7 +159,7 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse cmd := c.createNerdctlCmd(ctx, append([]string{"run"}, container.RunArgs...)...) if c.DebugPrintFull { - logrus.Debugf("Running %v", cmd.Args) + log.G(ctx).Debugf("Running %v", cmd.Args) } // FIXME diff --git a/pkg/composer/up_volume.go b/pkg/composer/up_volume.go index 3e8e26c5012..b1578b89a03 100644 --- a/pkg/composer/up_volume.go +++ b/pkg/composer/up_volume.go @@ -20,10 +20,9 @@ import ( "context" "fmt" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/reflectutil" - - "github.com/sirupsen/logrus" ) func (c *Composer) upVolume(ctx context.Context, shortName string) error { @@ -37,7 +36,7 @@ func (c *Composer) upVolume(ctx context.Context, shortName string) error { } if unknown := reflectutil.UnknownNonEmptyFields(&vol, "Name"); len(unknown) > 0 { - logrus.Warnf("Ignoring: volume %s: %+v", shortName, unknown) + log.G(ctx).Warnf("Ignoring: volume %s: %+v", shortName, unknown) } // shortName is like "db_data", fullName is like "compose-wordpress_db_data" @@ -46,7 +45,7 @@ func (c *Composer) upVolume(ctx context.Context, shortName string) error { if err != nil { return err } else if !volExists { - logrus.Infof("Creating volume %s", fullName) + log.G(ctx).Infof("Creating volume %s", fullName) //add metadata labels to volume https://github.com/compose-spec/compose-spec/blob/master/spec.md#labels-2 createArgs := []string{ fmt.Sprintf("--label=%s=%s", labels.ComposeProject, c.project.Name), diff --git a/pkg/consoleutil/detach.go b/pkg/consoleutil/detach.go index 94b550cb143..61cfa9e5631 100644 --- a/pkg/consoleutil/detach.go +++ b/pkg/consoleutil/detach.go @@ -21,8 +21,8 @@ import ( "fmt" "io" + "github.com/containerd/log" "github.com/moby/term" - "github.com/sirupsen/logrus" ) const DefaultDetachKeys = "ctrl-p,ctrl-q" @@ -53,7 +53,7 @@ func (ds *detachableStdin) Read(p []byte) (int, error) { n, err := ds.stdin.Read(p) var eerr term.EscapeError if errors.As(err, &eerr) { - logrus.Info("read detach keys") + log.L.Info("read detach keys") if ds.closer != nil { ds.closer() } diff --git a/pkg/containerinspector/containerinspector.go b/pkg/containerinspector/containerinspector.go index 8d760c77ebd..4ff3624c4c1 100644 --- a/pkg/containerinspector/containerinspector.go +++ b/pkg/containerinspector/containerinspector.go @@ -21,9 +21,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/containerd/typeurl/v2" - "github.com/sirupsen/logrus" ) func Inspect(ctx context.Context, container containerd.Container) (*native.Container, error) { @@ -38,13 +38,13 @@ func Inspect(ctx context.Context, container containerd.Container) (*native.Conta n.Spec, err = typeurl.UnmarshalAny(info.Spec) if err != nil { - logrus.WithError(err).WithField("id", id).Warnf("failed to inspect Spec") + log.G(ctx).WithError(err).WithField("id", id).Warnf("failed to inspect Spec") return n, nil } task, err := container.Task(ctx, nil) if err != nil { if !errdefs.IsNotFound(err) { - logrus.WithError(err).WithField("id", id).Warnf("failed to inspect Task") + log.G(ctx).WithError(err).WithField("id", id).Warnf("failed to inspect Task") } return n, nil } @@ -53,13 +53,13 @@ func Inspect(ctx context.Context, container containerd.Container) (*native.Conta } st, err := task.Status(ctx) if err != nil { - logrus.WithError(err).WithField("id", id).Warnf("failed to inspect Status") + log.G(ctx).WithError(err).WithField("id", id).Warnf("failed to inspect Status") return n, nil } n.Process.Status = st netNS, err := InspectNetNS(ctx, n.Process.Pid) if err != nil { - logrus.WithError(err).WithField("id", id).Warnf("failed to inspect NetNS") + log.G(ctx).WithError(err).WithField("id", id).Warnf("failed to inspect NetNS") return n, nil } n.Process.NetNS = netNS diff --git a/pkg/containerutil/container_network_manager_linux.go b/pkg/containerutil/container_network_manager_linux.go index 45bfd4523d0..b8ea83098f4 100644 --- a/pkg/containerutil/container_network_manager_linux.go +++ b/pkg/containerutil/container_network_manager_linux.go @@ -24,6 +24,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/oci" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/dnsutil" @@ -31,7 +32,6 @@ import ( "github.com/containerd/nerdctl/pkg/netutil" "github.com/containerd/nerdctl/pkg/resolvconf" "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/sirupsen/logrus" ) // Verifies that the internal network settings are correct. @@ -149,7 +149,7 @@ func (m *cniNetworkManager) buildResolvConf(resolvConfPath string) error { } // if resolvConf file does't exist, using default resolvers conf = &resolvconf.File{} - logrus.WithError(err).Debugf("resolvConf file doesn't exist on host") + log.L.WithError(err).Debugf("resolvConf file doesn't exist on host") } conf, err = resolvconf.FilterResolvDNS(conf.Content, true) if err != nil { diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 425223fb9df..31799827d59 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -34,6 +34,7 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/runtime/restart" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/consoleutil" "github.com/containerd/nerdctl/pkg/errutil" "github.com/containerd/nerdctl/pkg/formatter" @@ -45,7 +46,6 @@ import ( "github.com/containerd/nerdctl/pkg/taskutil" "github.com/moby/sys/signal" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" ) // PrintHostPort writes to `writer` the public (HostIP:HostPort) of a given `containerPort/protocol` in a container. @@ -246,7 +246,7 @@ func Start(ctx context.Context, container containerd.Container, flagA bool, clie cStatus := formatter.ContainerStatus(ctx, container) if cStatus == "Up" { - logrus.Warnf("container %s is already running", container.ID()) + log.G(ctx).Warnf("container %s is already running", container.ID()) return nil } @@ -262,7 +262,7 @@ func Start(ctx context.Context, container containerd.Container, flagA bool, clie } if oldTask, err := container.Task(ctx, nil); err == nil { if _, err := oldTask.Delete(ctx); err != nil { - logrus.WithError(err).Debug("failed to delete old task") + log.G(ctx).WithError(err).Debug("failed to delete old task") } } detachC := make(chan struct{}) @@ -279,7 +279,7 @@ func Start(ctx context.Context, container containerd.Container, flagA bool, clie } if flagA && flagT { if err := consoleutil.HandleConsoleResize(ctx, task, con); err != nil { - logrus.WithError(err).Error("console resize") + log.G(ctx).WithError(err).Error("console resize") } } sigc := signalutil.ForwardAllSignals(ctx, task) @@ -390,7 +390,7 @@ func Stop(ctx context.Context, container containerd.Container, timeout *time.Dur // signal will be sent once resume is finished if paused { if err := task.Resume(ctx); err != nil { - logrus.Warnf("Cannot unpause container %s: %s", container.ID(), err) + log.G(ctx).Warnf("Cannot unpause container %s: %s", container.ID(), err) } else { // no need to do it again when send sigkill signal paused = false @@ -422,7 +422,7 @@ func Stop(ctx context.Context, container containerd.Container, timeout *time.Dur // signal will be sent once resume is finished if paused { if err := task.Resume(ctx); err != nil { - logrus.Warnf("Cannot unpause container %s: %s", container.ID(), err) + log.G(ctx).Warnf("Cannot unpause container %s: %s", container.ID(), err) } } return waitContainerStop(ctx, exitCh, container.ID()) @@ -541,7 +541,7 @@ func GetContainerVolumes(containerLabels map[string]string) []*ContainerVolume { } if err != nil { - logrus.Warn(err) + log.L.Warn(err) } vols = append(vols, volumes...) } diff --git a/pkg/containerutil/cp_linux.go b/pkg/containerutil/cp_linux.go index c4716da5ea3..21fb413701b 100644 --- a/pkg/containerutil/cp_linux.go +++ b/pkg/containerutil/cp_linux.go @@ -31,10 +31,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/mount" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/containerd/nerdctl/pkg/tarutil" securejoin "github.com/cyphar/filepath-securejoin" - "github.com/sirupsen/logrus" ) // CopyFiles implements `nerdctl cp`. @@ -44,7 +44,7 @@ func CopyFiles(ctx context.Context, client *containerd.Client, container contain if err != nil { return err } - logrus.Debugf("Detected tar binary %q (GNU=%v)", tarBinary, isGNUTar) + log.G(ctx).Debugf("Detected tar binary %q (GNU=%v)", tarBinary, isGNUTar) var srcFull, dstFull, root, mountDestination, containerPath string var cleanup func() task, err := container.Task(ctx, nil) @@ -193,7 +193,7 @@ func CopyFiles(ctx context.Context, client *containerd.Client, container contain } cp = append(cp, srcFull, filepath.Join(td, tarCArg)) cpCmd := exec.CommandContext(ctx, cp[0], cp[1:]...) - logrus.Debugf("executing %v", cpCmd.Args) + log.G(ctx).Debugf("executing %v", cpCmd.Args) if out, err := cpCmd.CombinedOutput(); err != nil { return fmt.Errorf("failed to execute %v: %w (out=%q)", cpCmd.Args, err, string(out)) } @@ -237,11 +237,11 @@ func CopyFiles(ctx context.Context, client *containerd.Client, container contain tarXCmd.Stdout = os.Stderr tarXCmd.Stderr = os.Stderr - logrus.Debugf("executing %v in %q", tarCCmd.Args, tarCCmd.Dir) + log.G(ctx).Debugf("executing %v in %q", tarCCmd.Args, tarCCmd.Dir) if err := tarCCmd.Start(); err != nil { return fmt.Errorf("failed to execute %v: %w", tarCCmd.Args, err) } - logrus.Debugf("executing %v in %q", tarXCmd.Args, tarXCmd.Dir) + log.G(ctx).Debugf("executing %v in %q", tarXCmd.Args, tarXCmd.Dir) if err := tarXCmd.Start(); err != nil { return fmt.Errorf("failed to execute %v: %w", tarXCmd.Args, err) } @@ -275,7 +275,7 @@ func mountSnapshotForContainer(ctx context.Context, client *containerd.Client, c cleanup := func() { err = mount.Unmount(tempDir, 0) if err != nil { - logrus.Warnf("failed to unmount %s with error %s", tempDir, err.Error()) + log.G(ctx).Warnf("failed to unmount %s with error %s", tempDir, err.Error()) return } os.RemoveAll(tempDir) diff --git a/pkg/defaults/defaults_linux.go b/pkg/defaults/defaults_linux.go index 44541803d8e..63f35ab93e5 100644 --- a/pkg/defaults/defaults_linux.go +++ b/pkg/defaults/defaults_linux.go @@ -24,8 +24,8 @@ import ( "github.com/containerd/containerd/plugin" gocni "github.com/containerd/go-cni" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/sirupsen/logrus" ) const ( @@ -93,7 +93,7 @@ func CNIRuntimeDir() string { } xdr, err := rootlessutil.XDGRuntimeDir() if err != nil { - logrus.Warn(err) + log.L.Warn(err) xdr = fmt.Sprintf("/run/user/%d", rootlessutil.ParentEUID()) } return fmt.Sprintf("%s/cni", xdr) @@ -105,7 +105,7 @@ func BuildKitHost() string { } xdr, err := rootlessutil.XDGRuntimeDir() if err != nil { - logrus.Warn(err) + log.L.Warn(err) xdr = fmt.Sprintf("/run/user/%d", rootlessutil.ParentEUID()) } return fmt.Sprintf("unix://%s/buildkit/buildkitd.sock", xdr) diff --git a/pkg/dnsutil/hostsstore/updater.go b/pkg/dnsutil/hostsstore/updater.go index fa7dc11341b..660da9ed9d7 100644 --- a/pkg/dnsutil/hostsstore/updater.go +++ b/pkg/dnsutil/hostsstore/updater.go @@ -25,8 +25,8 @@ import ( "strings" "github.com/containerd/containerd/errdefs" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/netutil" - "github.com/sirupsen/logrus" ) // newUpdater creates an updater for hostsD (/var/lib/nerdctl//etchosts) @@ -110,7 +110,7 @@ func (u *updater) phase2() error { dir := filepath.Dir(path) myMeta, ok := u.metaByDir[dir] if !ok { - logrus.WithError(errdefs.ErrNotFound).Debugf("hostsstore metadata %q not found in %q?", metaJSON, dir) + log.L.WithError(errdefs.ErrNotFound).Debugf("hostsstore metadata %q not found in %q?", metaJSON, dir) return nil } myNetworks := make(map[string]struct{}) @@ -127,7 +127,7 @@ func (u *updater) phase2() error { var buf bytes.Buffer if r != nil { if err := parseHostsButSkipMarkedRegion(&buf, r); err != nil { - logrus.WithError(err).Warn("failed to read hosts file") + log.L.WithError(err).Warn("failed to read hosts file") } } diff --git a/pkg/formatter/formatter.go b/pkg/formatter/formatter.go index d0dc761a5c9..f8374ff94e8 100644 --- a/pkg/formatter/formatter.go +++ b/pkg/formatter/formatter.go @@ -32,9 +32,9 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/runtime/restart" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/portutil" "github.com/docker/go-units" - "github.com/sirupsen/logrus" ) func ContainerStatus(ctx context.Context, c containerd.Container) string { @@ -118,7 +118,7 @@ func Ellipsis(str string, maxDisplayWidth int) string { func FormatPorts(labelMap map[string]string) string { ports, err := portutil.ParsePortsLabel(labelMap) if err != nil { - logrus.Error(err.Error()) + log.L.Error(err.Error()) } if len(ports) == 0 { return "" diff --git a/pkg/imageinspector/imageinspector.go b/pkg/imageinspector/imageinspector.go index 6d98826fb77..3fff0bd5abe 100644 --- a/pkg/imageinspector/imageinspector.go +++ b/pkg/imageinspector/imageinspector.go @@ -21,9 +21,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" + "github.com/containerd/log" imgutil "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/sirupsen/logrus" ) // Inspect inspects the image, for the platform specified in image.platform. @@ -34,7 +34,7 @@ func Inspect(ctx context.Context, client *containerd.Client, image images.Image, img := containerd.NewImage(client, image) idx, idxDesc, err := imgutil.ReadIndex(ctx, img) if err != nil { - logrus.WithError(err).WithField("id", image.Name).Warnf("failed to inspect index") + log.G(ctx).WithError(err).WithField("id", image.Name).Warnf("failed to inspect index") } else { n.IndexDesc = idxDesc n.Index = idx @@ -42,7 +42,7 @@ func Inspect(ctx context.Context, client *containerd.Client, image images.Image, mani, maniDesc, err := imgutil.ReadManifest(ctx, img) if err != nil { - logrus.WithError(err).WithField("id", image.Name).Warnf("failed to inspect manifest") + log.G(ctx).WithError(err).WithField("id", image.Name).Warnf("failed to inspect manifest") } else { n.ManifestDesc = maniDesc n.Manifest = mani @@ -50,7 +50,7 @@ func Inspect(ctx context.Context, client *containerd.Client, image images.Image, imageConfig, imageConfigDesc, err := imgutil.ReadImageConfig(ctx, img) if err != nil { - logrus.WithError(err).WithField("id", image.Name).Warnf("failed to inspect image config") + log.G(ctx).WithError(err).WithField("id", image.Name).Warnf("failed to inspect image config") } else { n.ImageConfigDesc = imageConfigDesc n.ImageConfig = imageConfig @@ -58,7 +58,7 @@ func Inspect(ctx context.Context, client *containerd.Client, image images.Image, snapSvc := client.SnapshotService(snapshotter) n.Size, err = imgutil.UnpackedImageSize(ctx, snapSvc, img) if err != nil { - logrus.WithError(err).WithField("id", image.Name).Warnf("failed to inspect calculate size") + log.G(ctx).WithError(err).WithField("id", image.Name).Warnf("failed to inspect calculate size") } n.Image = image diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index a45fb939621..81bd0d6a425 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -37,14 +37,13 @@ import ( "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/rootfs" "github.com/containerd/containerd/snapshots" + "github.com/containerd/log" imgutil "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/labels" "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/identity" "github.com/opencontainers/image-spec/specs-go" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - "github.com/sirupsen/logrus" ) type Changes struct { @@ -80,13 +79,13 @@ func Commit(ctx context.Context, client *containerd.Client, container containerd platformLabel := info.Labels[labels.Platform] if platformLabel == "" { platformLabel = platforms.DefaultString() - logrus.Warnf("Image lacks label %q, assuming the platform to be %q", labels.Platform, platformLabel) + log.G(ctx).Warnf("Image lacks label %q, assuming the platform to be %q", labels.Platform, platformLabel) } ocispecPlatform, err := platforms.Parse(platformLabel) if err != nil { return emptyDigest, err } - logrus.Debugf("ocispecPlatform=%q", platforms.Format(ocispecPlatform)) + log.G(ctx).Debugf("ocispecPlatform=%q", platforms.Format(ocispecPlatform)) platformMC := platforms.Only(ocispecPlatform) baseImg := containerd.NewImageWithPlatform(client, baseImgWithoutPlatform, platformMC) @@ -115,7 +114,7 @@ func Commit(ctx context.Context, client *containerd.Client, container containerd defer func() { if err := task.Resume(ctx); err != nil { - logrus.Warnf("failed to unpause container %v: %v", id, err) + log.G(ctx).Warnf("failed to unpause container %v: %v", id, err) } }() } @@ -205,14 +204,14 @@ func generateCommitImageConfig(ctx context.Context, container containerd.Contain arch := baseConfig.Architecture if arch == "" { arch = runtime.GOARCH - logrus.Warnf("assuming arch=%q", arch) + log.G(ctx).Warnf("assuming arch=%q", arch) } os := baseConfig.OS if os == "" { os = runtime.GOOS - logrus.Warnf("assuming os=%q", os) + log.G(ctx).Warnf("assuming os=%q", os) } - logrus.Debugf("generateCommitImageConfig(): arch=%q, os=%q", arch, os) + log.G(ctx).Debugf("generateCommitImageConfig(): arch=%q, os=%q", arch, os) return ocispec.Image{ Platform: ocispec.Platform{ Architecture: arch, @@ -352,7 +351,7 @@ func applyDiffLayer(ctx context.Context, name string, baseImg ocispec.Image, sn // NOTE: the snapshotter should be hold by lease. Even // if the cleanup fails, the containerd gc can delete it. if err := sn.Remove(ctx, key); err != nil { - logrus.Warnf("failed to cleanup aborted apply %s: %s", key, err) + log.G(ctx).Warnf("failed to cleanup aborted apply %s: %s", key, err) } } }() diff --git a/pkg/imgutil/converter/zstd.go b/pkg/imgutil/converter/zstd.go index dc68b16bae9..859f1d3cc0c 100644 --- a/pkg/imgutil/converter/zstd.go +++ b/pkg/imgutil/converter/zstd.go @@ -26,10 +26,10 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/images/converter/uncompress" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" "github.com/klauspost/compress/zstd" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" ) // ZstdLayerConvertFunc converts legacy tar.gz layers into zstd layers with @@ -52,10 +52,10 @@ func ZstdLayerConvertFunc(options types.ImageConvertOptions) (converter.ConvertF } defer func() { if err := cs.Delete(ctx, uncompressedDesc.Digest); err != nil { - logrus.WithError(err).WithField("uncompressedDesc", uncompressedDesc).Warn("failed to remove tmp uncompressed layer") + log.L.WithError(err).WithField("uncompressedDesc", uncompressedDesc).Warn("failed to remove tmp uncompressed layer") } }() - logrus.Debugf("zstd: uncompressed %s into %s", desc.Digest, uncompressedDesc.Digest) + log.L.Debugf("zstd: uncompressed %s into %s", desc.Digest, uncompressedDesc.Digest) } info, err := cs.Info(ctx, desc.Digest) diff --git a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go index 6bac7c92240..f3017176b99 100644 --- a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go +++ b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go @@ -26,11 +26,11 @@ import ( "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" dockerconfig "github.com/containerd/containerd/remotes/docker/config" + "github.com/containerd/log" dockercliconfig "github.com/docker/cli/cli/config" "github.com/docker/cli/cli/config/credentials" dockercliconfigtypes "github.com/docker/cli/cli/config/types" "github.com/docker/docker/errdefs" - "github.com/sirupsen/logrus" ) var PushTracker = docker.NewInMemoryTracker() @@ -63,17 +63,17 @@ func WithSkipVerifyCerts(b bool) Opt { func WithHostsDirs(orig []string) Opt { var ss []string if len(orig) == 0 { - logrus.Debug("no hosts dir was specified") + log.L.Debug("no hosts dir was specified") } for _, v := range orig { if _, err := os.Stat(v); err == nil { - logrus.Debugf("Found hosts dir %q", v) + log.L.Debugf("Found hosts dir %q", v) ss = append(ss, v) } else { if errors.Is(err, os.ErrNotExist) { - logrus.WithError(err).Debugf("Ignoring hosts dir %q", v) + log.L.WithError(err).Debugf("Ignoring hosts dir %q", v) } else { - logrus.WithError(err).Warnf("Ignoring hosts dir %q", v) + log.L.WithError(err).Warnf("Ignoring hosts dir %q", v) } } } @@ -195,7 +195,7 @@ func NewAuthCreds(refHostname string) (AuthCreds, error) { // GetAuthConfig does not raise an error on ENOENT ac, err := dockerConfigFile.GetAuthConfig(authConfigHostname) if err != nil { - logrus.WithError(err).Warnf("cannot get auth config for authConfigHostname=%q (refHostname=%q)", + log.L.WithError(err).Warnf("cannot get auth config for authConfigHostname=%q (refHostname=%q)", authConfigHostname, refHostname) } else { // When refHostname is "docker.io": @@ -206,7 +206,7 @@ func NewAuthCreds(refHostname string) (AuthCreds, error) { if !isAuthConfigEmpty(ac) { if ac.ServerAddress == "" { // This can happen with Amazon ECR: https://github.com/containerd/nerdctl/issues/733 - logrus.Debugf("failed to get ac.ServerAddress for authConfigHostname=%q (refHostname=%q)", + log.L.Debugf("failed to get ac.ServerAddress for authConfigHostname=%q (refHostname=%q)", authConfigHostname, refHostname) } else if authConfigHostname == IndexServer { if ac.ServerAddress != IndexServer { @@ -223,7 +223,7 @@ func NewAuthCreds(refHostname string) (AuthCreds, error) { if ac.RegistryToken != "" { // Even containerd/CRI does not support RegistryToken as of v1.4.3, // so, nobody is actually using RegistryToken? - logrus.Warnf("ac.RegistryToken (for %q) is not supported yet (FIXME)", authConfigHostname) + log.L.Warnf("ac.RegistryToken (for %q) is not supported yet (FIXME)", authConfigHostname) } credFunc = func(credFuncArg string) (string, string, error) { diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index 3e1445c8c87..898b6f1c1e2 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -26,8 +26,8 @@ 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" - "github.com/sirupsen/logrus" ) // Filter types supported to filter images. @@ -136,9 +136,9 @@ func FilterImages(labelImages []images.Image, beforeImages []images.Image, since // FilterByReference filters images using references given in `filters`. func FilterByReference(imageList []images.Image, filters []string) ([]images.Image, error) { var filteredImageList []images.Image - logrus.Debug(filters) + log.L.Debug(filters) for _, image := range imageList { - logrus.Debug(image.Name) + log.L.Debug(image.Name) var matches int for _, f := range filters { var ref dockerreference.Reference diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 14e04c40705..9c14abcd5dc 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -32,6 +32,7 @@ import ( "github.com/containerd/containerd/snapshots" "github.com/containerd/imgcrypt" "github.com/containerd/imgcrypt/images/encryption" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/errutil" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" @@ -39,7 +40,6 @@ import ( "github.com/docker/docker/errdefs" "github.com/opencontainers/image-spec/identity" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" ) // EnsuredImage contains the image existed in containerd and its metadata. @@ -133,7 +133,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr var dOpts []dockerconfigresolver.Opt if insecure { - logrus.Warnf("skipping verifying HTTPS certs for %q", refDomain) + log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain) dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) } dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(hostsDirs)) @@ -149,7 +149,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr return nil, err } if insecure { - logrus.WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", refDomain) + log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", refDomain) dOpts = append(dOpts, dockerconfigresolver.WithPlainHTTP(true)) resolver, err = dockerconfigresolver.New(ctx, refDomain, dOpts...) if err != nil { @@ -157,8 +157,8 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr } return PullImage(ctx, client, stdout, stderr, snapshotter, resolver, ref, ocispecPlatforms, unpack, quiet) } - logrus.WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain) - logrus.Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)") + log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain) + log.G(ctx).Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)") return nil, err } @@ -176,7 +176,7 @@ func ResolveDigest(ctx context.Context, rawRef string, insecure bool, hostsDirs var dOpts []dockerconfigresolver.Opt if insecure { - logrus.Warnf("skipping verifying HTTPS certs for %q", refDomain) + log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain) dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) } dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(hostsDirs)) @@ -222,7 +222,7 @@ func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io snOpt := getSnapshotterOpts(snapshotter) if unpackB { - logrus.Debugf("The image will be unpacked for platform %q, snapshotter %q.", ocispecPlatforms[0], snapshotter) + log.G(ctx).Debugf("The image will be unpacked for platform %q, snapshotter %q.", ocispecPlatforms[0], snapshotter) imgcryptPayload := imgcrypt.Payload{} imgcryptUnpackOpt := encryption.WithUnpackConfigApplyOpts(encryption.WithDecryptedUnpack(&imgcryptPayload)) config.RemoteOpts = append(config.RemoteOpts, @@ -232,7 +232,7 @@ func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io // different remote snapshotters will update pull.Config separately snOpt.apply(config, ref) } else { - logrus.Debugf("The image will not be unpacked. Platforms=%v.", ocispecPlatforms) + log.G(ctx).Debugf("The image will not be unpacked. Platforms=%v.", ocispecPlatforms) } containerdImage, err = pull.Pull(ctx, client, ref, config) @@ -358,11 +358,11 @@ func ReadImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image, // ParseRepoTag parses raw `imgName` to repository and tag. func ParseRepoTag(imgName string) (string, string) { - logrus.Debugf("raw image name=%q", imgName) + log.L.Debugf("raw image name=%q", imgName) ref, err := refdocker.ParseDockerRef(imgName) if err != nil { - logrus.WithError(err).Debugf("unparsable image name %q", imgName) + log.L.WithError(err).Debugf("unparsable image name %q", imgName) return "", "" } @@ -411,7 +411,7 @@ func UnpackedImageSize(ctx context.Context, s snapshots.Snapshotter, img contain usage, err := s.Usage(ctx, chainID) if err != nil { if errdefs.IsNotFound(err) { - logrus.WithError(err).Debugf("image %q seems not unpacked", img.Name()) + log.G(ctx).WithError(err).Debugf("image %q seems not unpacked", img.Name()) return 0, nil } return 0, err diff --git a/pkg/imgutil/snapshotter.go b/pkg/imgutil/snapshotter.go index 922deca785f..1abc5a14fb3 100644 --- a/pkg/imgutil/snapshotter.go +++ b/pkg/imgutil/snapshotter.go @@ -23,9 +23,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/imgutil/pull" "github.com/containerd/stargz-snapshotter/fs/source" - "github.com/sirupsen/logrus" ) const ( @@ -58,7 +58,7 @@ func getSnapshotterOpts(snapshotter string) snapshotterOpts { for sn, sno := range builtinRemoteSnapshotterOpts { if strings.Contains(snapshotter, sn) { if snapshotter != sn { - logrus.Debugf("assuming %s to be a %s-compatible snapshotter", snapshotter, sn) + log.L.Debugf("assuming %s to be a %s-compatible snapshotter", snapshotter, sn) } return sno } diff --git a/pkg/infoutil/infoutil.go b/pkg/infoutil/infoutil.go index bee2792e1ab..e5eb2efddab 100644 --- a/pkg/infoutil/infoutil.go +++ b/pkg/infoutil/infoutil.go @@ -29,12 +29,12 @@ import ( "github.com/containerd/containerd" ptypes "github.com/containerd/containerd/protobuf/types" "github.com/containerd/containerd/services/introspection" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/buildkitutil" "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/containerd/nerdctl/pkg/logging" "github.com/containerd/nerdctl/pkg/version" - "github.com/sirupsen/logrus" ) func NativeDaemonInfo(ctx context.Context, client *containerd.Client) (*native.DaemonInfo, error) { @@ -160,19 +160,19 @@ func ServerSemVer(ctx context.Context, client *containerd.Client) (*semver.Versi func buildctlVersion() dockercompat.ComponentVersion { buildctlBinary, err := buildkitutil.BuildctlBinary() if err != nil { - logrus.Warnf("unable to determine buildctl version: %s", err.Error()) + log.L.Warnf("unable to determine buildctl version: %s", err.Error()) return dockercompat.ComponentVersion{Name: "buildctl"} } stdout, err := exec.Command(buildctlBinary, "--version").Output() if err != nil { - logrus.Warnf("unable to determine buildctl version: %s", err.Error()) + log.L.Warnf("unable to determine buildctl version: %s", err.Error()) return dockercompat.ComponentVersion{Name: "buildctl"} } v, err := parseBuildctlVersion(stdout) if err != nil { - logrus.Warn(err) + log.L.Warn(err) return dockercompat.ComponentVersion{Name: "buildctl"} } return *v @@ -205,12 +205,12 @@ func parseBuildctlVersion(buildctlVersionStdout []byte) (*dockercompat.Component func runcVersion() dockercompat.ComponentVersion { stdout, err := exec.Command("runc", "--version").Output() if err != nil { - logrus.Warnf("unable to determine runc version: %s", err.Error()) + log.L.Warnf("unable to determine runc version: %s", err.Error()) return dockercompat.ComponentVersion{Name: "runc"} } v, err := parseRuncVersion(stdout) if err != nil { - logrus.Warn(err) + log.L.Warn(err) return dockercompat.ComponentVersion{Name: "runc"} } return *v @@ -228,7 +228,7 @@ func parseRuncVersion(runcVersionStdout []byte) (*dockercompat.ComponentVersion, for _, detailsLine := range versionList[1:] { detail := strings.SplitN(detailsLine, ":", 2) if len(detail) != 2 { - logrus.Warnf("unable to determine one of runc details, got: %s, %d", detail, len(detail)) + log.L.Warnf("unable to determine one of runc details, got: %s, %d", detail, len(detail)) continue } switch strings.TrimSpace(detail[0]) { diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index 843c59c705c..2312274f9af 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -38,12 +38,12 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/runtime/restart" gocni "github.com/containerd/go-cni" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/inspecttypes/native" "github.com/containerd/nerdctl/pkg/labels" "github.com/docker/go-connections/nat" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" "github.com/tidwall/gjson" ) @@ -357,7 +357,7 @@ func networkSettingsFromNative(n *native.NetNS, sp *specs.Spec) (*NetworkSetting for _, a := range x.Addrs { ip, ipnet, err := net.ParseCIDR(a) if err != nil { - logrus.WithError(err).WithField("name", x.Name).Warnf("failed to parse %q", a) + log.L.WithError(err).WithField("name", x.Name).Warnf("failed to parse %q", a) continue } if ip.IsLoopback() || ip.IsLinkLocalUnicast() { diff --git a/pkg/ipfs/image.go b/pkg/ipfs/image.go index 931c673cac0..f5df458ae65 100644 --- a/pkg/ipfs/image.go +++ b/pkg/ipfs/image.go @@ -26,6 +26,7 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/remotes" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/pkg/imgutil" "github.com/containerd/nerdctl/pkg/platformutil" @@ -34,7 +35,6 @@ import ( ipfsclient "github.com/containerd/stargz-snapshotter/ipfs/client" "github.com/docker/docker/errdefs" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" ) const ipfsPathEnv = "IPFS_PATH" @@ -85,9 +85,9 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, layerCo ipath := lookupIPFSPath(ipfsPath) if ensureImage { // Ensure image contents are fully downloaded - logrus.Infof("ensuring image contents") + log.G(ctx).Infof("ensuring image contents") if err := ensureContentsOfIPFSImage(ctx, client, rawRef, allPlatforms, platform, ipath); err != nil { - logrus.WithError(err).Warnf("failed to ensure the existence of image %q", rawRef) + log.G(ctx).WithError(err).Warnf("failed to ensure the existence of image %q", rawRef) } } ref, err := referenceutil.ParseAny(rawRef) diff --git a/pkg/ipfs/registry.go b/pkg/ipfs/registry.go index f9fd183a263..76539826b12 100644 --- a/pkg/ipfs/registry.go +++ b/pkg/ipfs/registry.go @@ -31,10 +31,10 @@ import ( "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" + "github.com/containerd/log" ipfsclient "github.com/containerd/stargz-snapshotter/ipfs/client" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" ) // RegistryOptions represents options to configure the registry. @@ -72,14 +72,14 @@ var blobsRegexp = regexp.MustCompile(`/v2/ipfs/([a-z0-9]+)/blobs/(.*)`) func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { cid, content, mediaType, size, err := s.serve(r) if err != nil { - logrus.WithError(err).Warnf("failed to serve %q %q", r.Method, r.URL.Path) + log.L.WithError(err).Warnf("failed to serve %q %q", r.Method, r.URL.Path) // TODO: support response body following OCI Distribution Spec's error response format spec: // https://github.com/opencontainers/distribution-spec/blob/v1.0/spec.md#error-codes http.Error(w, "", http.StatusNotFound) return } if content == nil { - logrus.Debugf("returning without contents") + log.L.Debugf("returning without contents") w.WriteHeader(200) return } @@ -87,7 +87,7 @@ func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Length", strconv.FormatInt(size, 10)) if r.Method == "GET" { http.ServeContent(w, r, "", time.Now(), content) - logrus.WithField("CID", cid).Debugf("served file") + log.L.WithField("CID", cid).Debugf("served file") } } @@ -97,7 +97,7 @@ func (s *server) serve(r *http.Request) (string, io.ReadSeeker, string, int64, e } if r.URL.Path == "/v2/" { - logrus.Debugf("requested /v2/") + log.L.Debugf("requested /v2/") return "", nil, "", 0, nil } @@ -108,7 +108,7 @@ func (s *server) serve(r *http.Request) (string, io.ReadSeeker, string, int64, e if !images.IsManifestType(mediaType) && !images.IsIndexType(mediaType) { return "", nil, "", 0, fmt.Errorf("cannot serve non-manifest from manifest API: %q", mediaType) } - logrus.WithField("root CID", cidStr).WithField("digest", ref).WithField("resolved CID", resolvedCID).Debugf("resolved manifest by digest") + log.L.WithField("root CID", cidStr).WithField("digest", ref).WithField("resolved CID", resolvedCID).Debugf("resolved manifest by digest") return resolvedCID, content, mediaType, size, err } if ref != "latest" { @@ -118,7 +118,7 @@ func (s *server) serve(r *http.Request) (string, io.ReadSeeker, string, int64, e if err != nil { return "", nil, "", 0, err } - logrus.WithField("root CID", cidStr).WithField("resolved CID", resolvedCID).Debugf("resolved manifest by cid") + log.L.WithField("root CID", cidStr).WithField("resolved CID", resolvedCID).Debugf("resolved manifest by cid") return resolvedCID, content, mediaType, size, nil } @@ -128,7 +128,7 @@ func (s *server) serve(r *http.Request) (string, io.ReadSeeker, string, int64, e if err != nil { return "", nil, "", 0, err } - logrus.WithField("root CID", rootCIDStr).WithField("digest", dgstStr).WithField("resolved CID", resolvedCID).Debugf("resolved blob by digest") + log.L.WithField("root CID", rootCIDStr).WithField("digest", dgstStr).WithField("resolved CID", resolvedCID).Debugf("resolved blob by digest") return resolvedCID, content, mediaType, size, nil } diff --git a/pkg/lockutil/lockutil_unix.go b/pkg/lockutil/lockutil_unix.go index 4f8a2a06a8e..dbabcbc9b0f 100644 --- a/pkg/lockutil/lockutil_unix.go +++ b/pkg/lockutil/lockutil_unix.go @@ -22,7 +22,7 @@ import ( "fmt" "os" - "github.com/sirupsen/logrus" + "github.com/containerd/log" "golang.org/x/sys/unix" ) @@ -37,7 +37,7 @@ func WithDirLock(dir string, fn func() error) error { } defer func() { if err := Flock(dirFile, unix.LOCK_UN); err != nil { - logrus.WithError(err).Errorf("failed to unlock %q", dir) + log.L.WithError(err).Errorf("failed to unlock %q", dir) } }() return fn() diff --git a/pkg/lockutil/lockutil_windows.go b/pkg/lockutil/lockutil_windows.go index bcfd9776556..85658167443 100644 --- a/pkg/lockutil/lockutil_windows.go +++ b/pkg/lockutil/lockutil_windows.go @@ -20,7 +20,7 @@ import ( "fmt" "os" - "github.com/sirupsen/logrus" + "github.com/containerd/log" "golang.org/x/sys/windows" ) @@ -38,7 +38,7 @@ func WithDirLock(dir string, fn func() error) error { defer func() { if err := windows.UnlockFileEx(windows.Handle(dirFile.Fd()), 0, 1, 0, &windows.Overlapped{}); err != nil { - logrus.WithError(err).Errorf("failed to unlock %q", dir) + log.L.WithError(err).Errorf("failed to unlock %q", dir) } }() return fn() diff --git a/pkg/logging/cri_logger.go b/pkg/logging/cri_logger.go index a6381d33976..9865a99d6c1 100644 --- a/pkg/logging/cri_logger.go +++ b/pkg/logging/cri_logger.go @@ -35,7 +35,6 @@ import ( "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/logging/tail" - "github.com/sirupsen/logrus" ) // LogStreamType is the type of the stream in CRI container log. @@ -114,11 +113,11 @@ func ReadLogs(opts *LogViewOptions, stdout, stderr io.Writer, stopChannel chan o for { select { case <-stopChannel: - logrus.Debugf("received stop signal while reading cri logfile, returning") + log.L.Debugf("received stop signal while reading cri logfile, returning") return nil default: if stop || (limitedMode && limitedNum == 0) { - logrus.Debugf("finished parsing log file, path: %s", logPath) + log.L.Debugf("finished parsing log file, path: %s", logPath) return nil } l, err := r.ReadBytes(eol[0]) @@ -142,22 +141,22 @@ func ReadLogs(opts *LogViewOptions, stdout, stderr io.Writer, stopChannel chan o if len(l) == 0 { continue } - logrus.Debugf("incomplete line in log file, path: %s, line: %s", logPath, l) + log.L.Debugf("incomplete line in log file, path: %s, line: %s", logPath, l) } // Parse the log line. msg.reset() if err := ParseCRILog(l, msg); err != nil { - logrus.WithError(err).Errorf("failed when parsing line in log file, path: %s, line: %s", logPath, l) + log.L.WithError(err).Errorf("failed when parsing line in log file, path: %s, line: %s", logPath, l) continue } // Write the log line into the stream. if err := writer.write(msg, isNewLine); err != nil { if err == errMaximumWrite { - logrus.Debugf("finished parsing log file, hit bytes limit path: %s", logPath) + log.L.Debugf("finished parsing log file, hit bytes limit path: %s", logPath) return nil } - logrus.WithError(err).Errorf("failed when writing line to log file, path: %s, line: %s", logPath, l) + log.L.WithError(err).Errorf("failed when writing line to log file, path: %s, line: %s", logPath, l) return err } if limitedMode { diff --git a/pkg/logging/fluentd_logger.go b/pkg/logging/fluentd_logger.go index 402a26292b8..9abf9157962 100644 --- a/pkg/logging/fluentd_logger.go +++ b/pkg/logging/fluentd_logger.go @@ -27,9 +27,9 @@ import ( "time" "github.com/containerd/containerd/runtime/v2/logging" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/strutil" "github.com/fluent/fluent-logger-golang/fluent" - "github.com/sirupsen/logrus" ) type FluentdLogger struct { @@ -77,11 +77,11 @@ const ( func FluentdLogOptsValidate(logOptMap map[string]string) error { for key := range logOptMap { if !strutil.InStringSlice(FluentdLogOpts, key) { - logrus.Warnf("log-opt %s is ignored for fluentd log driver", key) + log.L.Warnf("log-opt %s is ignored for fluentd log driver", key) } } if _, ok := logOptMap[fluentAddress]; !ok { - logrus.Warnf("%s is missing for fluentd log driver, the default value %s:%d will be used", fluentAddress, defaultHost, defaultPort) + log.L.Warnf("%s is missing for fluentd log driver, the default value %s:%d will be used", fluentAddress, defaultHost, defaultPort) } return nil } diff --git a/pkg/logging/journald_logger.go b/pkg/logging/journald_logger.go index f14aa651b70..d5617eb8e97 100644 --- a/pkg/logging/journald_logger.go +++ b/pkg/logging/journald_logger.go @@ -29,11 +29,11 @@ import ( "time" "github.com/containerd/containerd/runtime/v2/logging" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/strutil" "github.com/coreos/go-systemd/v22/journal" "github.com/docker/cli/templates" timetypes "github.com/docker/docker/api/types/time" - "github.com/sirupsen/logrus" ) var JournalDriverLogOpts = []string{ @@ -43,7 +43,7 @@ var JournalDriverLogOpts = []string{ func JournalLogOptsValidate(logOptMap map[string]string) error { for key := range logOptMap { if !strutil.InStringSlice(JournalDriverLogOpts, key) { - logrus.Warnf("log-opt %s is ignored for journald log driver", key) + log.L.Warnf("log-opt %s is ignored for journald log driver", key) } } return nil @@ -141,7 +141,7 @@ func FetchLogs(stdout, stderr io.Writer, journalctlArgs []string, stopChannel ch // Setup killing goroutine: go func() { <-stopChannel - logrus.Debugf("killing journalctl logs process with PID: %#v", cmd.Process.Pid) + log.L.Debugf("killing journalctl logs process with PID: %#v", cmd.Process.Pid) cmd.Process.Kill() }() @@ -172,7 +172,7 @@ func viewLogsJournald(lvopts LogViewOptions, stdout, stderr io.Writer, stopChann journalctlArgs = append(journalctlArgs, "--since", date) } if lvopts.Timestamps { - logrus.Warnf("unsupported Timestamps option for journald driver") + log.L.Warnf("unsupported Timestamps option for journald driver") } if lvopts.Until != "" { // using GetTimestamp from moby to keep time format consistency diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index 5e61c615d93..88c8555d3e0 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -27,11 +27,11 @@ import ( "time" "github.com/containerd/containerd/runtime/v2/logging" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/logging/jsonfile" "github.com/containerd/nerdctl/pkg/strutil" "github.com/docker/go-units" "github.com/fahedouch/go-logrotate" - "github.com/sirupsen/logrus" ) var JSONDriverLogOpts = []string{ @@ -48,7 +48,7 @@ type JSONLogger struct { func JSONFileLogOptsValidate(logOptMap map[string]string) error { for key := range logOptMap { if !strutil.InStringSlice(JSONDriverLogOpts, key) { - logrus.Warnf("log-opt %s is ignored for json-file log driver", key) + log.L.Warnf("log-opt %s is ignored for json-file log driver", key) } } return nil @@ -160,7 +160,7 @@ func viewLogsJSONFileDirect(lvopts LogViewOptions, jsonLogFilePath string, stdou for { select { case <-stopChannel: - logrus.Debugf("received stop signal while re-reading JSON logfile, returning") + log.L.Debugf("received stop signal while re-reading JSON logfile, returning") return nil default: // Re-open the file and seek to the last-consumed offset. @@ -224,7 +224,7 @@ func viewLogsJSONFileThroughTailExec(lvopts LogViewOptions, jsonLogFilePath stri // Setup killing goroutine: go func() { <-stopChannel - logrus.Debugf("killing tail logs process with PID: %d", cmd.Process.Pid) + log.L.Debugf("killing tail logs process with PID: %d", cmd.Process.Pid) cmd.Process.Kill() }() diff --git a/pkg/logging/jsonfile/jsonfile.go b/pkg/logging/jsonfile/jsonfile.go index cf5400daca5..cb951534281 100644 --- a/pkg/logging/jsonfile/jsonfile.go +++ b/pkg/logging/jsonfile/jsonfile.go @@ -27,9 +27,8 @@ import ( "sync" "time" + "github.com/containerd/log" timetypes "github.com/docker/docker/api/types/time" - - "github.com/sirupsen/logrus" ) // Entry is compatible with Docker "json-file" logs @@ -54,14 +53,14 @@ func Encode(stdout <-chan string, stderr <-chan string, writer io.Writer) error e := &Entry{ Stream: name, } - for log := range dataChan { - e.Log = log + "\n" + for logEntry := range dataChan { + e.Log = logEntry + "\n" e.Time = time.Now().UTC() encMu.Lock() encErr := enc.Encode(e) encMu.Unlock() if encErr != nil { - logrus.WithError(encErr).Errorf("failed to encode JSON") + log.L.WithError(encErr).Errorf("failed to encode JSON") return } } @@ -119,7 +118,7 @@ func writeEntry(e *Entry, stdout, stderr io.Writer, refTime time.Time, timestamp case "stderr": writeTo = stderr default: - logrus.Errorf("unknown stream name %q, entry=%+v", e.Stream, e) + log.L.Errorf("unknown stream name %q, entry=%+v", e.Stream, e) } if writeTo != nil { @@ -149,7 +148,7 @@ func Decode(stdout, stderr io.Writer, r io.Reader, timestamps bool, since string // Write out the entry directly err := writeEntry(&e, stdout, stderr, now, timestamps, since, until) if err != nil { - logrus.Errorf("error while writing log entry to output stream: %s", err) + log.L.Errorf("error while writing log entry to output stream: %s", err) } } else { // Else place the entry in a ring buffer @@ -168,13 +167,13 @@ func Decode(stdout, stderr io.Writer, r io.Reader, timestamps bool, since string } cast, ok := e.(*Entry) if !ok { - logrus.Errorf("failed to cast Entry struct: %#v", e) + log.L.Errorf("failed to cast Entry struct: %#v", e) return } err := writeEntry(cast, stdout, stderr, now, timestamps, since, until) if err != nil { - logrus.Errorf("error while writing log entry to output stream: %s", err) + log.L.Errorf("error while writing log entry to output stream: %s", err) } }) } diff --git a/pkg/logging/log_viewer.go b/pkg/logging/log_viewer.go index 80d0626ef6e..b96670ac160 100644 --- a/pkg/logging/log_viewer.go +++ b/pkg/logging/log_viewer.go @@ -23,8 +23,8 @@ import ( "os/exec" "path/filepath" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/labels/k8slabels" - "github.com/sirupsen/logrus" ) // Type alias for functions which write out logs to the provided stdout/stderr Writers. @@ -37,7 +37,7 @@ var logViewers = make(map[string]LogViewerFunc) // Registers a LogViewerFunc for the func RegisterLogViewer(driverName string, lvfn LogViewerFunc) { if v, ok := logViewers[driverName]; ok { - logrus.Warnf("A LogViewerFunc with name %q has already been registered: %#v, overriding with %#v either way", driverName, v, lvfn) + log.L.Warnf("A LogViewerFunc with name %q has already been registered: %#v, overriding with %#v either way", driverName, v, lvfn) } logViewers[driverName] = lvfn } @@ -93,7 +93,7 @@ func (lvo *LogViewOptions) Validate() error { if err != nil { return err } - logrus.Warnf("given relative datastore path %q, transformed it to absolute path: %q", lvo.DatastoreRootPath, abs) + log.L.Warnf("given relative datastore path %q, transformed it to absolute path: %q", lvo.DatastoreRootPath, abs) lvo.DatastoreRootPath = abs } diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index f81180503f0..c55e6b81683 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -30,7 +30,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime/v2/logging" - "github.com/sirupsen/logrus" + "github.com/containerd/log" ) const ( @@ -154,7 +154,7 @@ func loggingProcessAdapter(driver Driver, dataStore string, config *logging.Conf scanner := bufio.NewScanner(reader) for scanner.Scan() { if scanner.Err() != nil { - logrus.Errorf("failed to read log: %v", scanner.Err()) + log.L.Errorf("failed to read log: %v", scanner.Err()) return } dataChan <- scanner.Text() diff --git a/pkg/logging/syslog_logger.go b/pkg/logging/syslog_logger.go index 16cf62662f0..c5108e821b1 100644 --- a/pkg/logging/syslog_logger.go +++ b/pkg/logging/syslog_logger.go @@ -27,12 +27,12 @@ import ( "strings" "sync" + "github.com/containerd/log" "github.com/docker/go-connections/tlsconfig" syslog "github.com/yuchanns/srslog" "github.com/containerd/containerd/runtime/v2/logging" "github.com/containerd/nerdctl/pkg/strutil" - "github.com/sirupsen/logrus" ) const ( @@ -91,7 +91,7 @@ const ( func SyslogOptsValidate(logOptMap map[string]string) error { for key := range logOptMap { if !strutil.InStringSlice(syslogOpts, key) { - logrus.Warnf("log-opt %s is ignored for syslog log driver", key) + log.L.Warnf("log-opt %s is ignored for syslog log driver", key) } } proto, _, err := parseSyslogAddress(logOptMap[syslogAddress]) diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index 6f8a71bc68f..bb46743ab02 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -27,12 +27,11 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/pkg/userns" + "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/opencontainers/runtime-spec/specs-go" - - "github.com/sirupsen/logrus" ) const ( @@ -63,7 +62,7 @@ func ProcessFlagV(s string, volStore volumestore.VolumeStore, createDir bool) (* case 1: dst = s res.AnonymousVolume = idgen.GenerateID() - logrus.Debugf("creating anonymous volume %q, for %q", res.AnonymousVolume, s) + log.L.Debugf("creating anonymous volume %q, for %q", res.AnonymousVolume, s) anonVol, err := volStore.Create(res.AnonymousVolume, []string{}) if err != nil { return nil, fmt.Errorf("failed to create an anonymous volume %q: %w", res.AnonymousVolume, err) @@ -92,7 +91,7 @@ func ProcessFlagV(s string, volStore volumestore.VolumeStore, createDir bool) (* res.Type = Volume } if !filepath.IsAbs(src) { - logrus.Warnf("expected an absolute path, got a relative path %q (allowed for nerdctl, but disallowed for Docker, so unrecommended)", src) + log.L.Warnf("expected an absolute path, got a relative path %q (allowed for nerdctl, but disallowed for Docker, so unrecommended)", src) var err error src, err = filepath.Abs(src) if err != nil { diff --git a/pkg/mountutil/mountutil_freebsd.go b/pkg/mountutil/mountutil_freebsd.go index 76766d6a3db..85613c32622 100644 --- a/pkg/mountutil/mountutil_freebsd.go +++ b/pkg/mountutil/mountutil_freebsd.go @@ -22,8 +22,8 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/mountutil/volumestore" - "github.com/sirupsen/logrus" ) func UnprivilegedMountFlags(path string) ([]string, error) { @@ -47,7 +47,7 @@ func parseVolumeOptions(vType, src, optsRaw string) ([]string, []oci.SpecOpts, e case "": // NOP default: - logrus.Warnf("unsupported volume option %q", opt) + log.L.Warnf("unsupported volume option %q", opt) } } var opts []string diff --git a/pkg/mountutil/mountutil_linux.go b/pkg/mountutil/mountutil_linux.go index 92e6ebadfee..2a3f145c2f0 100644 --- a/pkg/mountutil/mountutil_linux.go +++ b/pkg/mountutil/mountutil_linux.go @@ -28,11 +28,11 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/oci" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/mountutil/volumestore" "github.com/docker/go-units" mobymount "github.com/moby/sys/mount" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -118,7 +118,7 @@ func parseVolumeOptionsWithMountInfo(vType, src, optsRaw string, getMountInfoFun case "": // NOP default: - logrus.Warnf("unsupported volume option %q", opt) + log.L.Warnf("unsupported volume option %q", opt) } } @@ -144,7 +144,7 @@ func parseVolumeOptionsWithMountInfo(vType, src, optsRaw string, getMountInfoFun // Older version of runc just ignores "rro", so we have to add "ro" too, to our best effort. opts = append(opts, "ro", "rro") if len(propagationRawOpts) != 1 || propagationRawOpts[0] != "rprivate" { - logrus.Warn("Mount option \"rro\" should be used in conjunction with \"rprivate\"") + log.L.Warn("Mount option \"rro\" should be used in conjunction with \"rprivate\"") } case "rw": // NOP @@ -418,7 +418,7 @@ func ProcessFlagMount(s string, volStore volumestore.VolumeStore) (*Processed, e } fieldsStr := strings.Join(fields, ":") - logrus.Debugf("Call legacy %s process, spec: %s ", mountType, fieldsStr) + log.L.Debugf("Call legacy %s process, spec: %s ", mountType, fieldsStr) switch mountType { case Tmpfs: diff --git a/pkg/mountutil/mountutil_windows.go b/pkg/mountutil/mountutil_windows.go index 3867b8d10fc..5875198f2ed 100644 --- a/pkg/mountutil/mountutil_windows.go +++ b/pkg/mountutil/mountutil_windows.go @@ -22,8 +22,8 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/mountutil/volumestore" - "github.com/sirupsen/logrus" ) func UnprivilegedMountFlags(path string) ([]string, error) { @@ -49,7 +49,7 @@ func parseVolumeOptions(vType, src, optsRaw string) ([]string, []oci.SpecOpts, e case "": // NOP default: - logrus.Warnf("unsupported volume option %q", opt) + log.L.Warnf("unsupported volume option %q", opt) } } var opts []string diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index c2220d4c769..0279c6e0bbe 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -33,13 +33,13 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/namespaces" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/lockutil" "github.com/containerd/nerdctl/pkg/netutil/nettype" subnetutil "github.com/containerd/nerdctl/pkg/netutil/subnet" "github.com/containerd/nerdctl/pkg/strutil" "github.com/containernetworking/cni/libcni" - "github.com/sirupsen/logrus" ) type CNIEnv struct { @@ -162,7 +162,7 @@ func (e *CNIEnv) NetworkMap() (map[string]*NetworkConfig, error) { //nolint:revi m := make(map[string]*NetworkConfig, len(networks)) for _, n := range networks { if original, exists := m[n.Name]; exists { - logrus.Warnf("duplicate network name %q, %#v will get superseded by %#v", n.Name, original, n) + log.L.Warnf("duplicate network name %q, %#v will get superseded by %#v", n.Name, original, n) } m[n.Name] = n } @@ -292,7 +292,7 @@ func (e *CNIEnv) GetDefaultNetworkConfig() (*NetworkConfig, error) { } if len(labelMatches) >= 1 { if len(labelMatches) > 1 { - logrus.Warnf("returning the first network bearing the %q label out of the multiple found: %#v", labels.NerdctlDefaultNetwork, labelMatches) + log.L.Warnf("returning the first network bearing the %q label out of the multiple found: %#v", labels.NerdctlDefaultNetwork, labelMatches) } return labelMatches[0], nil } @@ -307,14 +307,14 @@ func (e *CNIEnv) GetDefaultNetworkConfig() (*NetworkConfig, error) { } if len(nameMatches) >= 1 { if len(nameMatches) > 1 { - logrus.Warnf("returning the first network bearing the %q default network name out of the multiple found: %#v", DefaultNetworkName, nameMatches) + log.L.Warnf("returning the first network bearing the %q default network name out of the multiple found: %#v", DefaultNetworkName, nameMatches) } // Warn the user if the default network was not created by nerdctl. match := nameMatches[0] _, statErr := os.Stat(e.getConfigPathForNetworkName(DefaultNetworkName)) if match.NerdctlID == nil || statErr != nil { - logrus.Warnf("default network named %q does not have an internal nerdctl ID or nerdctl-managed config file, it was most likely NOT created by nerdctl", DefaultNetworkName) + log.L.Warnf("default network named %q does not have an internal nerdctl ID or nerdctl-managed config file, it was most likely NOT created by nerdctl", DefaultNetworkName) } return nameMatches[0], nil diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index 2f69c2cb595..0e6c7b6c9b5 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -28,11 +28,11 @@ import ( "strings" "github.com/Masterminds/semver/v3" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/defaults" "github.com/containerd/nerdctl/pkg/strutil" "github.com/containerd/nerdctl/pkg/systemutil" "github.com/mitchellh/mapstructure" - "github.com/sirupsen/logrus" "github.com/vishvananda/netlink" ) @@ -184,7 +184,7 @@ func (e *CNIEnv) generateIPAM(driver string, subnetStr, gatewayStr, ipRangeStr s ipamConf.DaemonSocketPath = filepath.Join(defaults.CNIRuntimeDir(), "dhcp.sock") // TODO: support IPAM options for dhcp if err := systemutil.IsSocketAccessible(ipamConf.DaemonSocketPath); err != nil { - logrus.Warnf("cannot access dhcp socket %q (hint: try running with `dhcp daemon --socketpath=%s &` in CNI_PATH to launch the dhcp daemon)", ipamConf.DaemonSocketPath, ipamConf.DaemonSocketPath) + log.L.Warnf("cannot access dhcp socket %q (hint: try running with `dhcp daemon --socketpath=%s &` in CNI_PATH to launch the dhcp daemon)", ipamConf.DaemonSocketPath, ipamConf.DaemonSocketPath) } ipamConfig = ipamConf default: @@ -203,7 +203,7 @@ func fixUpIsolation(e *CNIEnv, name string, plugins []CNIPlugin) []CNIPlugin { if _, err := exec.LookPath(isolationPath); err == nil { // the warning is suppressed for DefaultNetworkName (because multi-bridge networking is not involved) if name != DefaultNetworkName { - logrus.Warnf(`network %q: Using the deprecated CNI "isolation" plugin instead of CNI "firewall" plugin (>= 1.1.0) ingressPolicy. + log.L.Warnf(`network %q: Using the deprecated CNI "isolation" plugin instead of CNI "firewall" plugin (>= 1.1.0) ingressPolicy. To dismiss this warning, uninstall %q and install CNI "firewall" plugin (>= 1.1.0) from https://github.com/containernetworking/plugins`, name, isolationPath) } @@ -211,7 +211,7 @@ To dismiss this warning, uninstall %q and install CNI "firewall" plugin (>= 1.1. for _, f := range plugins { if x, ok := f.(*firewallConfig); ok { if name != DefaultNetworkName { - logrus.Warnf("network %q: Unsetting firewall ingressPolicy %q (because using the deprecated \"isolation\" plugin)", name, x.IngressPolicy) + log.L.Warnf("network %q: Unsetting firewall ingressPolicy %q (because using the deprecated \"isolation\" plugin)", name, x.IngressPolicy) } x.IngressPolicy = "" } @@ -220,10 +220,10 @@ To dismiss this warning, uninstall %q and install CNI "firewall" plugin (>= 1.1. firewallPath := filepath.Join(e.Path, "firewall") ok, err := firewallPluginGEQ110(firewallPath) if err != nil { - logrus.WithError(err).Warnf("Failed to detect whether %q is newer than v1.1.0", firewallPath) + log.L.WithError(err).Warnf("Failed to detect whether %q is newer than v1.1.0", firewallPath) } if !ok { - logrus.Warnf("To isolate bridge networks, CNI plugin \"firewall\" (>= 1.1.0) needs to be installed in CNI_PATH (%q), see https://github.com/containernetworking/plugins", + log.L.Warnf("To isolate bridge networks, CNI plugin \"firewall\" (>= 1.1.0) needs to be installed in CNI_PATH (%q), see https://github.com/containernetworking/plugins", e.Path) } } diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 6e4499a3269..d7a59f00a1a 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -28,6 +28,7 @@ import ( "strings" gocni "github.com/containerd/go-cni" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/bypass4netnsutil" "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" "github.com/containerd/nerdctl/pkg/labels" @@ -165,7 +166,7 @@ func newHandlerOpts(state *specs.State, dataStore, cniPath, cniNetconfPath strin return nil, err } if o.cni == nil { - logrus.Warnf("no CNI network could be loaded from the provided network names: %v", networks) + log.L.Warnf("no CNI network could be loaded from the provided network names: %v", networks) } default: return nil, fmt.Errorf("unexpected network type %v", netType) @@ -300,7 +301,7 @@ func getPortMapOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { ) info, err := opts.rootlessKitClient.Info(context.TODO()) if err != nil { - logrus.WithError(err).Warn("cannot call RootlessKit Info API, make sure you have RootlessKit v0.14.1 or later") + log.L.WithError(err).Warn("cannot call RootlessKit Info API, make sure you have RootlessKit v0.14.1 or later") } else { childIP = info.NetworkDriver.ChildIP portDriverDisallowsLoopbackChildIP = info.PortDriver.DisallowLoopbackChildIP // true for slirp4netns port driver @@ -336,7 +337,7 @@ func getPortMapOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { func getIPAddressOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { if opts.containerIP != "" { if rootlessutil.IsRootlessChild() { - logrus.Debug("container IP assignment is not fully supported in rootless mode. The IP is not accessible from the host (but still accessible from other containers).") + log.L.Debug("container IP assignment is not fully supported in rootless mode. The IP is not accessible from the host (but still accessible from other containers).") } return []gocni.NamespaceOpts{ @@ -483,7 +484,7 @@ func onPostStop(opts *handlerOpts) error { namespaceOpts = append(namespaceOpts, ipAddressOpts...) namespaceOpts = append(namespaceOpts, macAddressOpts...) if err := opts.cni.Remove(ctx, opts.fullID, "", namespaceOpts...); err != nil { - logrus.WithError(err).Errorf("failed to call cni.Remove") + log.L.WithError(err).Errorf("failed to call cni.Remove") return err } hs, err := hostsstore.NewStore(opts.dataStore) diff --git a/pkg/ocihook/ocihook_linux.go b/pkg/ocihook/ocihook_linux.go index eb8d531533b..fd9d7878c85 100644 --- a/pkg/ocihook/ocihook_linux.go +++ b/pkg/ocihook/ocihook_linux.go @@ -18,10 +18,9 @@ package ocihook import ( "github.com/containerd/containerd/contrib/apparmor" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/apparmorutil" "github.com/containerd/nerdctl/pkg/defaults" - - "github.com/sirupsen/logrus" ) func loadAppArmor() { @@ -30,7 +29,7 @@ func loadAppArmor() { } // ensure that the default profile is loaded to the host if err := apparmor.LoadDefaultProfile(defaults.AppArmorProfileName); err != nil { - logrus.WithError(err).Errorf("failed to load AppArmor profile %q", defaults.AppArmorProfileName) + log.L.WithError(err).Errorf("failed to load AppArmor profile %q", defaults.AppArmorProfileName) // We do not abort here. This is by design, and not a security issue. // // If the container is configured to use the default AppArmor profile diff --git a/pkg/portutil/portutil.go b/pkg/portutil/portutil.go index da1c5a8761d..c8c132717e0 100644 --- a/pkg/portutil/portutil.go +++ b/pkg/portutil/portutil.go @@ -23,10 +23,10 @@ import ( "strings" gocni "github.com/containerd/go-cni" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/labels" "github.com/containerd/nerdctl/pkg/rootlessutil" "github.com/docker/go-connections/nat" - "github.com/sirupsen/logrus" ) // return respectively ip, hostPort, containerPort @@ -94,7 +94,7 @@ func ParseFlagP(s string) ([]gocni.PortMapping, error) { if err != nil { return nil, err } - logrus.Debugf("There is no hostPort has been spec in command, the auto allocate port is from %d:%d to %d:%d", startHostPort, startPort, endHostPort, endPort) + log.L.Debugf("There is no hostPort has been spec in command, the auto allocate port is from %d:%d to %d:%d", startHostPort, startPort, endHostPort, endPort) } else { startHostPort, endHostPort, err = nat.ParsePortRange(hostPort) if err != nil { diff --git a/pkg/resolvconf/resolvconf.go b/pkg/resolvconf/resolvconf.go index e776c9f8e40..676fc9fe366 100644 --- a/pkg/resolvconf/resolvconf.go +++ b/pkg/resolvconf/resolvconf.go @@ -35,7 +35,7 @@ import ( "strings" "sync" - "github.com/sirupsen/logrus" + "github.com/containerd/log" ) const ( @@ -78,7 +78,7 @@ func Path() string { ns := GetNameservers(candidateResolvConf, IP) if len(ns) == 1 && ns[0] == "127.0.0.53" { pathAfterSystemdDetection = alternatePath - logrus.Debugf("detected 127.0.0.53 nameserver, assuming systemd-resolved, so using resolv.conf: %s", alternatePath) + log.L.Debugf("detected 127.0.0.53 nameserver, assuming systemd-resolved, so using resolv.conf: %s", alternatePath) } }) return pathAfterSystemdDetection @@ -190,10 +190,10 @@ func FilterResolvDNS(resolvConf []byte, ipv6Enabled bool) (*File, error) { // if the resulting resolvConf has no more nameservers defined, add appropriate // default DNS servers for IPv4 and (optionally) IPv6 if len(GetNameservers(cleanedResolvConf, IP)) == 0 { - logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers: %v", defaultIPv4Dns) + log.L.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers: %v", defaultIPv4Dns) dns := defaultIPv4Dns if ipv6Enabled { - logrus.Infof("IPv6 enabled; Adding default IPv6 external servers: %v", defaultIPv6Dns) + log.L.Infof("IPv6 enabled; Adding default IPv6 external servers: %v", defaultIPv6Dns) dns = append(dns, defaultIPv6Dns...) } cleanedResolvConf = append(cleanedResolvConf, []byte("\n"+strings.Join(dns, "\n"))...) diff --git a/pkg/rootlessutil/parent_linux.go b/pkg/rootlessutil/parent_linux.go index ab9f627af80..42064671984 100644 --- a/pkg/rootlessutil/parent_linux.go +++ b/pkg/rootlessutil/parent_linux.go @@ -26,7 +26,7 @@ import ( "strings" "syscall" - "github.com/sirupsen/logrus" + "github.com/containerd/log" ) func IsRootlessParent() bool { @@ -68,7 +68,7 @@ func ParentMain(hostGatewayIP string) error { return errors.New("should not be called when !IsRootlessParent()") } stateDir, err := RootlessKitStateDir() - logrus.Debugf("stateDir: %s", stateDir) + log.L.Debugf("stateDir: %s", stateDir) if err != nil { return fmt.Errorf("rootless containerd not running? (hint: use `containerd-rootless-setuptool.sh install` to start rootless containerd): %w", err) } @@ -97,7 +97,7 @@ func ParentMain(hostGatewayIP string) error { "-F", // no fork } args = append(args, os.Args...) - logrus.Debugf("rootless parent main: executing %q with %v", arg0, args) + log.L.Debugf("rootless parent main: executing %q with %v", arg0, args) // Env vars corresponds to RootlessKit spec: // https://github.com/rootless-containers/rootlesskit/tree/v0.13.1#environment-variables diff --git a/pkg/signalutil/signals.go b/pkg/signalutil/signals.go index 69126cfb368..f3f627ed315 100644 --- a/pkg/signalutil/signals.go +++ b/pkg/signalutil/signals.go @@ -24,7 +24,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" - "github.com/sirupsen/logrus" + "github.com/containerd/log" ) // killer is from https://github.com/containerd/containerd/blob/v1.7.0-rc.2/cmd/ctr/commands/signals.go#L30-L32 @@ -40,16 +40,16 @@ func ForwardAllSignals(ctx gocontext.Context, task killer) chan os.Signal { go func() { for s := range sigc { if canIgnoreSignal(s) { - logrus.Debugf("Ignoring signal %s", s) + log.G(ctx).Debugf("Ignoring signal %s", s) continue } - logrus.Debug("forwarding signal ", s) + log.G(ctx).Debug("forwarding signal ", s) if err := task.Kill(ctx, s.(syscall.Signal)); err != nil { if errdefs.IsNotFound(err) { - logrus.WithError(err).Debugf("Not forwarding signal %s", s) + log.G(ctx).WithError(err).Debugf("Not forwarding signal %s", s) return } - logrus.WithError(err).Errorf("forward signal %s", s) + log.G(ctx).WithError(err).Errorf("forward signal %s", s) } } }() diff --git a/pkg/signutil/cosignutil.go b/pkg/signutil/cosignutil.go index 0928d4f568a..2932353e0c8 100644 --- a/pkg/signutil/cosignutil.go +++ b/pkg/signutil/cosignutil.go @@ -24,16 +24,16 @@ import ( "os/exec" "strings" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/sirupsen/logrus" ) // SignCosign signs an image(`rawRef`) using a cosign private key (`keyRef`) func SignCosign(rawRef string, keyRef string) error { cosignExecutable, err := exec.LookPath("cosign") if err != nil { - logrus.WithError(err).Error("cosign executable not found in path $PATH") - logrus.Info("you might consider installing cosign from: https://docs.sigstore.dev/cosign/installation") + log.L.WithError(err).Error("cosign executable not found in path $PATH") + log.L.Info("you might consider installing cosign from: https://docs.sigstore.dev/cosign/installation") return err } @@ -50,7 +50,7 @@ func SignCosign(rawRef string, keyRef string) error { cosignCmd.Args = append(cosignCmd.Args, "--yes") cosignCmd.Args = append(cosignCmd.Args, rawRef) - logrus.Debugf("running %s %v", cosignExecutable, cosignCmd.Args) + log.L.Debugf("running %s %v", cosignExecutable, cosignCmd.Args) err = processCosignIO(cosignCmd) if err != nil { @@ -67,7 +67,7 @@ func VerifyCosign(ctx context.Context, rawRef string, keyRef string, hostsDirs [ certIdentity string, certIdentityRegexp string, certOidcIssuer string, certOidcIssuerRegexp string) (string, error) { digest, err := imgutil.ResolveDigest(ctx, rawRef, false, hostsDirs) if err != nil { - logrus.WithError(err).Errorf("unable to resolve digest for an image %s: %v", rawRef, err) + log.G(ctx).WithError(err).Errorf("unable to resolve digest for an image %s: %v", rawRef, err) return rawRef, err } ref := rawRef @@ -75,12 +75,12 @@ func VerifyCosign(ctx context.Context, rawRef string, keyRef string, hostsDirs [ ref += "@" + digest } - logrus.Debugf("verifying image: %s", ref) + log.G(ctx).Debugf("verifying image: %s", ref) cosignExecutable, err := exec.LookPath("cosign") if err != nil { - logrus.WithError(err).Error("cosign executable not found in path $PATH") - logrus.Info("you might consider installing cosign from: https://docs.sigstore.dev/cosign/installation") + log.G(ctx).WithError(err).Error("cosign executable not found in path $PATH") + log.G(ctx).Info("you might consider installing cosign from: https://docs.sigstore.dev/cosign/installation") return ref, err } @@ -114,7 +114,7 @@ func VerifyCosign(ctx context.Context, rawRef string, keyRef string, hostsDirs [ cosignCmd.Args = append(cosignCmd.Args, ref) - logrus.Debugf("running %s %v", cosignExecutable, cosignCmd.Args) + log.G(ctx).Debugf("running %s %v", cosignExecutable, cosignCmd.Args) err = processCosignIO(cosignCmd) if err != nil { @@ -130,11 +130,11 @@ func VerifyCosign(ctx context.Context, rawRef string, keyRef string, hostsDirs [ func processCosignIO(cosignCmd *exec.Cmd) error { stdout, err := cosignCmd.StdoutPipe() if err != nil { - logrus.Warn("cosign: " + err.Error()) + log.L.Warn("cosign: " + err.Error()) } stderr, err := cosignCmd.StderrPipe() if err != nil { - logrus.Warn("cosign: " + err.Error()) + log.L.Warn("cosign: " + err.Error()) } if err := cosignCmd.Start(); err != nil { // only return err if it's critical (cosign start failed.) @@ -143,18 +143,18 @@ func processCosignIO(cosignCmd *exec.Cmd) error { scanner := bufio.NewScanner(stdout) for scanner.Scan() { - logrus.Info("cosign: " + scanner.Text()) + log.L.Info("cosign: " + scanner.Text()) } if err := scanner.Err(); err != nil { - logrus.Warn("cosign: " + err.Error()) + log.L.Warn("cosign: " + err.Error()) } errScanner := bufio.NewScanner(stderr) for errScanner.Scan() { - logrus.Info("cosign: " + errScanner.Text()) + log.L.Info("cosign: " + errScanner.Text()) } if err := errScanner.Err(); err != nil { - logrus.Warn("cosign: " + err.Error()) + log.L.Warn("cosign: " + err.Error()) } return nil diff --git a/pkg/signutil/notationutil.go b/pkg/signutil/notationutil.go index 522ce66f518..b15c80aaf5f 100644 --- a/pkg/signutil/notationutil.go +++ b/pkg/signutil/notationutil.go @@ -23,16 +23,16 @@ import ( "os/exec" "strings" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/sirupsen/logrus" ) // SignNotation signs an image(`rawRef`) using a notation key name (`keyNameRef`) func SignNotation(rawRef string, keyNameRef string) error { notationExecutable, err := exec.LookPath("notation") if err != nil { - logrus.WithError(err).Error("notation executable not found in path $PATH") - logrus.Info("you might consider installing notation from: https://notaryproject.dev/docs/installation/cli/") + log.L.WithError(err).Error("notation executable not found in path $PATH") + log.L.Info("you might consider installing notation from: https://notaryproject.dev/docs/installation/cli/") return err } @@ -46,7 +46,7 @@ func SignNotation(rawRef string, keyNameRef string) error { notationCmd.Args = append(notationCmd.Args, rawRef) - logrus.Debugf("running %s %v", notationExecutable, notationCmd.Args) + log.L.Debugf("running %s %v", notationExecutable, notationCmd.Args) err = processNotationIO(notationCmd) if err != nil { @@ -61,7 +61,7 @@ func SignNotation(rawRef string, keyNameRef string) error { func VerifyNotation(ctx context.Context, rawRef string, hostsDirs []string) (string, error) { digest, err := imgutil.ResolveDigest(ctx, rawRef, false, hostsDirs) if err != nil { - logrus.WithError(err).Errorf("unable to resolve digest for an image %s: %v", rawRef, err) + log.G(ctx).WithError(err).Errorf("unable to resolve digest for an image %s: %v", rawRef, err) return rawRef, err } ref := rawRef @@ -69,12 +69,12 @@ func VerifyNotation(ctx context.Context, rawRef string, hostsDirs []string) (str ref += "@" + digest } - logrus.Debugf("verifying image: %s", ref) + log.G(ctx).Debugf("verifying image: %s", ref) notationExecutable, err := exec.LookPath("notation") if err != nil { - logrus.WithError(err).Error("notation executable not found in path $PATH") - logrus.Info("you might consider installing notation from: https://notaryproject.dev/docs/installation/cli/") + log.G(ctx).WithError(err).Error("notation executable not found in path $PATH") + log.G(ctx).Info("you might consider installing notation from: https://notaryproject.dev/docs/installation/cli/") return ref, err } @@ -83,7 +83,7 @@ func VerifyNotation(ctx context.Context, rawRef string, hostsDirs []string) (str notationCmd.Args = append(notationCmd.Args, ref) - logrus.Debugf("running %s %v", notationExecutable, notationCmd.Args) + log.G(ctx).Debugf("running %s %v", notationExecutable, notationCmd.Args) err = processNotationIO(notationCmd) if err != nil { @@ -99,11 +99,11 @@ func VerifyNotation(ctx context.Context, rawRef string, hostsDirs []string) (str func processNotationIO(notationCmd *exec.Cmd) error { stdout, err := notationCmd.StdoutPipe() if err != nil { - logrus.Warn("notation: " + err.Error()) + log.L.Warn("notation: " + err.Error()) } stderr, err := notationCmd.StderrPipe() if err != nil { - logrus.Warn("notation: " + err.Error()) + log.L.Warn("notation: " + err.Error()) } if err := notationCmd.Start(); err != nil { // only return err if it's critical (notation start failed.) @@ -112,18 +112,18 @@ func processNotationIO(notationCmd *exec.Cmd) error { scanner := bufio.NewScanner(stdout) for scanner.Scan() { - logrus.Info("notation: " + scanner.Text()) + log.L.Info("notation: " + scanner.Text()) } if err := scanner.Err(); err != nil { - logrus.Warn("notation: " + err.Error()) + log.L.Warn("notation: " + err.Error()) } errScanner := bufio.NewScanner(stderr) for errScanner.Scan() { - logrus.Info("notation: " + errScanner.Text()) + log.L.Info("notation: " + errScanner.Text()) } if err := errScanner.Err(); err != nil { - logrus.Warn("notation: " + err.Error()) + log.L.Warn("notation: " + err.Error()) } return nil diff --git a/pkg/signutil/signutil.go b/pkg/signutil/signutil.go index 716816e1fc2..d599458048c 100644 --- a/pkg/signutil/signutil.go +++ b/pkg/signutil/signutil.go @@ -20,8 +20,8 @@ import ( "context" "fmt" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" - "github.com/sirupsen/logrus" ) // Sign signs an image using a signer and options provided in options. @@ -44,7 +44,7 @@ func Sign(rawRef string, experimental bool, options types.ImageSignOptions) erro return err } case "", "none": - logrus.Debugf("signing process skipped") + log.L.Debugf("signing process skipped") default: return fmt.Errorf("no signers found: %s", options.Provider) } @@ -72,7 +72,7 @@ func Verify(ctx context.Context, rawRef string, hostsDirs []string, experimental } case "", "none": ref = rawRef - logrus.Debugf("verifying process skipped") + log.G(ctx).Debugf("verifying process skipped") default: return "", fmt.Errorf("no verifiers found: %s", options.Provider) } diff --git a/pkg/snapshotterutil/sociutil.go b/pkg/snapshotterutil/sociutil.go index 7c01ed3d666..5a4043ac9e6 100644 --- a/pkg/snapshotterutil/sociutil.go +++ b/pkg/snapshotterutil/sociutil.go @@ -23,16 +23,16 @@ import ( "strconv" "strings" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/api/types" - "github.com/sirupsen/logrus" ) // CreateSoci creates a SOCI index(`rawRef`) func CreateSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, platforms []string, sOpts types.SociOptions) error { sociExecutable, err := exec.LookPath("soci") if err != nil { - logrus.WithError(err).Error("soci executable not found in path $PATH") - logrus.Info("you might consider installing soci from: https://github.com/awslabs/soci-snapshotter/blob/main/docs/install.md") + log.L.WithError(err).Error("soci executable not found in path $PATH") + log.L.Info("you might consider installing soci from: https://github.com/awslabs/soci-snapshotter/blob/main/docs/install.md") return err } @@ -68,7 +68,7 @@ func CreateSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform boo // --timeout, --debug, --content-store sociCmd.Args = append(sociCmd.Args, rawRef) - logrus.Debugf("running %s %v", sociExecutable, sociCmd.Args) + log.L.Debugf("running %s %v", sociExecutable, sociCmd.Args) err = processSociIO(sociCmd) if err != nil { @@ -81,12 +81,12 @@ func CreateSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform boo // PushSoci pushes a SOCI index(`rawRef`) // `hostsDirs` are used to resolve image `rawRef` func PushSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, platforms []string) error { - logrus.Debugf("pushing SOCI index: %s", rawRef) + log.L.Debugf("pushing SOCI index: %s", rawRef) sociExecutable, err := exec.LookPath("soci") if err != nil { - logrus.WithError(err).Error("soci executable not found in path $PATH") - logrus.Info("you might consider installing soci from: https://github.com/awslabs/soci-snapshotter/blob/main/docs/install.md") + log.L.WithError(err).Error("soci executable not found in path $PATH") + log.L.Info("you might consider installing soci from: https://github.com/awslabs/soci-snapshotter/blob/main/docs/install.md") return err } @@ -123,7 +123,7 @@ func PushSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, } sociCmd.Args = append(sociCmd.Args, rawRef) - logrus.Debugf("running %s %v", sociExecutable, sociCmd.Args) + log.L.Debugf("running %s %v", sociExecutable, sociCmd.Args) err = processSociIO(sociCmd) if err != nil { @@ -135,11 +135,11 @@ func PushSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, func processSociIO(sociCmd *exec.Cmd) error { stdout, err := sociCmd.StdoutPipe() if err != nil { - logrus.Warn("soci: " + err.Error()) + log.L.Warn("soci: " + err.Error()) } stderr, err := sociCmd.StderrPipe() if err != nil { - logrus.Warn("soci: " + err.Error()) + log.L.Warn("soci: " + err.Error()) } if err := sociCmd.Start(); err != nil { // only return err if it's critical (soci command failed to start.) @@ -148,18 +148,18 @@ func processSociIO(sociCmd *exec.Cmd) error { scanner := bufio.NewScanner(stdout) for scanner.Scan() { - logrus.Info("soci: " + scanner.Text()) + log.L.Info("soci: " + scanner.Text()) } if err := scanner.Err(); err != nil { - logrus.Warn("soci: " + err.Error()) + log.L.Warn("soci: " + err.Error()) } errScanner := bufio.NewScanner(stderr) for errScanner.Scan() { - logrus.Info("soci: " + errScanner.Text()) + log.L.Info("soci: " + errScanner.Text()) } if err := errScanner.Err(); err != nil { - logrus.Warn("soci: " + err.Error()) + log.L.Warn("soci: " + err.Error()) } return nil diff --git a/pkg/tarutil/tarutil.go b/pkg/tarutil/tarutil.go index 74019144d49..eb7b4600cf2 100644 --- a/pkg/tarutil/tarutil.go +++ b/pkg/tarutil/tarutil.go @@ -22,7 +22,7 @@ import ( "os/exec" "strings" - "github.com/sirupsen/logrus" + "github.com/containerd/log" ) // FindTarBinary returns a path to the tar binary and whether it is GNU tar. @@ -30,11 +30,11 @@ func FindTarBinary() (string, bool, error) { isGNU := func(exe string) bool { v, err := exec.Command(exe, "--version").Output() if err != nil { - logrus.Warnf("Failed to detect whether %q is GNU tar or not", exe) + log.L.Warnf("Failed to detect whether %q is GNU tar or not", exe) return false } if !strings.Contains(string(v), "GNU tar") { - logrus.Warnf("%q does not seem GNU tar", exe) + log.L.Warnf("%q does not seem GNU tar", exe) return false } return true diff --git a/pkg/taskutil/taskutil.go b/pkg/taskutil/taskutil.go index 1f6fae17f2f..62e622f716f 100644 --- a/pkg/taskutil/taskutil.go +++ b/pkg/taskutil/taskutil.go @@ -30,9 +30,9 @@ import ( "github.com/containerd/console" "github.com/containerd/containerd" "github.com/containerd/containerd/cio" + "github.com/containerd/log" "github.com/containerd/nerdctl/pkg/consoleutil" "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/sirupsen/logrus" "golang.org/x/term" ) @@ -52,14 +52,14 @@ func NewTask(ctx context.Context, client *containerd.Client, container container // [1] https://github.com/containerd/containerd/blob/8f756bc8c26465bd93e78d9cd42082b66f276e10/cio/io.go#L358-L359 io := t.IO() if io == nil { - logrus.Errorf("got a nil io") + log.G(ctx).Errorf("got a nil io") return } io.Cancel() } var ioCreator cio.Creator if flagA { - logrus.Debug("attaching output instead of using the log-uri") + log.G(ctx).Debug("attaching output instead of using the log-uri") if flagT { in, err := consoleutil.NewDetachableStdin(con, detachKeys, closer) if err != nil { @@ -120,15 +120,15 @@ func NewTask(ctx context.Context, client *containerd.Client, container container var in io.Reader if flagI { if sv, err := infoutil.ServerSemVer(ctx, client); err != nil { - logrus.Warn(err) + log.G(ctx).Warn(err) } else if sv.LessThan(semver.MustParse("1.6.0-0")) { - logrus.Warnf("`nerdctl (run|exec) -i` without `-t` expects containerd 1.6 or later, got containerd %v", sv) + log.G(ctx).Warnf("`nerdctl (run|exec) -i` without `-t` expects containerd 1.6 or later, got containerd %v", sv) } var stdinC io.ReadCloser = &StdinCloser{ Stdin: os.Stdin, Closer: func() { if t, err := container.Task(ctx, nil); err != nil { - logrus.WithError(err).Debugf("failed to get task for StdinCloser") + log.G(ctx).WithError(err).Debugf("failed to get task for StdinCloser") } else { t.CloseIO(ctx, containerd.WithStdinCloser) } From 41f2647a10065260266ed9aada182b600918fd72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 22:39:57 +0000 Subject: [PATCH 0179/1066] build(deps): bump github.com/klauspost/compress from 1.17.0 to 1.17.1 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.0 to 1.17.1. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.0...v1.17.1) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f4d5729d8c6..aae8d6db298 100644 --- a/go.mod +++ b/go.mod @@ -88,7 +88,7 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.0 + github.com/klauspost/compress v1.17.1 github.com/klauspost/cpuid/v2 v2.1.1 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/go.sum b/go.sum index 3d67a507892..2e5d0c96f97 100644 --- a/go.sum +++ b/go.sum @@ -168,8 +168,8 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g= +github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0= From 6c8ea8bcf837329504248b4186b91e313e4a0577 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Oct 2023 22:04:34 +0000 Subject: [PATCH 0180/1066] build(deps): bump actions/checkout from 4.1.0 to 4.1.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.0...v4.1.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 20 +++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index f1672c0699f..b9d6f1f2b16 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.0 + uses: actions/checkout@v4.1.1 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2129a87e2fd..689f1eab8c7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 - uses: actions/setup-go@v4 with: go-version: 1.21.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a34d94e642e..2a1b4d7b647 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -88,7 +88,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -141,7 +141,7 @@ jobs: CONTAINERD_VERSION: "${{ matrix.containerd }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -158,7 +158,7 @@ jobs: matrix: go-version: ["1.20.x", "1.21.x"] steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -173,7 +173,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 30 steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -209,7 +209,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - uses: actions/setup-go@v4 @@ -218,7 +218,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 with: repository: containerd/containerd ref: v1.7.7 @@ -243,7 +243,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.0 + - uses: actions/checkout@v4.1.1 - uses: actions/cache@v3 with: path: /root/.vagrant.d From 8c2610a18048b75e798e5cd553dfcf2926d9ee36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Oct 2023 22:38:43 +0000 Subject: [PATCH 0181/1066] build(deps): bump github.com/mattn/go-isatty from 0.0.19 to 0.0.20 Bumps [github.com/mattn/go-isatty](https://github.com/mattn/go-isatty) from 0.0.19 to 0.0.20. - [Commits](https://github.com/mattn/go-isatty/compare/v0.0.19...v0.0.20) --- updated-dependencies: - dependency-name: github.com/mattn/go-isatty dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index aae8d6db298..94d0809c9bd 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/fatih/color v1.15.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/ipfs/go-cid v0.4.1 - github.com/mattn/go-isatty v0.0.19 + github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/mapstructure v1.5.0 github.com/moby/sys/mount v0.3.3 github.com/moby/sys/signal v0.7.0 diff --git a/go.sum b/go.sum index 2e5d0c96f97..1ef28ee71d9 100644 --- a/go.sum +++ b/go.sum @@ -181,8 +181,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= From 35a7920adc9c1d991abdd67c841b6bf93b84b015 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Oct 2023 22:38:52 +0000 Subject: [PATCH 0182/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.11.1 to 0.11.2 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.11.1 to 0.11.2. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.11.1...v0.11.2) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index aae8d6db298..db96c542b10 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 - github.com/Microsoft/hcsshim v0.11.1 + github.com/Microsoft/hcsshim v0.11.2 github.com/awslabs/soci-snapshotter v0.4.0 github.com/compose-spec/compose-go v1.19.0 github.com/containerd/accelerated-container-image v1.0.0 diff --git a/go.sum b/go.sum index 2e5d0c96f97..d34bbb12098 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 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.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= -github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= +github.com/Microsoft/hcsshim v0.11.2 h1:63w4x0s9PjbJGGTQTNgCTExPCkyDXhx2AUVQDPDBAek= +github.com/Microsoft/hcsshim v0.11.2/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/awslabs/soci-snapshotter v0.4.0 h1:dA9lOYbzSUaYMahB8qXQZTVXUszhc0w8rwjRs6EPd24= github.com/awslabs/soci-snapshotter v0.4.0/go.mod h1:+ST8F4E/b6b6pnFBJKprdvzkxyXODMs0FC2TmclkgJc= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= From f51e06d2b9427472ffa71671879a3fcd4556bf78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 22:18:44 +0000 Subject: [PATCH 0183/1066] build(deps): bump github.com/compose-spec/compose-go Bumps [github.com/compose-spec/compose-go](https://github.com/compose-spec/compose-go) from 1.19.0 to 1.20.0. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v1.19.0...v1.20.0) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7a988f3548d..0f5add44294 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.11.2 github.com/awslabs/soci-snapshotter v0.4.0 - github.com/compose-spec/compose-go v1.19.0 + github.com/compose-spec/compose-go v1.20.0 github.com/containerd/accelerated-container-image v1.0.0 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 diff --git a/go.sum b/go.sum index 03ceebe79fb..c5d8913bcda 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go v1.19.0 h1:t68gAcwStDg0hy2kFvqHJIksf6xkqRnlSKfL45/ETqo= -github.com/compose-spec/compose-go v1.19.0/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= +github.com/compose-spec/compose-go v1.20.0 h1:h4ZKOst1EF/DwZp7dWkb+wbTVE4nEyT9Lc89to84Ol4= +github.com/compose-spec/compose-go v1.20.0/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= github.com/containerd/accelerated-container-image v1.0.0 h1:BWc+VNimtSXUCiegKWhqcHxN9GV4ve3kJEL1968AWF8= github.com/containerd/accelerated-container-image v1.0.0/go.mod h1:LYLT4rKKzJn9Ts0I8uk1pivFmqil/Y3WZT0u+9zb6BA= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= From 0af5badb87e6f50b4483d18190a27da69f70ae88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 22:18:49 +0000 Subject: [PATCH 0184/1066] build(deps): bump tonistiigi/xx from 1.2.1 to 1.3.0 Bumps tonistiigi/xx from 1.2.1 to 1.3.0. --- updated-dependencies: - dependency-name: tonistiigi/xx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6763145415b..bdfbf14bbb9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,7 +51,7 @@ ARG GOTESTSUM_VERSION=v1.11.0 ARG NYDUS_VERSION=v2.2.3 ARG SOCI_SNAPSHOTTER_VERSION=0.4.0 -FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.2.1 AS xx +FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.3.0 AS xx FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bullseye AS build-base-debian From 8a5177c786518effb104af80fec1d94949ed9fa1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 22:18:52 +0000 Subject: [PATCH 0185/1066] build(deps): bump github.com/containerd/continuity from 0.4.2 to 0.4.3 Bumps [github.com/containerd/continuity](https://github.com/containerd/continuity) from 0.4.2 to 0.4.3. - [Release notes](https://github.com/containerd/continuity/releases) - [Commits](https://github.com/containerd/continuity/compare/v0.4.2...v0.4.3) --- updated-dependencies: - dependency-name: github.com/containerd/continuity dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7a988f3548d..ae239d89b9c 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.7.7 - github.com/containerd/continuity v0.4.2 + github.com/containerd/continuity v0.4.3 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 github.com/containerd/log v0.1.0 diff --git a/go.sum b/go.sum index 03ceebe79fb..6e49b4f58a6 100644 --- a/go.sum +++ b/go.sum @@ -38,8 +38,8 @@ github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARu github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.7.7 h1:QOC2K4A42RQpcrZyptP6z9EJZnlHfHJUfZrAAHe15q4= github.com/containerd/containerd v1.7.7/go.mod h1:3c4XZv6VeT9qgf9GMTxNTMFxGJrGpI2vz1yk4ye+YY8= -github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= -github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +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/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= From a97162edac64741795066a45226286fc808f3e08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 22:03:40 +0000 Subject: [PATCH 0186/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.2 to 0.13.3. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.2...v0.13.3) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 661c54ec800..f007f7f2500 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.2 + github.com/containerd/nydus-snapshotter v0.13.3 github.com/containerd/stargz-snapshotter v0.14.3 github.com/containerd/stargz-snapshotter/estargz v0.14.3 github.com/containerd/stargz-snapshotter/ipfs v0.14.3 diff --git a/go.sum b/go.sum index 8f40b671077..319bc05ef48 100644 --- a/go.sum +++ b/go.sum @@ -48,8 +48,8 @@ github.com/containerd/imgcrypt v1.1.8 h1:ZS7TuywcRNLoHpU0g+v4/PsKynl6TYlw5xDVWWo github.com/containerd/imgcrypt v1.1.8/go.mod h1:x6QvFIkMyO2qGIY2zXc88ivEzcbgvLdWjoZyGqDap5U= 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.2 h1:Wjc59CetOv9TxtQIvSBY1wrjHxwD48gHR/TxyEeRTmI= -github.com/containerd/nydus-snapshotter v0.13.2/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= +github.com/containerd/nydus-snapshotter v0.13.3 h1:aa4tz0l2Z+vLDuCCx5Ic6f1AQd9ZH/R0B5C/QXGY774= +github.com/containerd/nydus-snapshotter v0.13.3/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= github.com/containerd/stargz-snapshotter v0.14.3/go.mod h1:j2Ya4JeA5gMZJr8BchSkPjlcCEh++auAxp4nidPI6N0= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= From 108542495a640e6d7f6da5ed822a544e951384f5 Mon Sep 17 00:00:00 2001 From: Olly Pomeroy Date: Fri, 20 Oct 2023 15:13:14 +0100 Subject: [PATCH 0187/1066] docs: minor soci push fix Signed-off-by: Olly Pomeroy --- docs/soci.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/soci.md b/docs/soci.md index 8ba5035bee8..67fbe92f584 100644 --- a/docs/soci.md +++ b/docs/soci.md @@ -21,7 +21,7 @@ See https://github.com/awslabs/soci-snapshotter to learn further information. ## Enable SOCI for `nerdctl run` and `nerdctl pull` | :zap: Requirement | nerdctl >= 1.5.0 | -| ----------------- |------------------| +| ----------------- | ---------------- | - Run `nerdctl` with `--snapshotter=soci` ```console @@ -38,10 +38,10 @@ For images that already have SOCI indices, see https://gallery.ecr.aws/soci-work ## Enable SOCI for `nerdctl push` | :zap: Requirement | nerdctl >= 1.6.0 | -| ----------------- |------------------| +| ----------------- | ---------------- | - Push the image with SOCI index. Adding `--snapshotter=soci` arg to `nerdctl pull`, `nerdctl` will create the SOCI index and push the index to same destination as the image. ```console -nerdctl push --snapshotter=soci push --soci-span-size=2097152 --soci-min-layer-size=20971520 public.ecr.aws/my-registry/my-repo:latest +nerdctl push --snapshotter=soci --soci-span-size=2097152 --soci-min-layer-size=20971520 public.ecr.aws/my-registry/my-repo:latest ``` --soci-span-size and --soci-min-layer-size are two properties to customize the SOCI index. See [Command Reference](https://github.com/containerd/nerdctl/blob/377b2077bb616194a8ef1e19ccde32aa1ffd6c84/docs/command-reference.md?plain=1#L773) for further details. From 1c41c10f36ccd6c2d6b52eecbb484d882413367b Mon Sep 17 00:00:00 2001 From: TinaMor Date: Wed, 18 Oct 2023 13:39:43 +0300 Subject: [PATCH 0188/1066] Replace logrus.SetOutput() with log.L.Logger.SetOutput() This is a followup from commit#63d446f18119bd0fedf903aea29089bb46a8e017 to complete the replacement of logrus package with https://github.com/containerd/log Signed-off-by: Christine Murimi --- go.mod | 2 +- pkg/ocihook/ocihook.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f007f7f2500..745c76a8ba7 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,6 @@ require ( github.com/pelletier/go-toml/v2 v2.1.0 github.com/rootless-containers/bypass4netns v0.3.0 github.com/rootless-containers/rootlesskit v1.1.1 - github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/tidwall/gjson v1.17.0 @@ -112,6 +111,7 @@ require ( github.com/pelletier/go-toml v1.9.5 // indirect github.com/philhofer/fwd v1.1.1 // indirect 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/tidwall/match v1.1.1 // indirect diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index d7a59f00a1a..2b5a6aa956e 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -41,7 +41,6 @@ import ( b4nndclient "github.com/rootless-containers/bypass4netns/pkg/api/daemon/client" rlkclient "github.com/rootless-containers/rootlesskit/pkg/api/client" - "github.com/sirupsen/logrus" ) const ( @@ -80,7 +79,7 @@ func Run(stdin io.Reader, stderr io.Writer, event, dataStore, cniPath, cniNetcon return err } defer logFile.Close() - logrus.SetOutput(io.MultiWriter(stderr, logFile)) + log.L.Logger.SetOutput(io.MultiWriter(stderr, logFile)) opts, err := newHandlerOpts(&state, dataStore, cniPath, cniNetconfPath) if err != nil { From 5d18f61d05c0f64a3b7fb932702b44aac11d508d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 22:38:28 +0000 Subject: [PATCH 0189/1066] build(deps): bump github.com/klauspost/compress from 1.17.1 to 1.17.2 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.1 to 1.17.2. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.1...v1.17.2) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 745c76a8ba7..576068f9f38 100644 --- a/go.mod +++ b/go.mod @@ -87,7 +87,7 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.1 + github.com/klauspost/compress v1.17.2 github.com/klauspost/cpuid/v2 v2.1.1 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/go.sum b/go.sum index 319bc05ef48..4295e70de7f 100644 --- a/go.sum +++ b/go.sum @@ -168,8 +168,8 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g= -github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0= From 359668452f1019d752487f629f5e2e356d830240 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Wed, 25 Oct 2023 14:05:46 +0000 Subject: [PATCH 0190/1066] support ip-masq option Signed-off-by: Kay Yan --- pkg/netutil/netutil_unix.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index 0e6c7b6c9b5..b75bf62a6c4 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -25,6 +25,7 @@ import ( "net" "os/exec" "path/filepath" + "strconv" "strings" "github.com/Masterminds/semver/v3" @@ -94,6 +95,7 @@ func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string] switch driver { case "bridge": mtu := 0 + iPMasq := true for opt, v := range opts { switch opt { case "mtu", "com.docker.network.driver.mtu": @@ -101,6 +103,11 @@ func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string] if err != nil { return nil, err } + case "ip-masq", "com.docker.network.bridge.enable_ip_masquerade": + iPMasq, err = strconv.ParseBool(v) + if err != nil { + return nil, err + } default: return nil, fmt.Errorf("unsupported %q network option %q", driver, opt) } @@ -114,7 +121,7 @@ func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string] bridge.MTU = mtu bridge.IPAM = ipam bridge.IsGW = true - bridge.IPMasq = true + bridge.IPMasq = iPMasq bridge.HairpinMode = true plugins = []CNIPlugin{bridge, newPortMapPlugin(), newFirewallPlugin(), newTuningPlugin()} plugins = fixUpIsolation(e, name, plugins) From caea0f9196edcb4e9d1cfb1d2803e867cb1115dd Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Wed, 25 Oct 2023 19:31:25 +0000 Subject: [PATCH 0191/1066] fix ps format names Signed-off-by: Kay Yan --- cmd/nerdctl/container_list.go | 6 +----- cmd/nerdctl/container_list_linux_test.go | 18 ++++++++++++++++++ pkg/cmd/container/list.go | 4 ++-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container_list.go index f203900a2e0..f0ac6fd6a3c 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container_list.go @@ -202,10 +202,6 @@ func formatAndPrintContainerInfo(containers []container.ListItem, options Format return err } } else { - var name string - if len(c.Names) > 0 { - name = c.Names[0] - } format := "%s\t%s\t%s\t%s\t%s\t%s\t%s" args := []interface{}{ c.ID, @@ -214,7 +210,7 @@ func formatAndPrintContainerInfo(containers []container.ListItem, options Format formatter.TimeSinceInHuman(c.CreatedAt), c.Status, c.Ports, - name, + c.Names, } if wide { format += "\t%s\t%s\t%s\n" diff --git a/cmd/nerdctl/container_list_linux_test.go b/cmd/nerdctl/container_list_linux_test.go index d7b04a3f005..a065ce289af 100644 --- a/cmd/nerdctl/container_list_linux_test.go +++ b/cmd/nerdctl/container_list_linux_test.go @@ -223,6 +223,24 @@ func TestContainerListWithLabels(t *testing.T) { }) } +func TestContainerListWithNames(t *testing.T) { + base, testContainer := preparePsTestContainer(t, "listWithNames", true) + + // hope there are no tests running parallel + base.Cmd("ps", "-n", "1", "--format", "{{.Names}}").AssertOutWithFunc(func(stdout string) error { + + // An example of nerdctl ps --format "{{.Names}}" + lines := strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) != 1 { + return fmt.Errorf("expected 1 line, got %d", len(lines)) + } + + assert.Equal(t, lines[0], testContainer.name) + + return nil + }) +} + func TestContainerListWithFilter(t *testing.T) { base, testContainerA := preparePsTestContainer(t, "listWithFilterA", true) _, testContainerB := preparePsTestContainer(t, "listWithFilterB", true) diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index c05989365ec..a06ee8347be 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -92,7 +92,7 @@ type ListItem struct { ID string Image string Platform string // nerdctl extension - Names []string + Names string Ports string Status string Runtime string // nerdctl extension @@ -130,7 +130,7 @@ func prepareContainers(ctx context.Context, client *containerd.Client, container ID: id, Image: info.Image, Platform: info.Labels[labels.Platform], - Names: []string{getContainerName(info.Labels)}, + Names: getContainerName(info.Labels), Ports: formatter.FormatPorts(info.Labels), Status: formatter.ContainerStatus(ctx, c), Runtime: info.Runtime.Name, From ae17b4865d0381c6b58e13b9efe7db6e57c354c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 22:46:30 +0000 Subject: [PATCH 0192/1066] build(deps): bump google.golang.org/grpc from 1.56.2 to 1.56.3 Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.56.2 to 1.56.3. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.56.2...v1.56.3) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 576068f9f38..d8c00edc713 100644 --- a/go.mod +++ b/go.mod @@ -131,7 +131,7 @@ require ( golang.org/x/tools v0.11.0 // indirect google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect - google.golang.org/grpc v1.56.2 // indirect + google.golang.org/grpc v1.56.3 // indirect google.golang.org/protobuf v1.31.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/go.sum b/go.sum index 4295e70de7f..d42d946bb2d 100644 --- a/go.sum +++ b/go.sum @@ -435,8 +435,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= -google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 0b977127a27810d422313436e266c0a12e2c4260 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 26 Oct 2023 12:41:21 +0000 Subject: [PATCH 0193/1066] Vagrantfile.freebsd: pin generic/freebsd13 to version 4.3.2 The latest version (v4.3.4) is currently broken Fix issue 2596 Carry PR 2597 (originally submitted by yankay) Co-authored-by: Kay Yan Signed-off-by: Akihiro Suda --- Vagrantfile.freebsd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Vagrantfile.freebsd b/Vagrantfile.freebsd index 08db3dddc4f..1aaadf5d6d9 100644 --- a/Vagrantfile.freebsd +++ b/Vagrantfile.freebsd @@ -18,6 +18,8 @@ # Vagrantfile for FreeBSD Vagrant.configure("2") do |config| config.vm.box = "generic/freebsd13" + # workaround for https://github.com/containerd/nerdctl/issues/2596 + config.vm.box_version = "4.3.2" memory = 2048 cpus = 1 From 161bf2055de17ae5cd2daeeb1edc8a85ae8083d4 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sat, 28 Oct 2023 00:30:25 +0900 Subject: [PATCH 0194/1066] compose_config_test: workaround for Docker Compose v2.23.0 The test for `docker compose config --hash=*` has to be temporarily skipped, as `docker compose config --hash=*` is broken in Docker Compose v2.23.0 (docker/compose issue 11145) Fix issue 2605 Signed-off-by: Akihiro Suda --- cmd/nerdctl/compose_config_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/compose_config_test.go b/cmd/nerdctl/compose_config_test.go index 705d467cb8f..29d371e98e4 100644 --- a/cmd/nerdctl/compose_config_test.go +++ b/cmd/nerdctl/compose_config_test.go @@ -68,7 +68,11 @@ services: comp := testutil.NewComposeDir(t, fmt.Sprintf(dockerComposeYAML, "3.13")) defer comp.CleanUp() - base.ComposeCmd("-f", comp.YAMLFullPath(), "config", "--hash=*").AssertOutContains("hello1") + // `--hash=*` is broken in Docker Compose v2.23.0: https://github.com/docker/compose/issues/11145 + if base.Target == testutil.Nerdctl { + base.ComposeCmd("-f", comp.YAMLFullPath(), "config", "--hash=*").AssertOutContains("hello1") + } + hash := base.ComposeCmd("-f", comp.YAMLFullPath(), "config", "--hash=hello1").Out() newComp := testutil.NewComposeDir(t, fmt.Sprintf(dockerComposeYAML, "3.14")) From 5964002522235ca692fae03e7f6fba144b82cf10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Oct 2023 16:48:36 +0000 Subject: [PATCH 0195/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 24.0.6+incompatible to 24.0.7+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v24.0.6...v24.0.7) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d8c00edc713..973b0e12518 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.4 github.com/docker/cli v24.0.6+incompatible - github.com/docker/docker v24.0.6+incompatible + github.com/docker/docker v24.0.7+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.0 diff --git a/go.sum b/go.sum index d42d946bb2d..d1335394ded 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ 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.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= -github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= +github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= From 63b8df5eec7de91529b5b77a0e249c2301493302 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Oct 2023 16:49:48 +0000 Subject: [PATCH 0196/1066] build(deps): bump github.com/containerd/containerd from 1.7.7 to 1.7.8 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.7 to 1.7.8. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.7...v1.7.8) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index d8c00edc713..874351fde0f 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.0.0 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 - github.com/containerd/containerd v1.7.7 + github.com/containerd/containerd v1.7.8 github.com/containerd/continuity v0.4.3 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.8 @@ -131,7 +131,7 @@ require ( golang.org/x/tools v0.11.0 // indirect google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect - google.golang.org/grpc v1.56.3 // indirect + google.golang.org/grpc v1.58.3 // indirect google.golang.org/protobuf v1.31.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/go.sum b/go.sum index d42d946bb2d..2ab55934c61 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKk github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.7 h1:QOC2K4A42RQpcrZyptP6z9EJZnlHfHJUfZrAAHe15q4= -github.com/containerd/containerd v1.7.7/go.mod h1:3c4XZv6VeT9qgf9GMTxNTMFxGJrGpI2vz1yk4ye+YY8= +github.com/containerd/containerd v1.7.8 h1:RkwgOW3AVUT3H/dyT0W03Dc8AzlpMG65lX48KftOFSM= +github.com/containerd/containerd v1.7.8/go.mod h1:L/Hn9qylJtUFT7cPeM0Sr3fATj+WjHwRQ0lyrYk3OPY= 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/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= @@ -435,8 +435,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 792a0cb108317d8ffe3dfefbdb853b36c2962eef Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Mon, 23 Oct 2023 22:48:03 +0200 Subject: [PATCH 0197/1066] support running container with network id Signed-off-by: fahed dorgaa --- cmd/nerdctl/container_run_network_linux_test.go | 7 +++++++ pkg/netutil/netutil.go | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index 693f3d1db58..9f0046ad143 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -42,6 +42,7 @@ func TestRunInternetConnectivity(t *testing.T) { type testCase struct { args []string } + customNetID := base.InspectNetwork(customNet).ID testCases := []testCase{ { args: []string{"--net", "bridge"}, @@ -49,6 +50,12 @@ func TestRunInternetConnectivity(t *testing.T) { { args: []string{"--net", customNet}, }, + { + args: []string{"--net", customNetID}, + }, + { + args: []string{"--net", customNetID[:12]}, + }, { args: []string{"--net", "host"}, }, diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 0279c6e0bbe..962bcc665bf 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -165,6 +165,14 @@ func (e *CNIEnv) NetworkMap() (map[string]*NetworkConfig, error) { //nolint:revi log.L.Warnf("duplicate network name %q, %#v will get superseded by %#v", n.Name, original, n) } m[n.Name] = n + if n.NerdctlID != nil { + id := *n.NerdctlID + m[id] = n + if len(id) > 12 { + id = id[:12] + m[id] = n + } + } } return m, nil } From fff98e3526eea8208682609b7588effe25a7dd03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 28 Oct 2023 02:43:48 +0000 Subject: [PATCH 0198/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 24.0.6+incompatible to 24.0.7+incompatible. - [Commits](https://github.com/docker/cli/compare/v24.0.6...v24.0.7) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 973b0e12518..fe8a317fd5b 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.4 - github.com/docker/cli v24.0.6+incompatible + github.com/docker/cli v24.0.7+incompatible github.com/docker/docker v24.0.7+incompatible github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index d1335394ded..cbbd1d18c76 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,8 @@ github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK github.com/distribution/reference v0.5.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.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= -github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v24.0.7+incompatible h1:wa/nIwYFW7BVTGa7SWPVyyXU9lgORqUb1xfI36MSkFg= +github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= From 55987ae916c9f33593668932a2b518d580c03107 Mon Sep 17 00:00:00 2001 From: Marco Verlato Date: Thu, 26 Oct 2023 13:13:39 +0000 Subject: [PATCH 0199/1066] Add support to CernVM-FS Snapshotter Signed-off-by: Marco Verlato --- docs/cvmfs.md | 89 ++++++++++++++++++++++++++++++++++++++ pkg/imgutil/snapshotter.go | 2 + 2 files changed, 91 insertions(+) create mode 100644 docs/cvmfs.md diff --git a/docs/cvmfs.md b/docs/cvmfs.md new file mode 100644 index 00000000000..7e3c812a62a --- /dev/null +++ b/docs/cvmfs.md @@ -0,0 +1,89 @@ +# Lazy-pulling using CernVM-FS Snapshotter + +CernVM-FS Snapshotter is a containerd snapshotter plugin. It is a specialized component responsible for assembling +all the layers of container images into a stacked file system that containerd can use. The snapshotter takes as input the list +of required layers and outputs a directory containing the final file system. It is also responsible to clean up the output +directory when containers using it are stopped. + +See the official [documentation](https://cvmfs.readthedocs.io/en/latest/cpt-containers.html#how-to-use-the-cernvm-fs-snapshotter) to learn further information. + +## Prerequisites + +- Install containerd remote snapshotter plugin (`cvmfs-snapshotter`) from [here](https://github.com/cvmfs/cvmfs/tree/devel/snapshotter). + +- Add the following to `/etc/containerd/config.toml`: +```toml +# Ask containerd to use this particular snapshotter +[plugins."io.containerd.grpc.v1.cri".containerd] + snapshotter = "cvmfs-snapshotter" + disable_snapshot_annotations = false + +# Set the communication endpoint between containerd and the snapshotter +[proxy_plugins] + [proxy_plugins.cvmfs] + type = "snapshot" + address = "/run/containerd-cvmfs-grpc/containerd-cvmfs-grpc.sock" +``` +- The default CernVM-FS repository hosting the flat root filesystems of the container images is `unpacked.cern.ch`. + The container images are unpacked into the CernVM-FS repository by the [DUCC](https://cvmfs.readthedocs.io/en/latest/cpt-ducc.html) + (Daemon that Unpacks Container Images into CernVM-FS) tool. + You can change the repository adding the following line to `/etc/containerd-cvmfs-grpc/config.toml`: +```toml +repository = "myrepo.mydomain" +``` +- Launch `containerd` and `cvmfs-snapshotter`: +```console +$ systemctl start containerd cvmfs-snapshotter +``` + +## Enable CernVM-FS Snapshotter for `nerdctl run` and `nerdctl pull` + +| :zap: Requirement | nerdctl >= 1.6.3 | +| ----------------- | ---------------- | + +- Run `nerdctl` with `--snapshotter cvmfs-snapshotter` as in the example below: +```console +$ nerdctl run -it --rm --snapshotter cvmfs-snapshotter clelange/cms-higgs-4l-full:latest +``` + +- You can also only pull the image with CernVM-FS Snapshotter without running the container: +```console +$ nerdctl pull --snapshotter cvmfs-snapshotter clelange/cms-higgs-4l-full:latest +``` + +The speedup for pulling this 9 GB (4.3 GB compressed) image is shown below: +- #### with the snapshotter: +```console +$ nerdctl --snapshotter cvmfs-snapshotter pull clelange/cms-higgs-4l-full:latest +docker.io/clelange/cms-higgs-4l-full:latest: resolved |++++++++++++++++++++++++++++++++++++++| +manifest-sha256:b8acbe80629dd28d213c03cf1ffd3d46d39e573f54215a281fabce7494b3d546: done |++++++++++++++++++++++++++++++++++++++| +config-sha256:89ef54b6c4fbbedeeeb29b1df2b9916b6d157c87cf1878ea882bff86a3093b5c: done |++++++++++++++++++++++++++++++++++++++| +elapsed: 4.7 s total: 19.8 K (4.2 KiB/s) + +$ nerdctl images +REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE +clelange/cms-higgs-4l-full latest b8acbe80629d 20 seconds ago linux/amd64 0.0 B 4.3 GiB +``` +- #### without the snapshotter: +```console +$ nerdctl pull clelange/cms-higgs-4l-full:latest +docker.io/clelange/cms-higgs-4l-full:latest: resolved |++++++++++++++++++++++++++++++++++++++| +manifest-sha256:b8acbe80629dd28d213c03cf1ffd3d46d39e573f54215a281fabce7494b3d546: exists |++++++++++++++++++++++++++++++++++++++| +config-sha256:89ef54b6c4fbbedeeeb29b1df2b9916b6d157c87cf1878ea882bff86a3093b5c: exists |++++++++++++++++++++++++++++++++++++++| +layer-sha256:e8114d4b0d10b33aaaa4fbc3c6da22bbbcf6f0ef0291170837e7c8092b73840a: done |++++++++++++++++++++++++++++++++++++++| +layer-sha256:a3eda0944a81e87c7a44b117b1c2e707bc8d18e9b7b478e21698c11ce3e8b819: done |++++++++++++++++++++++++++++++++++++++| +layer-sha256:8f3160776e8e8736ea9e3f6c870d14cd104143824bbcabe78697315daca0b9ad: done |++++++++++++++++++++++++++++++++++++++| +layer-sha256:22a5c05baa9db0aa7bba56ffdb2dd21246b9cf3ce938fc6d7bf20e92a067060e: done |++++++++++++++++++++++++++++++++++++++| +layer-sha256:bfcf9d498f92b72426c9d5b73663504d87249d6783c6b58d71fbafc275349ab9: done |++++++++++++++++++++++++++++++++++++++| +layer-sha256:0563e1549926b9c8beac62407bc6a420fa35bcf6f9844e5d8beeb9165325a872: done |++++++++++++++++++++++++++++++++++++++| +layer-sha256:6fff5fd7fb4eeb79a1399d9508614a84191d05e53f094832062d689245599640: done |++++++++++++++++++++++++++++++++++++++| +layer-sha256:25c39bfa66e1157415236703abc512d06cc1db31bd00fe8c3030c6d6d249dc4e: done |++++++++++++++++++++++++++++++++++++++| +layer-sha256:3cc0a0eb55eb3fb7ef0760c6bf1e567dfc56933ba5f11b5415f89228af751b72: done |++++++++++++++++++++++++++++++++++++++| +layer-sha256:a8850244786303e508b94bb31c8569310765e678c9c73bf1199310729209b803: done |++++++++++++++++++++++++++++++++++++++| +layer-sha256:32cdf5fc12485ac061347eb8b5c3b4a28505ce8564a7f3f83ac4241f03911176: done |++++++++++++++++++++++++++++++++++++++| +elapsed: 181.8s total: 4.3 Gi (24.2 MiB/s) + +$ nerdctl images +REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE +clelange/cms-higgs-4l-full latest b8acbe80629d 4 minutes ago linux/amd64 9.0 GiB 4.3 GiB +``` diff --git a/pkg/imgutil/snapshotter.go b/pkg/imgutil/snapshotter.go index 1abc5a14fb3..d1ce63cb8f1 100644 --- a/pkg/imgutil/snapshotter.go +++ b/pkg/imgutil/snapshotter.go @@ -33,6 +33,7 @@ const ( snapshotterNameStargz = "stargz" snapshotterNameNydus = "nydus" snapshotterNameSoci = "soci" + snapshotterNameCvmfs = "cvmfs-snapshotter" // prefetch size for stargz prefetchSize = 10 * 1024 * 1024 @@ -44,6 +45,7 @@ var builtinRemoteSnapshotterOpts = map[string]snapshotterOpts{ snapshotterNameStargz: &remoteSnapshotterOpts{snapshotter: "stargz", extraLabels: stargzExtraLabels}, snapshotterNameNydus: &remoteSnapshotterOpts{snapshotter: "nydus"}, snapshotterNameSoci: &remoteSnapshotterOpts{snapshotter: "soci", extraLabels: sociExtraLabels}, + snapshotterNameCvmfs: &remoteSnapshotterOpts{snapshotter: "cvmfs-snapshotter"}, } // snapshotterOpts is used to update pull config From a6a2d9176ec4446e19712d664c9893fc0d2c7abd Mon Sep 17 00:00:00 2001 From: yuchanns Date: Fri, 27 Oct 2023 14:21:03 +0800 Subject: [PATCH 0200/1066] Support IPv6 for nerdctl network Co-authored-by: Zheao Li Signed-off-by: Hanchin Hsieh --- .github/workflows/test.yml | 46 ++++++++++++ Dockerfile | 4 ++ cmd/nerdctl/container_run.go | 2 +- cmd/nerdctl/container_run_network.go | 7 ++ .../container_run_network_linux_test.go | 71 +++++++++++++++++++ cmd/nerdctl/network_create.go | 12 +++- cmd/nerdctl/network_create_linux_test.go | 40 +++++++++++ docs/command-reference.md | 6 +- pkg/api/types/container_network_types.go | 2 + pkg/cmd/container/create.go | 6 ++ pkg/cmd/network/create.go | 3 +- pkg/labels/labels.go | 3 + pkg/netutil/cni_plugin_unix.go | 20 +++--- pkg/netutil/netutil.go | 9 +-- pkg/netutil/netutil_unix.go | 51 ++++++++++--- pkg/netutil/netutil_windows.go | 27 ++++--- pkg/ocihook/ocihook.go | 40 +++++++++-- pkg/testutil/testutil.go | 25 ++++++- 18 files changed, 322 insertions(+), 52 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2a1b4d7b647..74b433a175f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -104,6 +104,50 @@ jobs: - name: "Run integration tests" run: docker run -t --rm --privileged test-integration + test-integration-ipv6: + runs-on: "ubuntu-${{ matrix.ubuntu }}" + timeout-minutes: 40 + strategy: + fail-fast: false + matrix: + # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 + include: + - ubuntu: 22.04 + containerd: v1.7.7 + env: + UBUNTU_VERSION: "${{ matrix.ubuntu }}" + CONTAINERD_VERSION: "${{ matrix.containerd }}" + steps: + - uses: actions/checkout@v4.1.1 + with: + fetch-depth: 1 + - name: Enable ipv4 and ipv6 forwarding + run: | + sudo sysctl -w net.ipv6.conf.all.forwarding=1 + sudo sysctl -w net.ipv4.ip_forward=1 + - name: Enable IPv6 for Docker + run: | + sudo mkdir -p /etc/docker + echo '{"ipv6": true, "fixed-cidr-v6": "2001:db8:1::/64", "experimental": true, "ip6tables": true}' | sudo tee /etc/docker/daemon.json + sudo systemctl restart docker + - name: "Prepare integration test environment" + run: DOCKER_BUILDKIT=1 docker build -t test-integration-ipv6 --target test-integration-ipv6 --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . + - name: "Remove snap loopback devices (conflicts with our loopback devices in TestRunDevice)" + run: | + sudo systemctl disable --now snapd.service snapd.socket + sudo apt-get purge -y snapd + sudo losetup -Dv + sudo losetup -lv + - name: "Register QEMU (tonistiigi/binfmt)" + run: docker run --privileged --rm tonistiigi/binfmt --install all + - name: "Run integration tests" + # The nested IPv6 network inside docker and qemu is complex and needs a bunch of sysctl config. + # Therefore it's hard to debug why the IPv6 tests fail in such an isolation layer. + # On the other side, using the host network is easier at configuration. + # Besides, each job is running on a different instance, which means using host network here + # is safe and has no side effects on others. + run: docker run --network host -t --rm --privileged test-integration-ipv6 + test-integration-rootless: runs-on: "ubuntu-${{ matrix.ubuntu }}" timeout-minutes: 60 @@ -200,6 +244,8 @@ jobs: sudo apt-get install -y expect - name: "Ensure that the integration test suite is compatible with Docker" run: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon + - name: "Ensure that the IPv6 integration test suite is compatible with Docker" + run: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon -test.ipv6 test-integration-windows: # A "larger" runner is used for enabling Hyper-V containers diff --git a/Dockerfile b/Dockerfile index bdfbf14bbb9..1626cc56d59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -341,4 +341,8 @@ FROM test-integration-rootless AS test-integration-rootless-port-slirp4netns COPY ./Dockerfile.d/home_rootless_.config_systemd_user_containerd.service.d_port-slirp4netns.conf /home/rootless/.config/systemd/user/containerd.service.d/port-slirp4netns.conf RUN chown -R rootless:rootless /home/rootless/.config +FROM test-integration AS test-integration-ipv6 +CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/cmd/nerdctl/...", \ + "--", "-timeout=30m", "-args", "-test.kill-daemon", "-test.ipv6"] + FROM base AS demo diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 5f2d60aeb7e..44720eea3af 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -120,8 +120,8 @@ func setCreateFlags(cmd *cobra.Command) { cmd.Flags().StringSlice("dns-option", nil, "Set DNS options") // publish is defined as StringSlice, not StringArray, to allow specifying "--publish=80:80,443:443" (compatible with Podman) cmd.Flags().StringSliceP("publish", "p", nil, "Publish a container's port(s) to the host") - // FIXME: not support IPV6 yet cmd.Flags().String("ip", "", "IPv4 address to assign to the container") + cmd.Flags().String("ip6", "", "IPv6 address to assign to the container") cmd.Flags().StringP("hostname", "h", "", "Container host name") cmd.Flags().String("mac-address", "", "MAC address to assign to the container") // #endregion diff --git a/cmd/nerdctl/container_run_network.go b/cmd/nerdctl/container_run_network.go index 8fc178c4bf7..e2d25a047e0 100644 --- a/cmd/nerdctl/container_run_network.go +++ b/cmd/nerdctl/container_run_network.go @@ -77,6 +77,13 @@ func loadNetworkFlags(cmd *cobra.Command) (types.NetworkOptions, error) { } netOpts.IPAddress = ipAddress + // --ip6= + ip6Address, err := cmd.Flags().GetString("ip6") + if err != nil { + return netOpts, err + } + netOpts.IP6Address = ip6Address + // -h/--hostname= hostName, err := cmd.Flags().GetString("hostname") if err != nil { diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index 9f0046ad143..e8b3d375b9d 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -19,6 +19,7 @@ package main import ( "fmt" "io" + "net" "regexp" "runtime" "strings" @@ -491,3 +492,73 @@ func TestRunContainerWithMACAddress(t *testing.T) { } } } + +func TestRunContainerWithStaticIP6(t *testing.T) { + if rootlessutil.IsRootless() { + t.Skip("Static IP6 assignment is not supported rootless mode yet.") + } + networkName := "test-network" + networkSubnet := "2001:db8:5::/64" + _, subnet, err := net.ParseCIDR(networkSubnet) + assert.Assert(t, err == nil) + base := testutil.NewBaseWithIPv6Compatible(t) + base.Cmd("network", "create", networkName, "--subnet", networkSubnet, "--ipv6").AssertOK() + t.Cleanup(func() { + base.Cmd("network", "rm", networkName).Run() + }) + testCases := []struct { + ip string + shouldSuccess bool + checkTheIPAddress bool + }{ + { + ip: "", + shouldSuccess: true, + checkTheIPAddress: false, + }, + { + ip: "2001:db8:5::6", + shouldSuccess: true, + checkTheIPAddress: true, + }, + { + ip: "2001:db8:4::6", + shouldSuccess: false, + checkTheIPAddress: false, + }, + } + tID := testutil.Identifier(t) + for i, tc := range testCases { + i := i + tc := tc + tcName := fmt.Sprintf("%+v", tc) + t.Run(tcName, func(t *testing.T) { + testContainerName := fmt.Sprintf("%s-%d", tID, i) + base := testutil.NewBaseWithIPv6Compatible(t) + args := []string{ + "run", "--rm", "--name", testContainerName, "--network", networkName, + } + if tc.ip != "" { + args = append(args, "--ip6", tc.ip) + } + args = append(args, []string{testutil.NginxAlpineImage, "ip", "addr", "show", "dev", "eth0"}...) + cmd := base.Cmd(args...) + if !tc.shouldSuccess { + cmd.AssertFail() + return + } + cmd.AssertOutWithFunc(func(stdout string) error { + ip := findIPv6(stdout) + if !subnet.Contains(ip) { + return fmt.Errorf("expected subnet %s include ip %s", subnet, ip) + } + if tc.checkTheIPAddress { + if ip.String() != tc.ip { + return fmt.Errorf("expected ip %s, got %s", tc.ip, ip) + } + } + return nil + }) + }) + } +} diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index c7452277bdf..b5c4f1e81e3 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -44,10 +44,11 @@ func newNetworkCreateCommand() *cobra.Command { networkCreateCommand.Flags().String("ipam-driver", "default", "IP Address Management Driver") networkCreateCommand.RegisterFlagCompletionFunc("ipam-driver", shellCompleteIPAMDrivers) networkCreateCommand.Flags().StringArray("ipam-opt", nil, "Set IPAM driver specific options") - networkCreateCommand.Flags().String("subnet", "", `Subnet in CIDR format that represents a network segment, e.g. "10.5.0.0/16"`) + networkCreateCommand.Flags().StringArray("subnet", nil, `Subnet in CIDR format that represents a network segment, e.g. "10.5.0.0/16"`) networkCreateCommand.Flags().String("gateway", "", `Gateway for the master subnet`) networkCreateCommand.Flags().String("ip-range", "", `Allocate container ip from a sub-range`) networkCreateCommand.Flags().StringArray("label", nil, "Set metadata for a network") + networkCreateCommand.Flags().Bool("ipv6", false, "Enable IPv6 networking") return networkCreateCommand } @@ -79,7 +80,7 @@ func networkCreateAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - subnetStr, err := cmd.Flags().GetString("subnet") + subnets, err := cmd.Flags().GetStringArray("subnet") if err != nil { return err } @@ -96,6 +97,10 @@ func networkCreateAction(cmd *cobra.Command, args []string) error { return err } labels = strutil.DedupeStrSlice(labels) + ipv6, err := cmd.Flags().GetBool("ipv6") + if err != nil { + return err + } return network.Create(types.NetworkCreateOptions{ GOptions: globalOptions, @@ -105,10 +110,11 @@ func networkCreateAction(cmd *cobra.Command, args []string) error { Options: strutil.ConvertKVStringsToMap(opts), IPAMDriver: ipamDriver, IPAMOptions: strutil.ConvertKVStringsToMap(ipamOpts), - Subnet: subnetStr, + Subnets: subnets, Gateway: gatewayStr, IPRange: ipRangeStr, Labels: labels, + IPv6: ipv6, }, }, cmd.OutOrStdout()) } diff --git a/cmd/nerdctl/network_create_linux_test.go b/cmd/nerdctl/network_create_linux_test.go index d055c10bb28..58b8fcecaed 100644 --- a/cmd/nerdctl/network_create_linux_test.go +++ b/cmd/nerdctl/network_create_linux_test.go @@ -17,6 +17,9 @@ package main import ( + "fmt" + "net" + "strings" "testing" "github.com/containerd/nerdctl/pkg/testutil" @@ -54,3 +57,40 @@ func TestNetworkCreate(t *testing.T) { base.Cmd("run", "--rm", "--net", testNetwork+"-1", testutil.CommonImage, "ip", "route").AssertNoOut(net.IPAM.Config[0].Subnet) } + +func TestNetworkCreateIPv6(t *testing.T) { + base := testutil.NewBaseWithIPv6Compatible(t) + testNetwork := testutil.Identifier(t) + + subnetStr := "2001:db8:8::/64" + _, subnet, err := net.ParseCIDR(subnetStr) + assert.Assert(t, err == nil) + + base.Cmd("network", "create", "--ipv6", "--subnet", subnetStr, testNetwork).AssertOK() + t.Cleanup(func() { + base.Cmd("network", "rm", testNetwork).Run() + }) + + base.Cmd("run", "--rm", "--net", testNetwork, testutil.CommonImage, "ip", "addr", "show", "dev", "eth0").AssertOutWithFunc(func(stdout string) error { + ip := findIPv6(stdout) + if subnet.Contains(ip) { + return nil + } + return fmt.Errorf("expected subnet %s include ip %s", subnet, ip) + }) +} + +func findIPv6(output string) net.IP { + var ipv6 string + lines := strings.Split(output, "\n") + for _, line := range lines { + if strings.Contains(line, "inet6") { + fields := strings.Fields(line) + if len(fields) > 1 { + ipv6 = strings.Split(fields[1], "/")[0] + break + } + } + } + return net.ParseIP(ipv6) +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 610bde2e8de..3a5fa0d32f5 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -183,6 +183,7 @@ Network flags: - :whale: `--add-host`: Add a custom host-to-IP mapping (host:ip). `ip` could be a special string `host-gateway`, - which will be resolved to the `host-gateway-ip` in nerdctl.toml or global flag. - :whale: `--ip`: Specific static IP address(es) to use +- :whale: `--ip6`: Specific static IP6 address(es) to use. Should be used with user networks - :whale: `--mac-address`: Specific MAC address to use. Be aware that it does not check if manually specified MAC addresses are unique. Supports network type `bridge` and `macvlan` @@ -375,7 +376,7 @@ IPFS flags: Unimplemented `docker run` flags: `--attach`, `--blkio-weight-device`, `--cpu-rt-*`, `--device-*`, - `--disable-content-trust`, `--domainname`, `--expose`, `--health-*`, `--ip6`, `--isolation`, `--no-healthcheck`, + `--disable-content-trust`, `--domainname`, `--expose`, `--health-*`, `--isolation`, `--no-healthcheck`, `--link*`, `--mac-address`, `--publish-all`, `--sig-proxy`, `--storage-opt`, `--userns`, `--volume-driver` @@ -992,8 +993,9 @@ Flags: - :whale: `--gateway`: Gateway for the master subnet - :whale: `--ip-range`: Allocate container ip from a sub-range - :whale: `--label`: Set metadata on a network +- :whale: `--ipv6`: Enable IPv6. Should be used with a valid subnet. -Unimplemented `docker network create` flags: `--attachable`, `--aux-address`, `--config-from`, `--config-only`, `--ingress`, `--internal`, `--ipv6`, `--scope` +Unimplemented `docker network create` flags: `--attachable`, `--aux-address`, `--config-from`, `--config-only`, `--ingress`, `--internal`, `--scope` ### :whale: nerdctl network ls diff --git a/pkg/api/types/container_network_types.go b/pkg/api/types/container_network_types.go index c4476662b9d..28e9a54102a 100644 --- a/pkg/api/types/container_network_types.go +++ b/pkg/api/types/container_network_types.go @@ -28,6 +28,8 @@ type NetworkOptions struct { MACAddress string // IPAddress set specific static IP address(es) to use IPAddress string + // IP6Address set specific static IP6 address(es) to use + IP6Address string // Hostname set container host name Hostname string // DNSServers set custom DNS servers diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index e2409877288..ca40bbe4c43 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -193,6 +193,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa internalLabels.hostname = netLabelOpts.Hostname internalLabels.ports = netLabelOpts.PortMappings internalLabels.ipAddress = netLabelOpts.IPAddress + internalLabels.ip6Address = netLabelOpts.IP6Address internalLabels.networks = netLabelOpts.NetworkSlice internalLabels.macAddress = netLabelOpts.MACAddress @@ -505,6 +506,7 @@ type internalLabels struct { // network networks []string ipAddress string + ip6Address string ports []gocni.PortMapping macAddress string // volume @@ -561,6 +563,10 @@ func withInternalLabels(internalLabels internalLabels) (containerd.NewContainerO m[labels.IPAddress] = internalLabels.ipAddress } + if internalLabels.ip6Address != "" { + m[labels.IP6Address] = internalLabels.ip6Address + } + m[labels.Platform], err = platformutil.NormalizeString(internalLabels.platform) if err != nil { return nil, err diff --git a/pkg/cmd/network/create.go b/pkg/cmd/network/create.go index 4c0cc65d020..8a032433478 100644 --- a/pkg/cmd/network/create.go +++ b/pkg/cmd/network/create.go @@ -26,10 +26,11 @@ import ( ) func Create(options types.NetworkCreateOptions, stdout io.Writer) error { - if options.CreateOptions.Subnet == "" { + if len(options.CreateOptions.Subnets) == 0 { if options.CreateOptions.Gateway != "" || options.CreateOptions.IPRange != "" { return fmt.Errorf("cannot set gateway or ip-range without subnet, specify --subnet manually") } + options.CreateOptions.Subnets = []string{""} } e, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath) diff --git a/pkg/labels/labels.go b/pkg/labels/labels.go index 58c747a559e..e11e96a9958 100644 --- a/pkg/labels/labels.go +++ b/pkg/labels/labels.go @@ -60,6 +60,9 @@ const ( // IPAddress is the static IP address of the container assigned by the user IPAddress = Prefix + "ip" + // IP6Address is the static IP6 address of the container assigned by the user + IP6Address = Prefix + "ip6" + // LogURI is the log URI LogURI = Prefix + "log-uri" diff --git a/pkg/netutil/cni_plugin_unix.go b/pkg/netutil/cni_plugin_unix.go index 535a003847e..588f339c669 100644 --- a/pkg/netutil/cni_plugin_unix.go +++ b/pkg/netutil/cni_plugin_unix.go @@ -31,12 +31,14 @@ type bridgeConfig struct { PromiscMode bool `json:"promiscMode,omitempty"` Vlan int `json:"vlan,omitempty"` IPAM map[string]interface{} `json:"ipam"` + Capabilities map[string]bool `json:"capabilities,omitempty"` } func newBridgePlugin(bridgeName string) *bridgeConfig { return &bridgeConfig{ - PluginType: "bridge", - BrName: bridgeName, + PluginType: "bridge", + BrName: bridgeName, + Capabilities: map[string]bool{}, } } @@ -46,16 +48,18 @@ func (*bridgeConfig) GetPluginType() string { // vlanConfig describes the macvlan/ipvlan config type vlanConfig struct { - PluginType string `json:"type"` - Master string `json:"master"` - Mode string `json:"mode,omitempty"` - MTU int `json:"mtu,omitempty"` - IPAM map[string]interface{} `json:"ipam"` + PluginType string `json:"type"` + Master string `json:"master"` + Mode string `json:"mode,omitempty"` + MTU int `json:"mtu,omitempty"` + IPAM map[string]interface{} `json:"ipam"` + Capabilities map[string]bool `json:"capabilities,omitempty"` } func newVLANPlugin(pluginType string) *vlanConfig { return &vlanConfig{ - PluginType: pluginType, + PluginType: pluginType, + Capabilities: map[string]bool{}, } } diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 962bcc665bf..f6e0079cd9f 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -231,10 +231,11 @@ type CreateOptions struct { Options map[string]string IPAMDriver string IPAMOptions map[string]string - Subnet string + Subnets []string Gateway string IPRange string Labels []string + IPv6 bool } func (e *CNIEnv) CreateNetwork(opts CreateOptions) (*NetworkConfig, error) { //nolint:revive @@ -249,11 +250,11 @@ func (e *CNIEnv) CreateNetwork(opts CreateOptions) (*NetworkConfig, error) { //n } fn := func() error { - ipam, err := e.generateIPAM(opts.IPAMDriver, opts.Subnet, opts.Gateway, opts.IPRange, opts.IPAMOptions) + ipam, err := e.generateIPAM(opts.IPAMDriver, opts.Subnets, opts.Gateway, opts.IPRange, opts.IPAMOptions, opts.IPv6) if err != nil { return err } - plugins, err := e.generateCNIPlugins(opts.Driver, opts.Name, ipam, opts.Options) + plugins, err := e.generateCNIPlugins(opts.Driver, opts.Name, ipam, opts.Options, opts.IPv6) if err != nil { return err } @@ -352,7 +353,7 @@ func (e *CNIEnv) createDefaultNetworkConfig() error { opts := CreateOptions{ Name: DefaultNetworkName, Driver: DefaultNetworkName, - Subnet: DefaultCIDR, + Subnets: []string{DefaultCIDR}, IPAMDriver: "default", Labels: []string{fmt.Sprintf("%s=true", labels.NerdctlDefaultNetwork)}, } diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index b75bf62a6c4..d149a1e9ebd 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -87,7 +87,7 @@ func (n *NetworkConfig) clean() error { return nil } -func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string]interface{}, opts map[string]string) ([]CNIPlugin, error) { +func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string]interface{}, opts map[string]string, ipv6 bool) ([]CNIPlugin, error) { var ( plugins []CNIPlugin err error @@ -123,6 +123,9 @@ func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string] bridge.IsGW = true bridge.IPMasq = iPMasq bridge.HairpinMode = true + if ipv6 { + bridge.Capabilities["ips"] = true + } plugins = []CNIPlugin{bridge, newPortMapPlugin(), newFirewallPlugin(), newTuningPlugin()} plugins = fixUpIsolation(e, name, plugins) case "macvlan", "ipvlan": @@ -160,6 +163,9 @@ func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string] vlan.Master = master vlan.Mode = mode vlan.IPAM = ipam + if ipv6 { + vlan.Capabilities["ips"] = true + } plugins = []CNIPlugin{vlan} default: return nil, fmt.Errorf("unsupported cni driver %q", driver) @@ -167,24 +173,23 @@ func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string] return plugins, nil } -func (e *CNIEnv) generateIPAM(driver string, subnetStr, gatewayStr, ipRangeStr string, opts map[string]string) (map[string]interface{}, error) { +func (e *CNIEnv) generateIPAM(driver string, subnets []string, gatewayStr, ipRangeStr string, opts map[string]string, ipv6 bool) (map[string]interface{}, error) { var ipamConfig interface{} switch driver { case "default", "host-local": - subnet, err := e.parseSubnet(subnetStr) - if err != nil { - return nil, err + ipamConf := newHostLocalIPAMConfig() + ipamConf.Routes = []IPAMRoute{ + {Dst: "0.0.0.0/0"}, } - ipamRange, err := parseIPAMRange(subnet, gatewayStr, ipRangeStr) + ranges, findIPv4, err := e.parseIPAMRanges(subnets, gatewayStr, ipRangeStr, ipv6) if err != nil { return nil, err } - - ipamConf := newHostLocalIPAMConfig() - ipamConf.Routes = []IPAMRoute{ - {Dst: "0.0.0.0/0"}, + ipamConf.Ranges = append(ipamConf.Ranges, ranges...) + if !findIPv4 { + ranges, _, _ = e.parseIPAMRanges([]string{""}, gatewayStr, ipRangeStr, ipv6) + ipamConf.Ranges = append(ipamConf.Ranges, ranges...) } - ipamConf.Ranges = append(ipamConf.Ranges, []IPAMRange{*ipamRange}) ipamConfig = ipamConf case "dhcp": ipamConf := newDHCPIPAMConfig() @@ -205,6 +210,30 @@ func (e *CNIEnv) generateIPAM(driver string, subnetStr, gatewayStr, ipRangeStr s return ipam, nil } +func (e *CNIEnv) parseIPAMRanges(subnets []string, gateway, ipRange string, ipv6 bool) ([][]IPAMRange, bool, error) { + findIPv4 := false + ranges := make([][]IPAMRange, 0, len(subnets)) + for i := range subnets { + subnet, err := e.parseSubnet(subnets[i]) + if err != nil { + return nil, findIPv4, err + } + // if ipv6 flag is not set, subnets of ipv6 should be excluded + if !ipv6 && subnet.IP.To4() == nil { + continue + } + if !findIPv4 && subnet.IP.To4() != nil { + findIPv4 = true + } + ipamRange, err := parseIPAMRange(subnet, gateway, ipRange) + if err != nil { + return nil, findIPv4, err + } + ranges = append(ranges, []IPAMRange{*ipamRange}) + } + return ranges, findIPv4, nil +} + func fixUpIsolation(e *CNIEnv, name string, plugins []CNIPlugin) []CNIPlugin { isolationPath := filepath.Join(e.Path, "isolation") if _, err := exec.LookPath(isolationPath); err == nil { diff --git a/pkg/netutil/netutil_windows.go b/pkg/netutil/netutil_windows.go index f0531152596..e0956bf7306 100644 --- a/pkg/netutil/netutil_windows.go +++ b/pkg/netutil/netutil_windows.go @@ -58,7 +58,7 @@ func (n *NetworkConfig) clean() error { return nil } -func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string]interface{}, opts map[string]string) ([]CNIPlugin, error) { +func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string]interface{}, opts map[string]string, ipv6 bool) ([]CNIPlugin, error) { var plugins []CNIPlugin switch driver { case "nat": @@ -71,8 +71,15 @@ func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string] return plugins, nil } -func (e *CNIEnv) generateIPAM(driver string, subnetStr, gatewayStr, ipRangeStr string, opts map[string]string) (map[string]interface{}, error) { - subnet, err := e.parseSubnet(subnetStr) +func (e *CNIEnv) generateIPAM(driver string, subnets []string, gatewayStr, ipRangeStr string, opts map[string]string, ipv6 bool) (map[string]interface{}, error) { + switch driver { + case "default": + default: + return nil, fmt.Errorf("unsupported ipam driver %q", driver) + } + + ipamConfig := newWindowsIPAMConfig() + subnet, err := e.parseSubnet(subnets[0]) if err != nil { return nil, err } @@ -80,18 +87,8 @@ func (e *CNIEnv) generateIPAM(driver string, subnetStr, gatewayStr, ipRangeStr s if err != nil { return nil, err } - - var ipamConfig interface{} - switch driver { - case "default": - ipamConf := newWindowsIPAMConfig() - ipamConf.Subnet = ipamRange.Subnet - ipamConf.Routes = append(ipamConf.Routes, IPAMRoute{Gateway: ipamRange.Gateway}) - ipamConfig = ipamConf - default: - return nil, fmt.Errorf("unsupported ipam driver %q", driver) - } - + ipamConfig.Subnet = ipamRange.Subnet + ipamConfig.Routes = append(ipamConfig.Routes, IPAMRoute{Gateway: ipamRange.Gateway}) ipam, err := structToMap(ipamConfig) if err != nil { return nil, err diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 2b5a6aa956e..222993c709c 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -188,7 +188,11 @@ func newHandlerOpts(state *specs.State, dataStore, cniPath, cniNetconfPath strin } if macAddress, ok := o.state.Annotations[labels.MACAddress]; ok { - o.contianerMAC = macAddress + o.containerMAC = macAddress + } + + if ip6Address, ok := o.state.Annotations[labels.IP6Address]; ok { + o.containerIP6 = ip6Address } if rootlessutil.IsRootlessChild() { @@ -226,7 +230,8 @@ type handlerOpts struct { bypassClient b4nndclient.Client extraHosts map[string]string // host:ip containerIP string - contianerMAC string + containerMAC string + containerIP6 string } // hookSpec is from https://github.com/containerd/containerd/blob/v1.4.3/cmd/containerd/command/oci-hook.go#L59-L64 @@ -353,14 +358,31 @@ func getIPAddressOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { } func getMACAddressOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { - if opts.contianerMAC != "" { + if opts.containerMAC != "" { return []gocni.NamespaceOpts{ gocni.WithLabels(map[string]string{ // allow loose CNI argument verification // FYI: https://github.com/containernetworking/cni/issues/560 "IgnoreUnknown": "1", }), - gocni.WithArgs("MAC", opts.contianerMAC), + gocni.WithArgs("MAC", opts.containerMAC), + }, nil + } + return nil, nil +} + +func getIP6AddressOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { + if opts.containerIP6 != "" { + if rootlessutil.IsRootlessChild() { + log.L.Debug("container IP6 assignment is not fully supported in rootless mode. The IP6 is not accessible from the host (but still accessible from other containers).") + } + return []gocni.NamespaceOpts{ + gocni.WithLabels(map[string]string{ + // allow loose CNI argument verification + // FYI: https://github.com/containernetworking/cni/issues/560 + "IgnoreUnknown": "1", + }), + gocni.WithCapability("ips", []string{opts.containerIP6}), }, nil } return nil, nil @@ -391,10 +413,15 @@ func onCreateRuntime(opts *handlerOpts) error { if err != nil { return err } + ip6AddressOpts, err := getIP6AddressOpts(opts) + if err != nil { + return err + } var namespaceOpts []gocni.NamespaceOpts namespaceOpts = append(namespaceOpts, portMapOpts...) namespaceOpts = append(namespaceOpts, ipAddressOpts...) namespaceOpts = append(namespaceOpts, macAddressOpts...) + namespaceOpts = append(namespaceOpts, ip6AddressOpts...) hsMeta := hostsstore.Meta{ Namespace: opts.state.Annotations[labels.Namespace], ID: opts.state.ID, @@ -478,10 +505,15 @@ func onPostStop(opts *handlerOpts) error { if err != nil { return err } + ip6AddressOpts, err := getIP6AddressOpts(opts) + if err != nil { + return err + } var namespaceOpts []gocni.NamespaceOpts namespaceOpts = append(namespaceOpts, portMapOpts...) namespaceOpts = append(namespaceOpts, ipAddressOpts...) namespaceOpts = append(namespaceOpts, macAddressOpts...) + namespaceOpts = append(namespaceOpts, ip6AddressOpts...) if err := opts.cni.Remove(ctx, opts.fullID, "", namespaceOpts...); err != nil { log.L.WithError(err).Errorf("failed to call cni.Remove") return err diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 04d55b85f8a..7947b156124 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -47,6 +47,8 @@ type Base struct { T testing.TB Target Target DaemonIsKillable bool + EnableIPv6 bool + IPv6Compatible bool Binary string Args []string Env []string @@ -482,11 +484,13 @@ const ( var ( flagTestTarget Target flagTestKillDaemon bool + flagTestIPv6 bool ) func M(m *testing.M) { flag.StringVar(&flagTestTarget, "test.target", Nerdctl, "target to test") flag.BoolVar(&flagTestKillDaemon, "test.kill-daemon", false, "enable tests that kill the daemon") + flag.BoolVar(&flagTestIPv6, "test.ipv6", false, "enable tests on IPv6") flag.Parse() fmt.Fprintf(os.Stderr, "test target: %q\n", flagTestTarget) os.Exit(m.Run()) @@ -499,6 +503,10 @@ func GetTarget() string { return flagTestTarget } +func GetEnableIPv6() bool { + return flagTestIPv6 +} + func GetDaemonIsKillable() bool { return flagTestKillDaemon } @@ -618,18 +626,29 @@ func NewBaseWithNamespace(t *testing.T, ns string) *Base { if ns == "" || ns == "default" || ns == Namespace { t.Fatalf(`the other base namespace cannot be "%s"`, ns) } - return newBase(t, ns) + return newBase(t, ns, false) +} + +func NewBaseWithIPv6Compatible(t *testing.T) *Base { + return newBase(t, Namespace, true) } func NewBase(t *testing.T) *Base { - return newBase(t, Namespace) + return newBase(t, Namespace, false) } -func newBase(t *testing.T, ns string) *Base { +func newBase(t *testing.T, ns string, ipv6Compatible bool) *Base { base := &Base{ T: t, Target: GetTarget(), DaemonIsKillable: GetDaemonIsKillable(), + EnableIPv6: GetEnableIPv6(), + IPv6Compatible: ipv6Compatible, + } + if base.EnableIPv6 && !base.IPv6Compatible { + t.Skip("runner skips non-IPv6 complatible tests in the IPv6 environment") + } else if !base.EnableIPv6 && base.IPv6Compatible { + t.Skip("runner skips IPv6 compatible tests in the non-IPv6 environment") } var err error switch base.Target { From ac0ceb5a93c09787b08e6c879720e515ad8e7cac Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 30 Oct 2023 16:15:59 +0900 Subject: [PATCH 0201/1066] nerdctl-full: compile containerd as static binaries Fix issue 266 Signed-off-by: Akihiro Suda --- Dockerfile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1626cc56d59..4ebb5efdbe2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -73,10 +73,7 @@ WORKDIR /go/src/github.com/containerd/containerd RUN git checkout ${CONTAINERD_VERSION} && \ mkdir -p /out /out/$TARGETARCH && \ cp -a containerd.service /out -ENV CGO_ENABLED=1 -ENV GO111MODULE=off -# TODO: how to build containerd as static binaries? https://github.com/containerd/containerd/issues/6158 -RUN GO=xx-go make && \ +RUN GO=xx-go make STATIC=1 && \ cp -a bin/containerd bin/containerd-shim-runc-v2 bin/ctr /out/$TARGETARCH FROM build-base-debian AS build-runc From 1138bfbe7ca10569317c9bb44dc34b1734a8243d Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 30 Oct 2023 16:52:09 +0900 Subject: [PATCH 0202/1066] nerdctl-full: compile ipfs (Kubo) as a static binary Signed-off-by: Akihiro Suda --- Dockerfile | 21 ++++++++++++++------- Dockerfile.d/SHA256SUMS.d/kubo-v0.23.0 | 3 --- 2 files changed, 14 insertions(+), 10 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/kubo-v0.23.0 diff --git a/Dockerfile b/Dockerfile index 4ebb5efdbe2..be667a436a1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -98,6 +98,18 @@ ENV CGO_ENABLED=1 RUN GO=xx-go make static && \ xx-verify --static bypass4netns && cp -a bypass4netns bypass4netnsd /out/${TARGETARCH} +FROM build-base-debian AS build-kubo +ARG KUBO_VERSION +ARG TARGETARCH +RUN git clone https://github.com/ipfs/kubo.git /go/src/github.com/ipfs/kubo +WORKDIR /go/src/github.com/ipfs/kubo +RUN git checkout ${KUBO_VERSION} && \ + mkdir -p /out/${TARGETARCH} +ENV CGO_ENABLED=0 +RUN xx-go --wrap && \ + make build && \ + xx-verify --static cmd/ipfs/ipfs && cp -a cmd/ipfs/ipfs /out/${TARGETARCH} + FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS build-base RUN apk add --no-cache make git curl COPY . /go/src/github.com/containerd/nerdctl @@ -194,13 +206,8 @@ RUN fname="containerd-fuse-overlayfs-${CONTAINERD_FUSE_OVERLAYFS_VERSION/v}-${TA rm -f "${fname}" && \ echo "- containerd-fuse-overlayfs: ${CONTAINERD_FUSE_OVERLAYFS_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG KUBO_VERSION -RUN fname="kubo_${KUBO_VERSION}_${TARGETOS:-linux}-${TARGETARCH:-amd64}.tar.gz" && \ - curl -o "${fname}" -fSL "https://github.com/ipfs/kubo/releases/download/${KUBO_VERSION}/${fname}" && \ - grep "${fname}" "/SHA256SUMS.d/kubo-${KUBO_VERSION}" | sha256sum -c && \ - tmpout=$(mktemp -d) && \ - tar -C ${tmpout} -xzf "${fname}" kubo/ipfs && \ - mv ${tmpout}/kubo/ipfs /out/bin/ && \ - echo "- Kubo (IPFS): ${KUBO_VERSION}" >> /out/share/doc/nerdctl-full/README.md +COPY --from=build-kubo /out/${TARGETARCH:-amd64}/* /out/bin/ +RUN echo "- Kubo (IPFS): ${KUBO_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG TINI_VERSION RUN fname="tini-static-${TARGETARCH:-amd64}" && \ curl -o "${fname}" -fSL "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/${fname}" && \ diff --git a/Dockerfile.d/SHA256SUMS.d/kubo-v0.23.0 b/Dockerfile.d/SHA256SUMS.d/kubo-v0.23.0 deleted file mode 100644 index f43a829064d..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/kubo-v0.23.0 +++ /dev/null @@ -1,3 +0,0 @@ -# From https://github.com/ipfs/kubo/releases -b78d209ce9b5797534348c6939d305b8758b0e4bc3abae532b63d15d9cddb9c6 kubo_v0.23.0_linux-amd64.tar.gz -0de1bf8564f563b77e7bef620f357c0787b2fad37378c8cdb789a55959e5b543 kubo_v0.23.0_linux-arm64.tar.gz From e6e24c216c507c7c7584d1192c33d47372772ffd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Oct 2023 22:05:14 +0000 Subject: [PATCH 0203/1066] build(deps): bump github.com/containerd/stargz-snapshotter Bumps [github.com/containerd/stargz-snapshotter](https://github.com/containerd/stargz-snapshotter) from 0.14.3 to 0.15.1. - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/compare/v0.14.3...v0.15.1) --- updated-dependencies: - dependency-name: github.com/containerd/stargz-snapshotter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 14 +++++++------- go.sum | 34 +++++++++++++++------------------- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/go.mod b/go.mod index cd1964f473a..d7a97424416 100644 --- a/go.mod +++ b/go.mod @@ -17,8 +17,8 @@ require ( github.com/containerd/imgcrypt v1.1.8 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.13.3 - github.com/containerd/stargz-snapshotter v0.14.3 - github.com/containerd/stargz-snapshotter/estargz v0.14.3 + github.com/containerd/stargz-snapshotter v0.15.1 + github.com/containerd/stargz-snapshotter/estargz v0.15.1 github.com/containerd/stargz-snapshotter/ipfs v0.14.3 github.com/containerd/typeurl/v2 v2.1.1 github.com/containernetworking/cni v1.1.2 @@ -84,7 +84,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.17.2 @@ -117,7 +117,7 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/tinylib/msgp v1.1.6 // indirect - github.com/vbatts/tar-split v0.11.3 // indirect + github.com/vbatts/tar-split v0.11.5 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -129,9 +129,9 @@ require ( golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/tools v0.11.0 // indirect - google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 // indirect - google.golang.org/grpc v1.58.3 // indirect + google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.31.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/go.sum b/go.sum index b525385695c..387dc0629a1 100644 --- a/go.sum +++ b/go.sum @@ -6,7 +6,6 @@ github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= 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= @@ -50,10 +49,10 @@ 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.3 h1:aa4tz0l2Z+vLDuCCx5Ic6f1AQd9ZH/R0B5C/QXGY774= github.com/containerd/nydus-snapshotter v0.13.3/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= -github.com/containerd/stargz-snapshotter v0.14.3 h1:OTUVZoPSPs8mGgmQUE1dqw3WX/3nrsmsurW7UPLWl1U= -github.com/containerd/stargz-snapshotter v0.14.3/go.mod h1:j2Ya4JeA5gMZJr8BchSkPjlcCEh++auAxp4nidPI6N0= -github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= -github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= +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.14.3 h1:Y9jAdsjvZyG30dnEUvfMyV0FOnfs/pdEuYcxYMTDGSM= github.com/containerd/stargz-snapshotter/ipfs v0.14.3/go.mod h1:Y7oQmTVPao0mE8S6WqIKVTnd59FNW55Gy0r/RIGySew= github.com/containerd/ttrpc v1.2.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs= @@ -156,8 +155,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= @@ -256,7 +255,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rootless-containers/bypass4netns v0.3.0 h1:UwI55zWDZz7OGyN4YWgfCKdsI58VGY7OlghcLdxJX10= @@ -265,7 +264,6 @@ github.com/rootless-containers/rootlesskit v1.1.1 h1:F5psKWoWY9/VjZ3ifVcaosjvFZJ github.com/rootless-containers/rootlesskit v1.1.1/go.mod h1:UD5GoA3dqKCJrnvnhVgQQnweMF2qZnf9KLw8EewcMZI= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -298,9 +296,8 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= -github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= -github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= -github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= +github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= +github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= @@ -390,7 +387,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= @@ -425,18 +421,18 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753 h1:+VoAg+OKmWaommL56xmZSE2sUK8A7m6SUO7X89F2tbw= -google.golang.org/genproto v0.0.0-20230717213848-3f92550aa753/go.mod h1:iqkVr8IRpZ53gx1dEnWlCUIEwDWqWARWrbzpasaTNYM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753 h1:XUODHrpzJEUeWmVo/jfNTLj0YyVveOo28oE6vkFbkO4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230717213848-3f92550aa753/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= 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= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 147cbbef3fc7ea1e38e185f68ce379e512cd3dd5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Oct 2023 22:05:23 +0000 Subject: [PATCH 0204/1066] build(deps): bump github.com/containerd/imgcrypt from 1.1.8 to 1.1.9 Bumps [github.com/containerd/imgcrypt](https://github.com/containerd/imgcrypt) from 1.1.8 to 1.1.9. - [Release notes](https://github.com/containerd/imgcrypt/releases) - [Changelog](https://github.com/containerd/imgcrypt/blob/main/CHANGES) - [Commits](https://github.com/containerd/imgcrypt/compare/v1.1.8...v1.1.9) --- updated-dependencies: - dependency-name: github.com/containerd/imgcrypt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index cd1964f473a..bb13d50d643 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/containerd/containerd v1.7.8 github.com/containerd/continuity v0.4.3 github.com/containerd/go-cni v1.1.9 - github.com/containerd/imgcrypt v1.1.8 + github.com/containerd/imgcrypt v1.1.9 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.13.3 github.com/containerd/stargz-snapshotter v0.14.3 @@ -71,7 +71,7 @@ require ( github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/ttrpc v1.2.2 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect - github.com/containers/ocicrypt v1.1.8 // indirect + github.com/containers/ocicrypt v1.1.9 // indirect github.com/distribution/reference v0.5.0 // indirect github.com/djherbis/times v1.5.0 // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect diff --git a/go.sum b/go.sum index b525385695c..8392fb01fb5 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ 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= github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= -github.com/containerd/imgcrypt v1.1.8 h1:ZS7TuywcRNLoHpU0g+v4/PsKynl6TYlw5xDVWWoIyFA= -github.com/containerd/imgcrypt v1.1.8/go.mod h1:x6QvFIkMyO2qGIY2zXc88ivEzcbgvLdWjoZyGqDap5U= +github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC2XV0= +github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= 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.3 h1:aa4tz0l2Z+vLDuCCx5Ic6f1AQd9ZH/R0B5C/QXGY774= @@ -66,8 +66,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.3.0 h1:QVNXMT6XloyMUoO2wUOqWTC1hWFV62Q6mVDp5H1HnjM= github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0= -github.com/containers/ocicrypt v1.1.8 h1:saSBF0/8DyPUjzcxMVzL2OBUWCkvRvqIm75pu0ADSZk= -github.com/containers/ocicrypt v1.1.8/go.mod h1:jM362hyBtbwLMWzXQZTlkjKGAQf/BN/LFMtH0FIRt34= +github.com/containers/ocicrypt v1.1.9 h1:2Csfba4jse85Raxk5HIyEk8OwZNjRvfkhEGijOjIdEM= +github.com/containers/ocicrypt v1.1.9/go.mod h1:dTKx1918d8TDkxXvarscpNVY+lyPakPNFN4jwA9GBys= 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= From 9143054ed8ad6d39af566a8bc17b898efb3a45d7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 00:03:10 +0000 Subject: [PATCH 0205/1066] build(deps): bump github.com/containerd/stargz-snapshotter/ipfs Bumps [github.com/containerd/stargz-snapshotter/ipfs](https://github.com/containerd/stargz-snapshotter) from 0.14.3 to 0.15.1. - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/compare/v0.14.3...v0.15.1) --- updated-dependencies: - dependency-name: github.com/containerd/stargz-snapshotter/ipfs dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 10 +++++----- go.sum | 21 ++++++++++----------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index a60259a1101..cce89f111f6 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/containerd/nydus-snapshotter v0.13.3 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 - github.com/containerd/stargz-snapshotter/ipfs v0.14.3 + github.com/containerd/stargz-snapshotter/ipfs v0.15.1 github.com/containerd/typeurl/v2 v2.1.1 github.com/containernetworking/cni v1.1.2 github.com/containernetworking/plugins v1.3.0 @@ -88,12 +88,12 @@ require ( github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.17.2 - github.com/klauspost/cpuid/v2 v2.1.1 // indirect + github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect - github.com/minio/sha256-simd v1.0.0 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/sys/mountinfo v0.6.2 // indirect @@ -102,7 +102,7 @@ require ( 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 - github.com/multiformats/go-multiaddr v0.8.0 // indirect + github.com/multiformats/go-multiaddr v0.12.0 // indirect github.com/multiformats/go-multibase v0.1.1 // indirect github.com/multiformats/go-multihash v0.2.1 // indirect github.com/multiformats/go-varint v0.0.6 // indirect @@ -126,7 +126,7 @@ require ( go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/trace v1.16.0 // indirect - golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect + golang.org/x/exp v0.0.0-20230725012225-302865e7556b // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/tools v0.11.0 // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect diff --git a/go.sum b/go.sum index 6d1016c0649..a068c76b08e 100644 --- a/go.sum +++ b/go.sum @@ -53,8 +53,8 @@ github.com/containerd/stargz-snapshotter v0.15.1 h1:fpsP4kf/Z4n2EYnU0WT8ZCE3eiKD 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.14.3 h1:Y9jAdsjvZyG30dnEUvfMyV0FOnfs/pdEuYcxYMTDGSM= -github.com/containerd/stargz-snapshotter/ipfs v0.14.3/go.mod h1:Y7oQmTVPao0mE8S6WqIKVTnd59FNW55Gy0r/RIGySew= +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.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs= github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak= github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 h1:rQvjv7gRi6Ki/NS/U9oLZFhqyk4dh/GH2M3o/4BRkMM= @@ -169,10 +169,9 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0= -github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -186,8 +185,8 @@ github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebG github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -212,8 +211,8 @@ github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aG github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= -github.com/multiformats/go-multiaddr v0.8.0 h1:aqjksEcqK+iD/Foe1RRFsGZh8+XFiGo7FgUCZlpv3LU= -github.com/multiformats/go-multiaddr v0.8.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= +github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE= +github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8= github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= @@ -332,8 +331,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= -golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230725012225-302865e7556b h1:tK7yjGqVRzYdXsBcfD2MLhFAhHfDgGLm2rY1ub7FA9k= +golang.org/x/exp v0.0.0-20230725012225-302865e7556b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= From b5da5ea35a3e473fc87a5a78a8ee52ac41f5e519 Mon Sep 17 00:00:00 2001 From: Kenichiro Kadowaki Date: Mon, 30 Oct 2023 23:58:07 +0000 Subject: [PATCH 0206/1066] fix add-host overwritten Signed-off-by: Kenichiro Kadowaki --- cmd/nerdctl/container_run_test.go | 42 ++++++++++++++++++++++++++++ pkg/dnsutil/hostsstore/hostsstore.go | 6 ++-- pkg/dnsutil/hostsstore/updater.go | 10 ++----- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index 7e8bfd77a46..b543c8811ae 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -17,11 +17,14 @@ package main import ( + "bufio" + "bytes" "errors" "fmt" "os" "os/exec" "path/filepath" + "regexp" "runtime" "strings" "testing" @@ -468,3 +471,42 @@ func TestRunWithTtyAndDetached(t *testing.T) { withTtyContainer := base.InspectContainer(withTtyContainerName) assert.Equal(base.T, 0, withTtyContainer.State.ExitCode) } + +// history: There was a bug that the --add-host items disappear when the another container created. +// This case ensures that it's doesn't happen. +// (https://github.com/containerd/nerdctl/issues/2560) +func TestRunAddHostRemainsWhenAnotherContainerCreated(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("ocihook is not yet supported on Windows") + } + base := testutil.NewBase(t) + + containerName := testutil.Identifier(t) + hostMapping := "test-add-host:10.0.0.1" + base.Cmd("run", "-d", "--add-host", hostMapping, "--name", containerName, testutil.CommonImage, "sleep", "infinity").AssertOK() + defer base.Cmd("container", "rm", "-f", containerName).Run() + + checkEtcHosts := func(stdout string) error { + matcher, err := regexp.Compile(`^10.0.0.1\s+test-add-host$`) + if err != nil { + return err + } + var found bool + sc := bufio.NewScanner(bytes.NewBufferString(stdout)) + for sc.Scan() { + if matcher.Match(sc.Bytes()) { + found = true + } + } + if !found { + return fmt.Errorf("host not found") + } + return nil + } + base.Cmd("exec", containerName, "cat", "/etc/hosts").AssertOutWithFunc(checkEtcHosts) + + // run another container + base.Cmd("run", "--rm", testutil.CommonImage).AssertOK() + + base.Cmd("exec", containerName, "cat", "/etc/hosts").AssertOutWithFunc(checkEtcHosts) +} diff --git a/pkg/dnsutil/hostsstore/hostsstore.go b/pkg/dnsutil/hostsstore/hostsstore.go index f90e7ad8752..40a7726e66d 100644 --- a/pkg/dnsutil/hostsstore/hostsstore.go +++ b/pkg/dnsutil/hostsstore/hostsstore.go @@ -133,7 +133,7 @@ func (x *store) Acquire(meta Meta) error { if err := os.WriteFile(metaPath, metaB, 0644); err != nil { return err } - return newUpdater(meta.ID, x.hostsD, meta.ExtraHosts).update() + return newUpdater(meta.ID, x.hostsD).update() } return lockutil.WithDirLock(x.hostsD, fn) } @@ -153,7 +153,7 @@ func (x *store) Release(ns, id string) error { if err := os.RemoveAll(metaPath); err != nil { return err } - return newUpdater(id, x.hostsD, nil).update() + return newUpdater(id, x.hostsD).update() } return lockutil.WithDirLock(x.hostsD, fn) } @@ -177,7 +177,7 @@ func (x *store) Update(ns, id, newName string) error { if err := os.WriteFile(metaPath, metaB, 0644); err != nil { return err } - return newUpdater(meta.ID, x.hostsD, meta.ExtraHosts).update() + return newUpdater(meta.ID, x.hostsD).update() } return lockutil.WithDirLock(x.hostsD, fn) } diff --git a/pkg/dnsutil/hostsstore/updater.go b/pkg/dnsutil/hostsstore/updater.go index 660da9ed9d7..58116e8b5b8 100644 --- a/pkg/dnsutil/hostsstore/updater.go +++ b/pkg/dnsutil/hostsstore/updater.go @@ -30,14 +30,13 @@ import ( ) // newUpdater creates an updater for hostsD (/var/lib/nerdctl//etchosts) -func newUpdater(id, hostsD string, extraHosts map[string]string) *updater { +func newUpdater(id, hostsD string) *updater { u := &updater{ id: id, hostsD: hostsD, metaByIPStr: make(map[string]*Meta), nwNameByIPStr: make(map[string]string), metaByDir: make(map[string]*Meta), - extraHosts: extraHosts, } return u } @@ -49,7 +48,6 @@ type updater struct { metaByIPStr map[string]*Meta // key: IP string nwNameByIPStr map[string]string // key: IP string, value: key of Meta.Networks metaByDir map[string]*Meta // key: "/var/lib/nerdctl//etchosts//" - extraHosts map[string]string // key: host value: IP string } // update updates the hostsD tree. @@ -136,10 +134,8 @@ func (u *updater) phase2() error { buf.WriteString("::1 localhost localhost.localdomain\n") // keep extra hosts first - if u.id == myMeta.ID { - for host, ip := range u.extraHosts { - buf.WriteString(fmt.Sprintf("%-15s %s\n", ip, host)) - } + for host, ip := range myMeta.ExtraHosts { + buf.WriteString(fmt.Sprintf("%-15s %s\n", ip, host)) } for ip, nwName := range u.nwNameByIPStr { From 3dd95cd4e1fb2f2bb777cf2f4f474bb72744ae2d Mon Sep 17 00:00:00 2001 From: Kohei Tokunaga Date: Wed, 1 Nov 2023 12:17:56 +0900 Subject: [PATCH 0207/1066] Dockerfile: stargz-snapshotter v0.15.1 Signed-off-by: Kohei Tokunaga --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.14.3 | 3 --- Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.15.1 | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.14.3 create mode 100644 Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.15.1 diff --git a/Dockerfile b/Dockerfile index be667a436a1..8f382997f8a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ ARG CNI_PLUGINS_VERSION=v1.3.0 # Extra deps: Build ARG BUILDKIT_VERSION=v0.12.2 # Extra deps: Lazy-pulling -ARG STARGZ_SNAPSHOTTER_VERSION=v0.14.3 +ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption ARG IMGCRYPT_VERSION=v1.1.8 # Extra deps: Rootless diff --git a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.14.3 b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.14.3 deleted file mode 100644 index f0a635ee028..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.14.3 +++ /dev/null @@ -1,3 +0,0 @@ -3f5c268eac6c68f1caeb433321a07e6332ed304e9b3ae428f183982ce6df91d6 stargz-snapshotter-v0.14.3-linux-amd64.tar.gz -5788407890786210ea9552a62fd653cea3acc48ffd354f66e5821967128d06d9 stargz-snapshotter-v0.14.3-linux-arm64.tar.gz -f1cf855870af16a653d8acb9daa3edf84687c2c05323cb958f078fb148af3eec stargz-snapshotter.service diff --git a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.15.1 b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.15.1 new file mode 100644 index 00000000000..bb983c9d0dd --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.15.1 @@ -0,0 +1,3 @@ +7f25b570f5e954a33df695d41fdf60d060a3096066f1668236fb5e1b4c7b7753 stargz-snapshotter-v0.15.1-linux-amd64.tar.gz +4bd1ac3331501e14d87f5f8c3cde82cb08971d9b55643eb80155f74261e82a5a stargz-snapshotter-v0.15.1-linux-arm64.tar.gz +f1cf855870af16a653d8acb9daa3edf84687c2c05323cb958f078fb148af3eec stargz-snapshotter.service From 2af4cef9e7e7ca2f36b3f81aa33f10b619e51e6b Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 1 Nov 2023 22:20:42 +0900 Subject: [PATCH 0208/1066] nerdctl ps: implement `--format {{.Label "foo"}}` Fix issue 2598 Signed-off-by: Akihiro Suda --- cmd/nerdctl/container_list.go | 2 +- cmd/nerdctl/container_list_test.go | 43 ++++++++++++++++++++++++++++++ pkg/cmd/container/list.go | 4 +++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 cmd/nerdctl/container_list_test.go diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container_list.go index f0ac6fd6a3c..be2aaaae831 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container_list.go @@ -191,7 +191,7 @@ func formatAndPrintContainerInfo(containers []container.ListItem, options Format for _, c := range containers { if tmpl != nil { var b bytes.Buffer - if err := tmpl.Execute(&b, c); err != nil { + if err := tmpl.Execute(&b, &c); err != nil { return err } if _, err := fmt.Fprintln(w, b.String()); err != nil { diff --git a/cmd/nerdctl/container_list_test.go b/cmd/nerdctl/container_list_test.go new file mode 100644 index 00000000000..7ec299b62ed --- /dev/null +++ b/cmd/nerdctl/container_list_test.go @@ -0,0 +1,43 @@ +/* + 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" + "testing" + + "github.com/containerd/nerdctl/pkg/testutil" +) + +// https://github.com/containerd/nerdctl/issues/2598 +func TestContainerListWithFormatLabel(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + tID := testutil.Identifier(t) + cID := tID + labelK := "label-key-" + tID + labelV := "label-value-" + tID + + base.Cmd("run", "-d", + "--name", cID, + "--label", labelK+"="+labelV, + testutil.CommonImage, "sleep", "infinity").AssertOK() + defer base.Cmd("rm", "-f", cID).AssertOK() + base.Cmd("ps", "-a", + "--filter", "label="+labelK, + "--format", fmt.Sprintf("{{.Label %q}}", labelK)).AssertOutExactly(labelV + "\n") +} diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index a06ee8347be..97f6033f9f8 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -101,6 +101,10 @@ type ListItem struct { // TODO: "LocalVolumes", "Mounts", "Networks", "RunningFor", "State" } +func (x *ListItem) Label(s string) string { + return x.Labels[s] +} + func prepareContainers(ctx context.Context, client *containerd.Client, containers []containerd.Container, options types.ContainerListOptions) ([]ListItem, error) { listItems := make([]ListItem, len(containers)) for i, c := range containers { From 2c3cb4a4ef3216fee04d756d56b5a88eb3cdcb5a Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 1 Nov 2023 22:30:50 +0900 Subject: [PATCH 0209/1066] update containerd (1.7.8) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 18 +++++++++--------- Dockerfile | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 74b433a175f..2a98c56dcb4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,9 +79,9 @@ jobs: - ubuntu: 20.04 containerd: v1.6.24 - ubuntu: 20.04 - containerd: v1.7.7 + containerd: v1.7.8 - ubuntu: 22.04 - containerd: v1.7.7 + containerd: v1.7.8 - ubuntu: 22.04 containerd: main env: @@ -113,7 +113,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 22.04 - containerd: v1.7.7 + containerd: v1.7.8 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -160,10 +160,10 @@ jobs: containerd: v1.6.24 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.7 + containerd: v1.7.8 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.7 + containerd: v1.7.8 target: test-integration-rootless - ubuntu: 22.04 containerd: main @@ -172,10 +172,10 @@ jobs: containerd: v1.6.24 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.7 + containerd: v1.7.8 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.7 + containerd: v1.7.8 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main @@ -267,7 +267,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: repository: containerd/containerd - ref: v1.7.7 + ref: v1.7.8 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -275,7 +275,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.7 + ctrdVersion: 1.7.8 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index 8f382997f8a..b4fc7e0da34 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.7 +ARG CONTAINERD_VERSION=v1.7.8 ARG RUNC_VERSION=v1.1.9 ARG CNI_PLUGINS_VERSION=v1.3.0 From 9c1ee0665e81d9b2d22a4cee522edb8d17ad21c1 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 1 Nov 2023 22:31:53 +0900 Subject: [PATCH 0210/1066] update runc (1.1.10) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b4fc7e0da34..7cfa3f1b4b5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v1.7.8 -ARG RUNC_VERSION=v1.1.9 +ARG RUNC_VERSION=v1.1.10 ARG CNI_PLUGINS_VERSION=v1.3.0 # Extra deps: Build From 2c57b5ca0b25283ef6b0810203486d8025a3c629 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 1 Nov 2023 22:33:05 +0900 Subject: [PATCH 0211/1066] update BuildKit (0.12.3) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.2 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.3 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.2 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.3 diff --git a/Dockerfile b/Dockerfile index 7cfa3f1b4b5..902181c40f6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.10 ARG CNI_PLUGINS_VERSION=v1.3.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.12.2 +ARG BUILDKIT_VERSION=v0.12.3 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.2 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.2 deleted file mode 100644 index 2c9236831c1..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.2 +++ /dev/null @@ -1,2 +0,0 @@ -c856bb4e6584d75ca6b2a7b6e946b7b14628e82bf1eccb4a43bc731bbc8e67ea buildkit-v0.12.2.linux-amd64.tar.gz -78846e12435f00e0ee5b9ca0af28ec78691fa712ebe7d2c799ec8a074c791969 buildkit-v0.12.2.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.3 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.3 new file mode 100644 index 00000000000..3e1148e4704 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.3 @@ -0,0 +1,2 @@ +01682ab9e8e7cada519396b5f7b72c964c0c30da0c2eb7ee46caf30622717fa1 buildkit-v0.12.3.linux-amd64.tar.gz +a6809c7983834f5a4dd3a92a421a9ff9a306e774ce2866d53636e8d5a3f2e82b buildkit-v0.12.3.linux-arm64.tar.gz From 0e643d2bf80584b0048c925c35abaf44e00118b5 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 1 Nov 2023 22:34:08 +0900 Subject: [PATCH 0212/1066] update imgcrypt (1.1.9) Signed-off-by: Akihiro Suda --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 902181c40f6..f48d4a25501 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ ARG BUILDKIT_VERSION=v0.12.3 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption -ARG IMGCRYPT_VERSION=v1.1.8 +ARG IMGCRYPT_VERSION=v1.1.9 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v1.1.1 ARG SLIRP4NETNS_VERSION=v1.2.2 @@ -172,6 +172,7 @@ RUN fname="stargz-snapshotter-${STARGZ_SNAPSHOTTER_VERSION}-${TARGETOS:-linux}-$ ARG IMGCRYPT_VERSION RUN git clone https://github.com/containerd/imgcrypt.git /go/src/github.com/containerd/imgcrypt && \ cd /go/src/github.com/containerd/imgcrypt && \ + git checkout "${IMGCRYPT_VERSION}" && \ CGO_ENABLED=0 make && DESTDIR=/out make install && \ echo "- imgcrypt: ${IMGCRYPT_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG ROOTLESSKIT_VERSION From ae12819e8f1cdd57c240bd7715a9b4c093aa4983 Mon Sep 17 00:00:00 2001 From: yuchanns Date: Tue, 31 Oct 2023 22:22:36 +0800 Subject: [PATCH 0213/1066] Fix unstable sort of container list in compose Signed-off-by: Hanchin Hsieh --- cmd/nerdctl/compose_exec_linux_test.go | 92 ++++++++++++++++++++++++++ pkg/composer/exec.go | 23 ++++++- 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/compose_exec_linux_test.go b/cmd/nerdctl/compose_exec_linux_test.go index 28d92d76efa..074b78513b9 100644 --- a/cmd/nerdctl/compose_exec_linux_test.go +++ b/cmd/nerdctl/compose_exec_linux_test.go @@ -19,12 +19,14 @@ package main import ( "errors" "fmt" + "net" "os" "runtime" "strings" "testing" "github.com/containerd/nerdctl/pkg/testutil" + "gotest.tools/v3/assert" ) func TestComposeExec(t *testing.T) { @@ -207,3 +209,93 @@ services: base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), "exec", "-t=false", "svc0", "stty").AssertFail() // `-i` base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), "exec", "-i=false", "-t=false", "svc0", "stty").AssertFail() } + +func TestComposeExecWithIndex(t *testing.T) { + base := testutil.NewBase(t) + var dockerComposeYAML = fmt.Sprintf(` +version: '3.1' + +services: + svc0: + image: %s + command: "sleep infinity" + deploy: + replicas: 3 +`, testutil.CommonImage) + + comp := testutil.NewComposeDir(t, dockerComposeYAML) + t.Cleanup(func() { + comp.CleanUp() + }) + projectName := comp.ProjectName() + t.Logf("projectName=%q", projectName) + + base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "-d", "svc0").AssertOK() + t.Cleanup(func() { + base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").AssertOK() + }) + + // try 5 times to ensure that results are stable + for i := 0; i < 5; i++ { + for _, j := range []string{"1", "2", "3"} { + name := fmt.Sprintf("%s-svc0-%s", projectName, j) + host := fmt.Sprintf("%s.%s_default", name, projectName) + var ( + expectIP string + realIP string + ) + // docker and nerdctl have different DNS resolution behaviors. + // it uses the ID in the /etc/hosts file, so we need to fetch the ID first. + if testutil.GetTarget() == testutil.Docker { + base.Cmd("ps", "--filter", fmt.Sprintf("name=%s", name), "--format", "{{.ID}}").AssertOutWithFunc(func(stdout string) error { + host = strings.TrimSpace(stdout) + return nil + }) + } + cmds := []string{"-f", comp.YAMLFullPath(), "exec", "-i=false", "-t=false", "--index", j, "svc0"} + base.ComposeCmd(append(cmds, "cat", "/etc/hosts")...). + AssertOutWithFunc(func(stdout string) error { + lines := strings.Split(stdout, "\n") + for _, line := range lines { + if !strings.Contains(line, host) { + continue + } + fields := strings.Fields(line) + if len(fields) == 0 { + continue + } + expectIP = fields[0] + return nil + } + return errors.New("fail to get the expected ip address") + }) + base.ComposeCmd(append(cmds, "ip", "addr", "show", "dev", "eth0")...). + AssertOutWithFunc(func(stdout string) error { + ip := findIP(stdout) + if ip == nil { + return errors.New("fail to get the real ip address") + } + realIP = ip.String() + return nil + }) + assert.Equal(t, realIP, expectIP) + } + } +} + +func findIP(output string) net.IP { + var ip string + lines := strings.Split(output, "\n") + for _, line := range lines { + if !strings.Contains(line, "inet ") { + continue + } + fields := strings.Fields(line) + if len(fields) <= 1 { + continue + } + ip = strings.Split(fields[1], "/")[0] + break + } + return net.ParseIP(ip) +} diff --git a/pkg/composer/exec.go b/pkg/composer/exec.go index 965287c8008..95ffee05620 100644 --- a/pkg/composer/exec.go +++ b/pkg/composer/exec.go @@ -20,9 +20,14 @@ import ( "context" "fmt" "os" + "sort" + "strconv" + "strings" "github.com/containerd/containerd" "github.com/containerd/log" + "github.com/containerd/nerdctl/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/pkg/labels" ) // ExecOptions stores options passed from users as flags and args. @@ -54,9 +59,21 @@ func (c *Composer) Exec(ctx context.Context, eo ExecOptions) error { return fmt.Errorf("index (%d) out of range: only %d running instances from service %s", eo.Index, len(containers), eo.ServiceName) } - container := containers[eo.Index-1] - - return c.exec(ctx, container, eo) + if len(containers) == 1 { + return c.exec(ctx, containers[0], eo) + } + // The order of the containers is not consistently ascending + // we need to re-sort them. + sort.SliceStable(containers, func(i, j int) bool { + infoI, _ := containers[i].Info(ctx, containerd.WithoutRefreshedMetadata) + infoJ, _ := containers[j].Info(ctx, containerd.WithoutRefreshedMetadata) + segsI := strings.Split(infoI.Labels[labels.Name], serviceparser.Separator) + segsJ := strings.Split(infoJ.Labels[labels.Name], serviceparser.Separator) + indexI, _ := strconv.Atoi(segsI[len(segsI)-1]) + indexJ, _ := strconv.Atoi(segsJ[len(segsJ)-1]) + return indexI < indexJ + }) + return c.exec(ctx, containers[eo.Index-1], eo) } // exec constructs/executes the `nerdctl exec` command to be executed on the given container. From a9e5ea4377890383a7005eae6c9ef4496779dbee Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 3 Nov 2023 00:50:57 +0900 Subject: [PATCH 0214/1066] update containerd-fuse-overlayfs (1.0.8) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.7 | 6 ------ Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.8 | 6 ++++++ 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.7 create mode 100644 Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.8 diff --git a/Dockerfile b/Dockerfile index f48d4a25501..7b9d2d71987 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ ARG SLIRP4NETNS_VERSION=v1.2.2 ARG BYPASS4NETNS_VERSION=v0.3.0 # Extra deps: FUSE-OverlayFS ARG FUSE_OVERLAYFS_VERSION=v1.13 -ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.7 +ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 # Extra deps: IPFS ARG KUBO_VERSION=v0.23.0 # Extra deps: Init diff --git a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.7 b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.7 deleted file mode 100644 index 82244bc54c7..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.7 +++ /dev/null @@ -1,6 +0,0 @@ -d9c1a8d511a0697e4262250d54fda79acab86cc7fba20623c5960dbd679c1581 containerd-fuse-overlayfs-1.0.7-linux-amd64.tar.gz -e365cdff6b81e2e3cd8ec27e074aa416a4379f7601c83f6d647b64cb81d8c56e containerd-fuse-overlayfs-1.0.7-linux-arm-v7.tar.gz -013ae62d06a840016437772b6f7206781040528eef04d541a1d3a8b48ec2a70b containerd-fuse-overlayfs-1.0.7-linux-arm64.tar.gz -ef4e93f892dd63f5fff8c5602fd188b38717242ae3a0d9944f4facbfb974d65b containerd-fuse-overlayfs-1.0.7-linux-ppc64le.tar.gz -cd56a229dda55764c237483198e0373d87d8d4d8381167b57265408057d64269 containerd-fuse-overlayfs-1.0.7-linux-riscv64.tar.gz -300d16911403a094ccc610730c34eaa313b0f0df1150015c76a4ea0e85fc9ed3 containerd-fuse-overlayfs-1.0.7-linux-s390x.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.8 b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.8 new file mode 100644 index 00000000000..1a5d72b95dc --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.8 @@ -0,0 +1,6 @@ +a831f236299007bd1078e49df2e45ad0aeee47c5ed099852ad5f6791b091d536 containerd-fuse-overlayfs-1.0.8-linux-amd64.tar.gz +d0fd1fd92ee9ef03050aa759f197b50c46bca81a75bed65b4433b6213a145022 containerd-fuse-overlayfs-1.0.8-linux-arm-v7.tar.gz +17a3a83ae92002dce8ebe41e6a10877ac5d417550d63939c74fc22b0be6ca04a containerd-fuse-overlayfs-1.0.8-linux-arm64.tar.gz +dddaea552594166eb4edef8adabe765b2fae099574b7afe47657fc87674c81db containerd-fuse-overlayfs-1.0.8-linux-ppc64le.tar.gz +d6846b4bf1500cc2dbd29e382ba8b1f2268bdbfc5358a48d17131b8108f97aa9 containerd-fuse-overlayfs-1.0.8-linux-riscv64.tar.gz +492ce81ed25a9b8b3c64d807d3e0f7de6011e70dc11915df8aef64a77fa67fb9 containerd-fuse-overlayfs-1.0.8-linux-s390x.tar.gz From 0008cd6c162b7bb908b566c33d2bd3f4955effb0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 22:44:32 +0000 Subject: [PATCH 0215/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.11.2 to 0.11.4 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.11.2 to 0.11.4. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.11.2...v0.11.4) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cce89f111f6..4a809387b95 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 - github.com/Microsoft/hcsshim v0.11.2 + github.com/Microsoft/hcsshim v0.11.4 github.com/awslabs/soci-snapshotter v0.4.0 github.com/compose-spec/compose-go v1.20.0 github.com/containerd/accelerated-container-image v1.0.0 diff --git a/go.sum b/go.sum index a068c76b08e..08115101a84 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 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.2 h1:63w4x0s9PjbJGGTQTNgCTExPCkyDXhx2AUVQDPDBAek= -github.com/Microsoft/hcsshim v0.11.2/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= +github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/awslabs/soci-snapshotter v0.4.0 h1:dA9lOYbzSUaYMahB8qXQZTVXUszhc0w8rwjRs6EPd24= github.com/awslabs/soci-snapshotter v0.4.0/go.mod h1:+ST8F4E/b6b6pnFBJKprdvzkxyXODMs0FC2TmclkgJc= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= From d96ad3b402441ee128ed983cca9072f4148a275c Mon Sep 17 00:00:00 2001 From: Min Uk Lee Date: Mon, 15 May 2023 03:14:58 +0900 Subject: [PATCH 0216/1066] Add `diff` command Signed-off-by: Min Uk Lee --- cmd/nerdctl/container.go | 1 + cmd/nerdctl/container_diff.go | 219 +++++++++++++++++++++++++++++ cmd/nerdctl/container_diff_test.go | 39 +++++ cmd/nerdctl/main.go | 1 + pkg/api/types/container_types.go | 7 + 5 files changed, 267 insertions(+) create mode 100644 cmd/nerdctl/container_diff.go create mode 100644 cmd/nerdctl/container_diff_test.go diff --git a/cmd/nerdctl/container.go b/cmd/nerdctl/container.go index 311b77d8799..05cef331ab6 100644 --- a/cmd/nerdctl/container.go +++ b/cmd/nerdctl/container.go @@ -44,6 +44,7 @@ func newContainerCommand() *cobra.Command { newRestartCommand(), newKillCommand(), newPauseCommand(), + newDiffCommand(), newWaitCommand(), newUnpauseCommand(), newCommitCommand(), diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go new file mode 100644 index 00000000000..eebaddf4122 --- /dev/null +++ b/cmd/nerdctl/container_diff.go @@ -0,0 +1,219 @@ +/* + 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 ( + "context" + "fmt" + "os" + "path/filepath" + "time" + + "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" + "github.com/containerd/nerdctl/pkg/clientutil" + "github.com/containerd/nerdctl/pkg/idgen" + "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/nerdctl/pkg/labels" + "github.com/opencontainers/image-spec/identity" + "github.com/spf13/cobra" +) + +func newDiffCommand() *cobra.Command { + var diffCommand = &cobra.Command{ + Use: "diff [flags] [CONTAINER]", + Short: "Inspect changes to files or directories on a container's filesystem", + Args: cobra.MinimumNArgs(1), + RunE: diffAction, + SilenceUsage: true, + SilenceErrors: true, + } + return diffCommand +} + +func processContainerDiffOptions(cmd *cobra.Command) (types.ContainerDiffOptions, error) { + globalOptions, err := processRootCmdFlags(cmd) + if err != nil { + return types.ContainerDiffOptions{}, err + } + + return types.ContainerDiffOptions{ + Stdout: cmd.OutOrStdout(), + GOptions: globalOptions, + }, nil +} + +func diffAction(cmd *cobra.Command, args []string) error { + options, err := processContainerDiffOptions(cmd) + if err != nil { + return err + } + + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), options.GOptions.Namespace, options.GOptions.Address) + if err != nil { + return err + } + defer cancel() + + walker := &containerwalker.ContainerWalker{ + Client: client, + OnFound: func(ctx context.Context, found containerwalker.Found) error { + if found.MatchCount > 1 { + return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + } + changes, err := getChanges(ctx, client, found.Container) + if err != nil { + return err + } + + for _, change := range changes { + switch change.Kind { + case fs.ChangeKindAdd: + fmt.Fprintln(cmd.OutOrStdout(), "A", change.Path) + case fs.ChangeKindModify: + fmt.Fprintln(cmd.OutOrStdout(), "C", change.Path) + case fs.ChangeKindDelete: + fmt.Fprintln(cmd.OutOrStdout(), "D", change.Path) + default: + } + } + + return nil + }, + } + + container := args[0] + + n, err := walker.Walk(ctx, container) + if err != nil { + return err + } else if n == 0 { + return fmt.Errorf("no such container %s", container) + } + return nil +} + +func getChanges(ctx context.Context, client *containerd.Client, container containerd.Container) ([]fs.Change, error) { + id := container.ID() + info, err := container.Info(ctx) + if err != nil { + return nil, err + } + + var ( + snName = info.Snapshotter + sn = client.SnapshotService(snName) + ) + + mounts, err := sn.Mounts(ctx, id) + if err != nil { + return nil, err + } + + // NOTE: Moby uses provided rootfs to run container. It doesn't support + // to commit container created by moby. + baseImgWithoutPlatform, err := client.ImageService().Get(ctx, info.Image) + if err != nil { + return nil, fmt.Errorf("container %q lacks image (wasn't created by nerdctl?): %w", id, err) + } + platformLabel := info.Labels[labels.Platform] + if platformLabel == "" { + platformLabel = platforms.DefaultString() + log.G(ctx).Warnf("Image lacks label %q, assuming the platform to be %q", labels.Platform, platformLabel) + } + ocispecPlatform, err := platforms.Parse(platformLabel) + if err != nil { + return nil, err + } + log.G(ctx).Debugf("ocispecPlatform=%q", platforms.Format(ocispecPlatform)) + platformMC := platforms.Only(ocispecPlatform) + baseImg := containerd.NewImageWithPlatform(client, baseImgWithoutPlatform, platformMC) + + baseImgConfig, _, err := imgutil.ReadImageConfig(ctx, baseImg) + if err != nil { + return nil, err + } + + // Don't gc me and clean the dirty data after 1 hour! + ctx, done, err := client.WithLease(ctx, leases.WithRandomID(), leases.WithExpiration(1*time.Hour)) + if err != nil { + return nil, fmt.Errorf("failed to create lease for diff: %w", err) + } + defer done(ctx) + + rootfsID := identity.ChainID(baseImgConfig.RootFS.DiffIDs).String() + + randomID := idgen.GenerateID() + parent, err := sn.View(ctx, randomID, rootfsID) + if err != nil { + return nil, err + } + defer sn.Remove(ctx, randomID) + + var changes []fs.Change + err = mount.WithReadonlyTempMount(ctx, parent, func(lower string) error { + return mount.WithReadonlyTempMount(ctx, mounts, func(upper string) error { + fs.Changes(ctx, lower, upper, func(ck fs.ChangeKind, s string, fi os.FileInfo, err error) error { + if err != nil { + return err + } + changes = appendChanges(changes, fs.Change{ + Kind: ck, + Path: s, + }) + return nil + }) + return err + }) + }) + + return changes, err +} + +func appendChanges(changes []fs.Change, new fs.Change) []fs.Change { + newDir, _ := filepath.Split(new.Path) + newDirPath := filepath.SplitList(newDir) + + if len(changes) == 0 { + for i := 1; i < len(newDirPath); i++ { + changes = append(changes, fs.Change{ + Kind: fs.ChangeKindModify, + Path: filepath.Join(newDirPath[:i+1]...), + }) + } + return append(changes, new) + } + last := changes[len(changes)-1] + lastDir, _ := filepath.Split(last.Path) + lastDirPath := filepath.SplitList(lastDir) + for i := range newDirPath { + if len(lastDirPath) > i && lastDirPath[i] == newDirPath[i] { + continue + } + changes = append(changes, fs.Change{ + Kind: fs.ChangeKindModify, + Path: filepath.Join(newDirPath[:i+1]...), + }) + } + return append(changes, new) +} diff --git a/cmd/nerdctl/container_diff_test.go b/cmd/nerdctl/container_diff_test.go new file mode 100644 index 00000000000..5652c334a01 --- /dev/null +++ b/cmd/nerdctl/container_diff_test.go @@ -0,0 +1,39 @@ +/* + 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 ( + "testing" + + "github.com/containerd/nerdctl/pkg/testutil" +) + +func TestDiff(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + defer base.Cmd("rm", containerName).Run() + + base.Cmd("run", "-d", "--name", containerName, testutil.CommonImage, + "sh", "-euxc", "touch /a; touch /bin/b; rm /bin/base64").AssertOK() + base.Cmd("diff", containerName).AssertOutContains(`A /a +C /bin +A /bin/b +D /bin/base64 +`) + base.Cmd("rm", "-f", containerName).AssertOK() +} diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index be8287db335..c97da084cac 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -251,6 +251,7 @@ Config file ($NERDCTL_TOML): %s newPortCommand(), newStopCommand(), newStartCommand(), + newDiffCommand(), newRestartCommand(), newKillCommand(), newRmCommand(), diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index f742d8f5443..4c30443b990 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -344,6 +344,13 @@ type ContainerCommitOptions struct { Pause bool } +// ContainerDiffOptions specifies options for `nerdctl (container) diff`. +type ContainerDiffOptions struct { + Stdout io.Writer + // GOptions is the global options + GOptions GlobalCommandOptions +} + // ContainerLogsOptions specifies options for `nerdctl (container) logs`. type ContainerLogsOptions struct { Stdout io.Writer From 2fcd3c4c9337e55288b306c6dc9b3b5f28bedd01 Mon Sep 17 00:00:00 2001 From: Min Uk Lee Date: Sat, 4 Nov 2023 22:01:38 +0900 Subject: [PATCH 0217/1066] Add comment to diff test Signed-off-by: Min Uk Lee --- cmd/nerdctl/container_diff_test.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cmd/nerdctl/container_diff_test.go b/cmd/nerdctl/container_diff_test.go index 5652c334a01..7fd2c9ce71c 100644 --- a/cmd/nerdctl/container_diff_test.go +++ b/cmd/nerdctl/container_diff_test.go @@ -30,10 +30,12 @@ func TestDiff(t *testing.T) { base.Cmd("run", "-d", "--name", containerName, testutil.CommonImage, "sh", "-euxc", "touch /a; touch /bin/b; rm /bin/base64").AssertOK() - base.Cmd("diff", containerName).AssertOutContains(`A /a -C /bin -A /bin/b -D /bin/base64 -`) + // nerdctl contains more output "C /etc", "A /etc/resolv.conf" unlike docker + base.Cmd("diff", containerName).AssertOutContainsAll( + "A /a", + "C /bin", + "A /bin/b", + "D /bin/base64", + ) base.Cmd("rm", "-f", containerName).AssertOK() } From da85b403840c11f2491b6ffaac823b0ee2236dfa Mon Sep 17 00:00:00 2001 From: Min Uk Lee Date: Sat, 4 Nov 2023 22:46:39 +0900 Subject: [PATCH 0218/1066] Remove diff test from windows Signed-off-by: Min Uk Lee --- .../{container_diff_test.go => container_diff_linux_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cmd/nerdctl/{container_diff_test.go => container_diff_linux_test.go} (100%) diff --git a/cmd/nerdctl/container_diff_test.go b/cmd/nerdctl/container_diff_linux_test.go similarity index 100% rename from cmd/nerdctl/container_diff_test.go rename to cmd/nerdctl/container_diff_linux_test.go From cc52ea45e36962f8a4a43d664c0889d8174fd1ae Mon Sep 17 00:00:00 2001 From: Min Uk Lee Date: Sat, 4 Nov 2023 23:11:37 +0900 Subject: [PATCH 0219/1066] Support diff command's autocompletion Signed-off-by: Min Uk Lee --- cmd/nerdctl/container_diff.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index eebaddf4122..443534b73d2 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -41,12 +41,13 @@ import ( func newDiffCommand() *cobra.Command { var diffCommand = &cobra.Command{ - Use: "diff [flags] [CONTAINER]", - Short: "Inspect changes to files or directories on a container's filesystem", - Args: cobra.MinimumNArgs(1), - RunE: diffAction, - SilenceUsage: true, - SilenceErrors: true, + Use: "diff [flags] [CONTAINER]", + Short: "Inspect changes to files or directories on a container's filesystem", + Args: cobra.MinimumNArgs(1), + RunE: diffAction, + ValidArgsFunction: diffShellComplete, + SilenceUsage: true, + SilenceErrors: true, } return diffCommand } @@ -217,3 +218,8 @@ func appendChanges(changes []fs.Change, new fs.Change) []fs.Change { } return append(changes, new) } + +func diffShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + // show container names (TODO: only show containers with logs) + return shellCompleteContainerNames(cmd, nil) +} From 00c0d3b726b46caa95618efc76bdc4ffb1814493 Mon Sep 17 00:00:00 2001 From: Min Uk Lee Date: Sun, 5 Nov 2023 00:53:16 +0900 Subject: [PATCH 0220/1066] Fix missing error handling Signed-off-by: Min Uk Lee --- cmd/nerdctl/container_diff.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index 443534b73d2..5dee6d06a46 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -174,7 +174,7 @@ func getChanges(ctx context.Context, client *containerd.Client, container contai var changes []fs.Change err = mount.WithReadonlyTempMount(ctx, parent, func(lower string) error { return mount.WithReadonlyTempMount(ctx, mounts, func(upper string) error { - fs.Changes(ctx, lower, upper, func(ck fs.ChangeKind, s string, fi os.FileInfo, err error) error { + return fs.Changes(ctx, lower, upper, func(ck fs.ChangeKind, s string, fi os.FileInfo, err error) error { if err != nil { return err } @@ -184,9 +184,11 @@ func getChanges(ctx context.Context, client *containerd.Client, container contai }) return nil }) - return err }) }) + if err != nil { + return nil, err + } return changes, err } From d03a5993400c400a84f9e2c5c2d96d4f736db193 Mon Sep 17 00:00:00 2001 From: Min Uk Lee Date: Sun, 5 Nov 2023 00:54:17 +0900 Subject: [PATCH 0221/1066] Fix wrong comment of completion Signed-off-by: Min Uk Lee --- cmd/nerdctl/container_diff.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index 5dee6d06a46..e9e497c9e4e 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -222,6 +222,6 @@ func appendChanges(changes []fs.Change, new fs.Change) []fs.Change { } func diffShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // show container names (TODO: only show containers with logs) + // show container names return shellCompleteContainerNames(cmd, nil) } From 3d1a5f1157be20bcd801181d1582e8edc074df60 Mon Sep 17 00:00:00 2001 From: Min Uk Lee Date: Sun, 5 Nov 2023 00:55:31 +0900 Subject: [PATCH 0222/1066] Use prepared Stdout Signed-off-by: Min Uk Lee --- cmd/nerdctl/container_diff.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index e9e497c9e4e..1dccf9fc400 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -90,11 +90,11 @@ func diffAction(cmd *cobra.Command, args []string) error { for _, change := range changes { switch change.Kind { case fs.ChangeKindAdd: - fmt.Fprintln(cmd.OutOrStdout(), "A", change.Path) + fmt.Fprintln(options.Stdout, "A", change.Path) case fs.ChangeKindModify: - fmt.Fprintln(cmd.OutOrStdout(), "C", change.Path) + fmt.Fprintln(options.Stdout, "C", change.Path) case fs.ChangeKindDelete: - fmt.Fprintln(cmd.OutOrStdout(), "D", change.Path) + fmt.Fprintln(options.Stdout, "D", change.Path) default: } } From a78b50efbf1100f8a395818e6854ec73a04ebf9e Mon Sep 17 00:00:00 2001 From: Min Uk Lee Date: Sun, 5 Nov 2023 01:01:21 +0900 Subject: [PATCH 0223/1066] Add diff command to docs & fix usage message Signed-off-by: Min Uk Lee --- cmd/nerdctl/container_diff.go | 2 +- docs/command-reference.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index 1dccf9fc400..48db2be7891 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -41,7 +41,7 @@ import ( func newDiffCommand() *cobra.Command { var diffCommand = &cobra.Command{ - Use: "diff [flags] [CONTAINER]", + Use: "diff [CONTAINER]", Short: "Inspect changes to files or directories on a container's filesystem", Args: cobra.MinimumNArgs(1), RunE: diffAction, diff --git a/docs/command-reference.md b/docs/command-reference.md index 3a5fa0d32f5..81f9bc49b9a 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -33,6 +33,7 @@ It does not necessarily mean that the corresponding features are missing in cont - [:whale: nerdctl rename](#whale-nerdctl-rename) - [:whale: nerdctl attach](#whale-nerdctl-attach) - [:whale: nerdctl container prune](#whale-nerdctl-container-prune) + - [:whale: nerdctl diff](#whale-nerdctl-diff) - [Build](#build) - [:whale: nerdctl build](#whale-nerdctl-build) - [:whale: nerdctl commit](#whale-nerdctl-commit) @@ -648,6 +649,12 @@ Flags: Unimplemented `docker container prune` flags: `--filter` +### :whale: nerdctl diff + +Inspect changes to files or directories on a container's filesystem + +Usage: `nerdctl diff CONTAINER` + ## Build ### :whale: nerdctl build From d9d684bf004422417d1560306768bcb3a94a6ee3 Mon Sep 17 00:00:00 2001 From: Han Xu Date: Sat, 4 Nov 2023 19:54:39 +0800 Subject: [PATCH 0224/1066] chore(test): remove some incompatible in compose test Signed-off-by: Han Xu --- cmd/nerdctl/compose_create_linux_test.go | 11 ----------- cmd/nerdctl/compose_down_linux_test.go | 5 +---- cmd/nerdctl/compose_exec_linux_test.go | 9 --------- cmd/nerdctl/compose_images_linux_test.go | 4 ---- cmd/nerdctl/compose_kill_linux_test.go | 4 ---- cmd/nerdctl/compose_port_linux_test.go | 4 ---- cmd/nerdctl/compose_start_linux_test.go | 4 ---- cmd/nerdctl/compose_stop_linux_test.go | 3 --- 8 files changed, 1 insertion(+), 43 deletions(-) diff --git a/cmd/nerdctl/compose_create_linux_test.go b/cmd/nerdctl/compose_create_linux_test.go index 5e5ce315ec7..82d2ed50542 100644 --- a/cmd/nerdctl/compose_create_linux_test.go +++ b/cmd/nerdctl/compose_create_linux_test.go @@ -48,10 +48,6 @@ services: } func TestComposeCreateDependency(t *testing.T) { - // docker-compose v1 depecreated this command - // docker-compose v2 reimplemented this command - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` version: '3.1' @@ -79,9 +75,6 @@ services: } func TestComposeCreatePull(t *testing.T) { - // docker-compose v1 depecreated this command - // docker-compose v2 reimplemented this command - testutil.DockerIncompatible(t) base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` @@ -111,10 +104,6 @@ services: } func TestComposeCreateBuild(t *testing.T) { - // docker-compose v1 depecreated this command - // docker-compose v2 reimplemented this command - testutil.DockerIncompatible(t) - const imageSvc0 = "composebuild_svc0" dockerComposeYAML := fmt.Sprintf(` diff --git a/cmd/nerdctl/compose_down_linux_test.go b/cmd/nerdctl/compose_down_linux_test.go index 64c55479408..583e2c98c61 100644 --- a/cmd/nerdctl/compose_down_linux_test.go +++ b/cmd/nerdctl/compose_down_linux_test.go @@ -28,9 +28,6 @@ import ( func TestComposeDownRemoveUsedNetwork(t *testing.T) { base := testutil.NewBase(t) - // The error output is different with docker - testutil.DockerIncompatible(t) - var ( dockerComposeYAMLOrphan = fmt.Sprintf(` version: '3.1' @@ -60,7 +57,7 @@ services: base.ComposeCmd("-p", projectName, "-f", compFull.YAMLFullPath(), "up", "-d").AssertOK() defer base.ComposeCmd("-p", projectName, "-f", compFull.YAMLFullPath(), "down", "--remove-orphans").AssertOK() - base.ComposeCmd("-p", projectName, "-f", compOrphan.YAMLFullPath(), "down", "-v").AssertCombinedOutContains("is in use") + base.ComposeCmd("-p", projectName, "-f", compOrphan.YAMLFullPath(), "down", "-v").AssertCombinedOutContains("in use") } diff --git a/cmd/nerdctl/compose_exec_linux_test.go b/cmd/nerdctl/compose_exec_linux_test.go index 074b78513b9..9a9da25e85d 100644 --- a/cmd/nerdctl/compose_exec_linux_test.go +++ b/cmd/nerdctl/compose_exec_linux_test.go @@ -30,9 +30,6 @@ import ( ) func TestComposeExec(t *testing.T) { - // disabling `-it` in `compose exec` is only supported in compose v2. - // Currently CI is using compose v1. - testutil.DockerIncompatible(t) base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` version: '3.1' @@ -62,9 +59,6 @@ services: } func TestComposeExecWithEnv(t *testing.T) { - // disabling `-it` in `compose exec` is only supported in compose v2. - // Currently CI is using compose v1. - testutil.DockerIncompatible(t) base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` version: '3.1' @@ -131,9 +125,6 @@ services: } func TestComposeExecWithUser(t *testing.T) { - // disabling `-it` in `compose exec` is only supported in compose v2. - // Currently CI is using compose v1. - testutil.DockerIncompatible(t) base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` version: '3.1' diff --git a/cmd/nerdctl/compose_images_linux_test.go b/cmd/nerdctl/compose_images_linux_test.go index 85132a6890c..b10b18309ad 100644 --- a/cmd/nerdctl/compose_images_linux_test.go +++ b/cmd/nerdctl/compose_images_linux_test.go @@ -78,10 +78,6 @@ volumes: } func TestComposeImagesJson(t *testing.T) { - // `--format` is only supported in docker compose v2. - // Currently, CI is using docker compose v1. - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` version: '3.1' diff --git a/cmd/nerdctl/compose_kill_linux_test.go b/cmd/nerdctl/compose_kill_linux_test.go index cdcc6245e41..3a1d138bed3 100644 --- a/cmd/nerdctl/compose_kill_linux_test.go +++ b/cmd/nerdctl/compose_kill_linux_test.go @@ -25,10 +25,6 @@ import ( ) func TestComposeKill(t *testing.T) { - // docker-compose v2 hides exited/killed containers in `compose ps`, and shows - // them if `-a` is passed, which is not supported yet by `nerdctl compose`. - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` version: '3.1' diff --git a/cmd/nerdctl/compose_port_linux_test.go b/cmd/nerdctl/compose_port_linux_test.go index f5240edc55b..991ac6c847a 100644 --- a/cmd/nerdctl/compose_port_linux_test.go +++ b/cmd/nerdctl/compose_port_linux_test.go @@ -52,10 +52,6 @@ services: } func TestComposePortFailure(t *testing.T) { - // when no port mapping is found, docker compose v1 prints `\n` while v2 prints `:0\n` - // both v1 and v2 have exit code 0 (succeess) - // nerdctl compose will fail with error (no public port found). - testutil.DockerIncompatible(t) base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` diff --git a/cmd/nerdctl/compose_start_linux_test.go b/cmd/nerdctl/compose_start_linux_test.go index 64567528093..2a156052408 100644 --- a/cmd/nerdctl/compose_start_linux_test.go +++ b/cmd/nerdctl/compose_start_linux_test.go @@ -57,10 +57,6 @@ services: } func TestComposeStartFailWhenServicePause(t *testing.T) { - // Incompatible with docker compose v1. Currently CI is using compose v1. - // Starting a paused container triggers an error in v2 but is ignored in v1. - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) switch base.Info().CgroupDriver { case "none", "": diff --git a/cmd/nerdctl/compose_stop_linux_test.go b/cmd/nerdctl/compose_stop_linux_test.go index 35377ad5da0..d618894ab33 100644 --- a/cmd/nerdctl/compose_stop_linux_test.go +++ b/cmd/nerdctl/compose_stop_linux_test.go @@ -24,9 +24,6 @@ import ( ) func TestComposeStop(t *testing.T) { - // docker-compose v2 hides exited/killed containers in `compose ps`, and shows - // them if `-a` is passed, which is not supported yet by `nerdctl compose`. - testutil.DockerIncompatible(t) base := testutil.NewBase(t) var dockerComposeYAML = fmt.Sprintf(` version: '3.1' From d08f4c470e1a03a2a9c8728130f0eef2feb85579 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 22:03:13 +0000 Subject: [PATCH 0225/1066] build(deps): bump golang.org/x/text from 0.13.0 to 0.14.0 Bumps [golang.org/x/text](https://github.com/golang/text) from 0.13.0 to 0.14.0. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.13.0...v0.14.0) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4a809387b95..a8caa5e6768 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( golang.org/x/sync v0.4.0 golang.org/x/sys v0.13.0 golang.org/x/term v0.13.0 - golang.org/x/text v0.13.0 + golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) diff --git a/go.sum b/go.sum index 08115101a84..ea9bcea08dc 100644 --- a/go.sum +++ b/go.sum @@ -396,8 +396,8 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From 6c560bcf50e5c05ba1e68b3c4c0636e08ea49984 Mon Sep 17 00:00:00 2001 From: Amr Hanafi Date: Mon, 6 Nov 2023 21:51:53 -0800 Subject: [PATCH 0226/1066] [build][iidfile] Setthe same permissions as docker Docker makes the file readable by other users, nerdctl makes only readable by the user created the file, which breaks compatibility. Signed-off-by: Amr Hanafi --- pkg/cmd/builder/build.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 4dc06928e79..df575fcd955 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -91,7 +91,7 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder if err != nil { return err } - if err := os.WriteFile(options.IidFile, []byte(id), 0600); err != nil { + if err := os.WriteFile(options.IidFile, []byte(id), 0644); err != nil { return err } } From 651cc8cb02a5fd0a5d1778e80dbc881f18a694b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Nov 2023 22:46:53 +0000 Subject: [PATCH 0227/1066] build(deps): bump golang.org/x/net from 0.17.0 to 0.18.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.17.0 to 0.18.0. - [Commits](https://github.com/golang/net/compare/v0.17.0...v0.18.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index a8caa5e6768..660b3ea5334 100644 --- a/go.mod +++ b/go.mod @@ -51,11 +51,11 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 - golang.org/x/crypto v0.14.0 - golang.org/x/net v0.17.0 + golang.org/x/crypto v0.15.0 + golang.org/x/net v0.18.0 golang.org/x/sync v0.4.0 - golang.org/x/sys v0.13.0 - golang.org/x/term v0.13.0 + golang.org/x/sys v0.14.0 + golang.org/x/term v0.14.0 golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 diff --git a/go.sum b/go.sum index ea9bcea08dc..7ccfea74173 100644 --- a/go.sum +++ b/go.sum @@ -328,8 +328,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230725012225-302865e7556b h1:tK7yjGqVRzYdXsBcfD2MLhFAhHfDgGLm2rY1ub7FA9k= golang.org/x/exp v0.0.0-20230725012225-302865e7556b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= @@ -352,8 +352,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -388,11 +388,11 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From a7cdd348cc924afcb54aa5b9825a741c6ab40044 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 19:38:21 +0000 Subject: [PATCH 0228/1066] build(deps): bump golang.org/x/sync from 0.4.0 to 0.5.0 Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.4.0 to 0.5.0. - [Commits](https://github.com/golang/sync/compare/v0.4.0...v0.5.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 660b3ea5334..4e717aa5a24 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/yuchanns/srslog v1.1.0 golang.org/x/crypto v0.15.0 golang.org/x/net v0.18.0 - golang.org/x/sync v0.4.0 + golang.org/x/sync v0.5.0 golang.org/x/sys v0.14.0 golang.org/x/term v0.14.0 golang.org/x/text v0.14.0 diff --git a/go.sum b/go.sum index 7ccfea74173..7594a6fe4bd 100644 --- a/go.sum +++ b/go.sum @@ -361,8 +361,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 411f9dafb5c350f6b5968a067f228e7d3e5c12fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 19:38:25 +0000 Subject: [PATCH 0229/1066] build(deps): bump github.com/fatih/color from 1.15.0 to 1.16.0 Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.15.0 to 1.16.0. - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.15.0...v1.16.0) --- updated-dependencies: - dependency-name: github.com/fatih/color dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 660b3ea5334..ea1cb64ffa8 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/docker/go-connections v0.4.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.0 - github.com/fatih/color v1.15.0 + github.com/fatih/color v1.16.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/ipfs/go-cid v0.4.1 github.com/mattn/go-isatty v0.0.20 diff --git a/go.sum b/go.sum index 7ccfea74173..af899ccf2ce 100644 --- a/go.sum +++ b/go.sum @@ -101,8 +101,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fahedouch/go-logrotate v0.2.0 h1:UR9Fv8MDVfWwnkirmFHck+tRSWzqOwRjVRLMpQgSxaI= github.com/fahedouch/go-logrotate v0.2.0/go.mod h1:1RL/yr7LntS4zadAC6FT6yB/C1CQt3V6eHAZzymfwzE= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= From 33350146494169d909cc515676b9751d86ac4312 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Nov 2023 05:43:02 +0000 Subject: [PATCH 0230/1066] build(deps): bump github.com/spf13/cobra from 1.7.0 to 1.8.0 Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/spf13/cobra/releases) - [Commits](https://github.com/spf13/cobra/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: github.com/spf13/cobra dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 047ffb9b4ec..d1e1cd7cafd 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/pelletier/go-toml/v2 v2.1.0 github.com/rootless-containers/bypass4netns v0.3.0 github.com/rootless-containers/rootlesskit v1.1.1 - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/tidwall/gjson v1.17.0 github.com/vishvananda/netlink v1.2.1-beta.2 diff --git a/go.sum b/go.sum index ddd7c2ee335..65ea46d35cf 100644 --- a/go.sum +++ b/go.sum @@ -71,7 +71,7 @@ github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsa github.com/coreos/go-iptables v0.7.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= @@ -267,8 +267,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +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= From 0d9340740ae2ffd9025b21030fc09b5223f263ac Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 20 Nov 2023 10:14:30 +0900 Subject: [PATCH 0231/1066] Deflake TestContainerListWithFilter Fix issue 2640 Signed-off-by: Akihiro Suda --- cmd/nerdctl/container_list_linux_test.go | 17 ++++++++++------- pkg/testutil/testutil.go | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/cmd/nerdctl/container_list_linux_test.go b/cmd/nerdctl/container_list_linux_test.go index a065ce289af..109e7f9469d 100644 --- a/cmd/nerdctl/container_list_linux_test.go +++ b/cmd/nerdctl/container_list_linux_test.go @@ -37,7 +37,8 @@ type psTestContainer struct { network string } -func preparePsTestContainer(t *testing.T, identity string, restart bool) (*testutil.Base, psTestContainer) { +// When keepAlive is false, the container will exit immediately with status 1. +func preparePsTestContainer(t *testing.T, identity string, keepAlive bool) (*testutil.Base, psTestContainer) { base := testutil.NewBase(t) base.Cmd("pull", testutil.CommonImage).AssertOK() @@ -82,21 +83,23 @@ func preparePsTestContainer(t *testing.T, identity string, restart bool) (*testu "-v", mnt1, "-v", mnt2, "--net", testContainerName, - testutil.CommonImage, - "top", } - if !restart { - args = append(args, "--restart=no") + if keepAlive { + args = append(args, testutil.CommonImage, "top") + } else { + args = append(args, "--restart=no", testutil.CommonImage, "false") } base.Cmd(args...).AssertOK() - if restart { + if keepAlive { base.EnsureContainerStarted(testContainerName) + } else { + base.EnsureContainerExited(testContainerName, 1) } // dd if=/dev/zero of=test_file bs=1M count=25 // let the container occupy 25MiB space. - if restart { + if keepAlive { base.Cmd("exec", testContainerName, "dd", "if=/dev/zero", "of=/test_file", "bs=1M", "count=25").AssertOK() } volumes := []string{} diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 7947b156124..340ff7bf059 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -316,6 +316,30 @@ func (b *Base) EnsureContainerStarted(con string) { b.T.Fatalf("conainer %s not running", con) } +func (b *Base) EnsureContainerExited(con string, expectedExitCode int) { + b.T.Helper() + + const ( + maxRetry = 5 + sleep = time.Second + ) + var c dockercompat.Container + for i := 0; i < maxRetry; i++ { + c = b.InspectContainer(con) + if c.State.Status == "exited" { + b.T.Logf("container %s have exited with status %d", con, c.State.ExitCode) + if c.State.ExitCode == expectedExitCode { + return + } + break + } + b.T.Logf("(retry=%d)", i+1) + time.Sleep(sleep) + } + b.T.Fatalf("expected conainer %s to have exited with code %d, got status %+v", + con, expectedExitCode, c.State) +} + type Cmd struct { icmd.Cmd *Base From c6a4bfeb4113650284f1bd2d94211b52c5fc8c85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:32:08 +0000 Subject: [PATCH 0232/1066] build(deps): bump docker/build-push-action from 5.0.0 to 5.1.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.0.0 to 5.1.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v5.0.0...v5.1.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index b9d6f1f2b16..49d633b8ad3 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -59,7 +59,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v5.0.0 + uses: docker/build-push-action@v5.1.0 with: context: . platforms: linux/amd64,linux/arm64 From ca8c1180aac0a7444575fb0f4bb9da886225e0ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:32:23 +0000 Subject: [PATCH 0233/1066] build(deps): bump github.com/compose-spec/compose-go Bumps [github.com/compose-spec/compose-go](https://github.com/compose-spec/compose-go) from 1.20.0 to 1.20.1. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v1.20.0...v1.20.1) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d1e1cd7cafd..104d98a5c2f 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.11.4 github.com/awslabs/soci-snapshotter v0.4.0 - github.com/compose-spec/compose-go v1.20.0 + github.com/compose-spec/compose-go v1.20.1 github.com/containerd/accelerated-container-image v1.0.0 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 diff --git a/go.sum b/go.sum index 65ea46d35cf..ad9bb90674b 100644 --- a/go.sum +++ b/go.sum @@ -25,8 +25,8 @@ github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go v1.20.0 h1:h4ZKOst1EF/DwZp7dWkb+wbTVE4nEyT9Lc89to84Ol4= -github.com/compose-spec/compose-go v1.20.0/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= +github.com/compose-spec/compose-go v1.20.1 h1:I6gCMGLl96kEf8XZwaozeTwnNfxA2eVsO46W+5ciTEg= +github.com/compose-spec/compose-go v1.20.1/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= github.com/containerd/accelerated-container-image v1.0.0 h1:BWc+VNimtSXUCiegKWhqcHxN9GV4ve3kJEL1968AWF8= github.com/containerd/accelerated-container-image v1.0.0/go.mod h1:LYLT4rKKzJn9Ts0I8uk1pivFmqil/Y3WZT0u+9zb6BA= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= From 77d1fd64a6e84f6d5ed83be9919918ff18aa73b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:33:09 +0000 Subject: [PATCH 0234/1066] build(deps): bump github.com/containerd/containerd from 1.7.8 to 1.7.9 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.8 to 1.7.9. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.8...v1.7.9) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index d1e1cd7cafd..f176b9ac419 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.0.0 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 - github.com/containerd/containerd v1.7.8 + github.com/containerd/containerd v1.7.9 github.com/containerd/continuity v0.4.3 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.9 @@ -123,9 +123,9 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel v1.16.0 // indirect - go.opentelemetry.io/otel/metric v1.16.0 // indirect - go.opentelemetry.io/otel/trace v1.16.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 golang.org/x/exp v0.0.0-20230725012225-302865e7556b // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/tools v0.11.0 // indirect diff --git a/go.sum b/go.sum index 65ea46d35cf..331dd3085c9 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKk github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.8 h1:RkwgOW3AVUT3H/dyT0W03Dc8AzlpMG65lX48KftOFSM= -github.com/containerd/containerd v1.7.8/go.mod h1:L/Hn9qylJtUFT7cPeM0Sr3fATj+WjHwRQ0lyrYk3OPY= +github.com/containerd/containerd v1.7.9 h1:KOhK01szQbM80YfW1H6RZKh85PHGqY/9OcEZ35Je8sc= +github.com/containerd/containerd v1.7.9/go.mod h1:0/W44LWEYfSHoxBtsHIiNU/duEkgpMokemafHVCpq9Y= 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/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= @@ -317,12 +317,12 @@ go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwf go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= -go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= -go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= +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.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= From d767662839ea7c37c5b8a8b5734cf037de3fc7aa Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 16 Nov 2023 19:29:51 +0000 Subject: [PATCH 0235/1066] docs: read-only (RRO) bind-mount have been support by docker Co-authored-by: Akihiro Suda Signed-off-by: Kay Yan --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 81c9d8cefb7..4d1ceb02ab6 100644 --- a/README.md +++ b/README.md @@ -188,8 +188,6 @@ Major: - [Image encryption and decryption using ocicrypt (imgcrypt)](./docs/ocicrypt.md): `nerdctl image (encrypt|decrypt) SRC DST` - [P2P image distribution using IPFS](./docs/ipfs.md): `nerdctl run ipfs://CID` . P2P image distribution (IPFS) is completely optional. Your host is NOT connected to any P2P network, unless you opt in to [install and run IPFS daemon](https://docs.ipfs.io/install/). -- Recursive read-only (RRO) bind-mount: `nerdctl run -v /mnt:/mnt:rro` (make children such as `/mnt/usb` to be read-only, too). - Requires kernel >= 5.12, and crun >= 1.4 or runc >= 1.1 (PR [#3272](https://github.com/opencontainers/runc/pull/3272)). - [Cosign integration](./docs/cosign.md): `nerdctl pull --verify=cosign` and `nerdctl push --sign=cosign`, and [in Compose](./docs/cosign.md#cosign-in-compose) - [Accelerated rootless containers using bypass4netns](./docs/rootless.md): `nerdctl run --label nerdctl/bypass4netns=true` @@ -210,6 +208,11 @@ Trivial: - Inspecting raw OCI config: `nerdctl container inspect --mode=native` . +## Features implemented in `nerdctl` ahead of Docker + +- Recursive read-only (RRO) bind-mount: `nerdctl run -v /mnt:/mnt:rro` (make children such as `/mnt/usb` to be read-only, too). + Requires kernel >= 5.12. +The same feature was later introduced in Docker v25 with a different syntax. nerdctl will support Docker v25 syntax too in the future. ## Similar tools - [`ctr`](https://github.com/containerd/containerd/tree/main/cmd/ctr): incompatible with Docker CLI, and not friendly to users. From 9b62e889b8578ba25e3c629b49fe070b6da4b9bc Mon Sep 17 00:00:00 2001 From: David Son Date: Mon, 13 Nov 2023 18:37:19 +0000 Subject: [PATCH 0236/1066] Add SOCI index digest flag `soci image rpull` and the SOCI library both allow for a particular SOCI index to be specified, so this change adds support for passing this in. Since no existing structure was in place to pass flags to remote snapshotters, this change also introduces the structures needed to support such future changes. Signed-off-by: David Son --- cmd/nerdctl/image_pull.go | 19 +++++- cmd/nerdctl/image_pull_linux_test.go | 95 +++++++++++++++++----------- docs/command-reference.md | 1 + pkg/api/types/image_types.go | 8 ++- pkg/cmd/compose/compose.go | 4 +- pkg/cmd/image/pull.go | 4 +- pkg/imgutil/imgutil.go | 10 +-- pkg/imgutil/snapshotter.go | 20 +++--- pkg/imgutil/snapshotter_test.go | 3 +- pkg/ipfs/image.go | 4 +- 10 files changed, 107 insertions(+), 61 deletions(-) diff --git a/cmd/nerdctl/image_pull.go b/cmd/nerdctl/image_pull.go index 71d00899d23..11b2444870f 100644 --- a/cmd/nerdctl/image_pull.go +++ b/cmd/nerdctl/image_pull.go @@ -20,6 +20,7 @@ import ( "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/cmd/image" + "github.com/containerd/nerdctl/pkg/imgutil" "github.com/spf13/cobra" ) @@ -56,6 +57,10 @@ func newPullCommand() *cobra.Command { pullCommand.Flags().String("cosign-certificate-oidc-issuer-regexp", "", "A regular expression alternative to --certificate-oidc-issuer for --verify=cosign,. Accepts the Go regular expression syntax described at https://golang.org/s/re2syntax. Either --cosign-certificate-oidc-issuer or --cosign-certificate-oidc-issuer-regexp must be set for keyless flows") // #endregion + // #region socipull flags + pullCommand.Flags().String("soci-index-digest", "", "Specify a particular index digest for SOCI. If left empty, SOCI will automatically use the index determined by the selection policy.") + // #endregion + pullCommand.Flags().BoolP("quiet", "q", false, "Suppress verbose output") pullCommand.Flags().String("ipfs-address", "", "multiaddr of IPFS API (default uses $IPFS_PATH env variable if defined or local directory ~/.ipfs)") @@ -81,6 +86,7 @@ func processPullCommandFlags(cmd *cobra.Command) (types.ImagePullOptions, error) if err != nil { return types.ImagePullOptions{}, err } + quiet, err := cmd.Flags().GetBool("quiet") if err != nil { return types.ImagePullOptions{}, err @@ -89,6 +95,12 @@ func processPullCommandFlags(cmd *cobra.Command) (types.ImagePullOptions, error) if err != nil { return types.ImagePullOptions{}, err } + + sociIndexDigest, err := cmd.Flags().GetString("soci-index-digest") + if err != nil { + return types.ImagePullOptions{}, err + } + verifyOptions, err := processImageVerifyOptions(cmd) if err != nil { return types.ImagePullOptions{}, err @@ -101,8 +113,11 @@ func processPullCommandFlags(cmd *cobra.Command) (types.ImagePullOptions, error) Unpack: unpackStr, Quiet: quiet, IPFSAddress: ipfsAddressStr, - Stdout: cmd.OutOrStdout(), - Stderr: cmd.OutOrStderr(), + RFlags: imgutil.RemoteSnapshotterFlags{ + SociIndexDigest: sociIndexDigest, + }, + Stdout: cmd.OutOrStdout(), + Stderr: cmd.OutOrStderr(), }, nil } diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image_pull_linux_test.go index 2ddf44ba882..b2addb786e3 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image_pull_linux_test.go @@ -148,55 +148,74 @@ CMD ["echo", "nerdctl-build-test-string"] func TestPullSoci(t *testing.T) { testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - requiresSoci(base) - - //counting initial snapshot mounts - initialMounts, err := exec.Command("mount").Output() - if err != nil { - t.Fatal(err) + tests := []struct { + name string + sociIndexDigest string + }{ + { + name: "Run without specifying SOCI index", + sociIndexDigest: "", + }, + { + name: "Run with bad SOCI index", + sociIndexDigest: "sha256:thisisabadindex0000000000000000000000000000000000000000000000000", + }, } - remoteSnapshotsInitialCount := strings.Count(string(initialMounts), "fuse.rawBridge") + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + base := testutil.NewBase(t) + requiresSoci(base) - //validating `nerdctl --snapshotter=soci pull` and `soci rpull` behave the same using mounts - pullOutput := base.Cmd("--snapshotter=soci", "pull", testutil.FfmpegSociImage).Out() - base.T.Logf("pull output: %s", pullOutput) + //counting initial snapshot mounts + initialMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } - actualMounts, err := exec.Command("mount").Output() - if err != nil { - t.Fatal(err) - } - remoteSnapshotsActualCount := strings.Count(string(actualMounts), "fuse.rawBridge") - base.T.Logf("number of actual mounts: %v", remoteSnapshotsActualCount) + remoteSnapshotsInitialCount := strings.Count(string(initialMounts), "fuse.rawBridge") - rmiOutput := base.Cmd("rmi", testutil.FfmpegSociImage).Out() - base.T.Logf("rmi output: %s", rmiOutput) + //validating `nerdctl --snapshotter=soci pull` and `soci rpull` behave the same using mounts + pullOutput := base.Cmd("--snapshotter=soci", "pull", testutil.FfmpegSociImage).Out() + base.T.Logf("pull output: %s", pullOutput) - sociExecutable, err := exec.LookPath("soci") - if err != nil { - t.Fatalf("SOCI is not installed.") - } + actualMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } + remoteSnapshotsActualCount := strings.Count(string(actualMounts), "fuse.rawBridge") + base.T.Logf("number of actual mounts: %v", remoteSnapshotsActualCount) - rpullCmd := exec.Command(sociExecutable, []string{"image", "rpull", testutil.FfmpegSociImage}...) + rmiOutput := base.Cmd("rmi", testutil.FfmpegSociImage).Out() + base.T.Logf("rmi output: %s", rmiOutput) - rpullCmd.Env = os.Environ() + sociExecutable, err := exec.LookPath("soci") + if err != nil { + t.Fatalf("SOCI is not installed.") + } - err = rpullCmd.Run() - if err != nil { - t.Fatal(err) - } + rpullCmd := exec.Command(sociExecutable, []string{"image", "rpull", testutil.FfmpegSociImage}...) - expectedMounts, err := exec.Command("mount").Output() - if err != nil { - t.Fatal(err) - } + rpullCmd.Env = os.Environ() + + err = rpullCmd.Run() + if err != nil { + t.Fatal(err) + } - remoteSnapshotsExpectedCount := strings.Count(string(expectedMounts), "fuse.rawBridge") - base.T.Logf("number of expected mounts: %v", remoteSnapshotsExpectedCount) + expectedMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } - if remoteSnapshotsExpectedCount != (remoteSnapshotsActualCount - remoteSnapshotsInitialCount) { - t.Fatalf("incorrect number of remote snapshots; expected=%d, actual=%d", - remoteSnapshotsExpectedCount, remoteSnapshotsActualCount) + remoteSnapshotsExpectedCount := strings.Count(string(expectedMounts), "fuse.rawBridge") + base.T.Logf("number of expected mounts: %v", remoteSnapshotsExpectedCount) + + if remoteSnapshotsExpectedCount != (remoteSnapshotsActualCount - remoteSnapshotsInitialCount) { + t.Fatalf("incorrect number of remote snapshots; expected=%d, actual=%d", + remoteSnapshotsExpectedCount, remoteSnapshotsActualCount) + } + }) } + } diff --git a/docs/command-reference.md b/docs/command-reference.md index 81f9bc49b9a..a67d9fa5e98 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -757,6 +757,7 @@ Flags: - :nerd_face: `--cosign-certificate-oidc-issuer`: The OIDC issuer expected in a valid Fulcio certificate for --verify=cosign,, e.g. https://token.actions.githubusercontent.com or https://oauth2.sigstore.dev/auth. Either --cosign-certificate-oidc-issuer or --cosign-certificate-oidc-issuer-regexp must be set for keyless flows - :nerd_face: `--cosign-certificate-oidc-issuer-regexp`: A regular expression alternative to --certificate-oidc-issuer for --verify=cosign,. Accepts the Go regular expression syntax described at https://golang.org/s/re2syntax. Either --cosign-certificate-oidc-issuer or --cosign-certificate-oidc-issuer-regexp must be set for keyless flows - :nerd_face: `--ipfs-address`: Multiaddr of IPFS API (default uses `$IPFS_PATH` env variable if defined or local directory `~/.ipfs`) +- :nerd_face: `--soci-index-digest`: Specify a particular index digest for SOCI. If left empty, SOCI will automatically use the index determined by the selection policy. Unimplemented `docker pull` flags: `--all-tags`, `--disable-content-trust` (default true) diff --git a/pkg/api/types/image_types.go b/pkg/api/types/image_types.go index ea59098e6e8..aebee69ea03 100644 --- a/pkg/api/types/image_types.go +++ b/pkg/api/types/image_types.go @@ -16,7 +16,11 @@ package types -import "io" +import ( + "io" + + "github.com/containerd/nerdctl/pkg/imgutil" +) // ImageListOptions specifies options for `nerdctl image list`. type ImageListOptions struct { @@ -193,6 +197,8 @@ type ImagePullOptions struct { Quiet bool // multiaddr of IPFS API (default uses $IPFS_PATH env variable if defined or local directory ~/.ipfs) IPFSAddress string + // Flags to pass into remote snapshotters + RFlags imgutil.RemoteSnapshotterFlags } // ImageTagOptions specifies options for `nerdctl (image) tag`. diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 1b5cd8d37c0..287706f2e5c 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -125,7 +125,7 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op ipfsPath = dir } _, err = ipfs.EnsureImage(ctx, client, stdout, stderr, globalOptions.Snapshotter, scheme, ref, - pullMode, ocispecPlatforms, nil, quiet, ipfsPath) + pullMode, ocispecPlatforms, nil, quiet, ipfsPath, imgutil.RemoteSnapshotterFlags{}) return err } @@ -136,7 +136,7 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op } _, err = imgutil.EnsureImage(ctx, client, stdout, stderr, globalOptions.Snapshotter, ref, - pullMode, globalOptions.InsecureRegistry, globalOptions.HostsDir, ocispecPlatforms, nil, quiet) + pullMode, globalOptions.InsecureRegistry, globalOptions.HostsDir, ocispecPlatforms, nil, quiet, imgutil.RemoteSnapshotterFlags{}) return err } diff --git a/pkg/cmd/image/pull.go b/pkg/cmd/image/pull.go index 50ac66bb97f..68e14e03735 100644 --- a/pkg/cmd/image/pull.go +++ b/pkg/cmd/image/pull.go @@ -76,7 +76,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, } ensured, err = ipfs.EnsureImage(ctx, client, options.Stdout, options.Stderr, options.GOptions.Snapshotter, scheme, ref, - pull, ocispecPlatforms, unpack, quiet, ipfsPath) + pull, ocispecPlatforms, unpack, quiet, ipfsPath, options.RFlags) if err != nil { return nil, err } @@ -89,7 +89,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, } ensured, err = imgutil.EnsureImage(ctx, client, options.Stdout, options.Stderr, options.GOptions.Snapshotter, ref, - pull, options.GOptions.InsecureRegistry, options.GOptions.HostsDir, ocispecPlatforms, unpack, quiet) + pull, options.GOptions.InsecureRegistry, options.GOptions.HostsDir, ocispecPlatforms, unpack, quiet, options.RFlags) if err != nil { return nil, err } diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 9c14abcd5dc..9dd63502cff 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -103,7 +103,7 @@ func GetExistingImage(ctx context.Context, client *containerd.Client, snapshotte // # When insecure is set, skips verifying certs, and also falls back to HTTP when the registry does not speak HTTPS // // FIXME: this func has too many args -func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter, rawRef string, mode PullMode, insecure bool, hostsDirs []string, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool) (*EnsuredImage, error) { +func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter, rawRef string, mode PullMode, insecure bool, hostsDirs []string, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, rFlags RemoteSnapshotterFlags) (*EnsuredImage, error) { switch mode { case "always", "missing", "never": // NOP @@ -142,7 +142,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr return nil, err } - img, err := PullImage(ctx, client, stdout, stderr, snapshotter, resolver, ref, ocispecPlatforms, unpack, quiet) + img, err := PullImage(ctx, client, stdout, stderr, snapshotter, resolver, ref, ocispecPlatforms, unpack, quiet, rFlags) if err != nil { // In some circumstance (e.g. people just use 80 port to support pure http), the error will contain message like "dial tcp : connection refused". if !errutil.IsErrHTTPResponseToHTTPSClient(err) && !errutil.IsErrConnectionRefused(err) { @@ -155,7 +155,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr if err != nil { return nil, err } - return PullImage(ctx, client, stdout, stderr, snapshotter, resolver, ref, ocispecPlatforms, unpack, quiet) + return PullImage(ctx, client, stdout, stderr, snapshotter, resolver, ref, ocispecPlatforms, unpack, quiet, rFlags) } log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain) log.G(ctx).Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)") @@ -194,7 +194,7 @@ func ResolveDigest(ctx context.Context, rawRef string, insecure bool, hostsDirs } // PullImage pulls an image using the specified resolver. -func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter string, resolver remotes.Resolver, ref string, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool) (*EnsuredImage, error) { +func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter string, resolver remotes.Resolver, ref string, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, rFlags RemoteSnapshotterFlags) (*EnsuredImage, error) { ctx, done, err := client.WithLease(ctx) if err != nil { return nil, err @@ -230,7 +230,7 @@ func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io containerd.WithUnpackOpts([]containerd.UnpackOpt{imgcryptUnpackOpt})) // different remote snapshotters will update pull.Config separately - snOpt.apply(config, ref) + snOpt.apply(config, ref, rFlags) } else { log.G(ctx).Debugf("The image will not be unpacked. Platforms=%v.", ocispecPlatforms) } diff --git a/pkg/imgutil/snapshotter.go b/pkg/imgutil/snapshotter.go index d1ce63cb8f1..694ea518e19 100644 --- a/pkg/imgutil/snapshotter.go +++ b/pkg/imgutil/snapshotter.go @@ -48,10 +48,14 @@ var builtinRemoteSnapshotterOpts = map[string]snapshotterOpts{ snapshotterNameCvmfs: &remoteSnapshotterOpts{snapshotter: "cvmfs-snapshotter"}, } +type RemoteSnapshotterFlags struct { + SociIndexDigest string +} + // snapshotterOpts is used to update pull config // for different snapshotters type snapshotterOpts interface { - apply(config *pull.Config, ref string) + apply(config *pull.Config, ref string, rFlags RemoteSnapshotterFlags) isRemote() bool } @@ -73,17 +77,17 @@ func getSnapshotterOpts(snapshotter string) snapshotterOpts { // interface `snapshotterOpts.isRemote()` function type remoteSnapshotterOpts struct { snapshotter string - extraLabels func(func(images.Handler) images.Handler) func(images.Handler) images.Handler + extraLabels func(func(images.Handler) images.Handler, RemoteSnapshotterFlags) func(images.Handler) images.Handler } func (rs *remoteSnapshotterOpts) isRemote() bool { return true } -func (rs *remoteSnapshotterOpts) apply(config *pull.Config, ref string) { +func (rs *remoteSnapshotterOpts) apply(config *pull.Config, ref string, rFlags RemoteSnapshotterFlags) { h := ctdsnapshotters.AppendInfoHandlerWrapper(ref) if rs.extraLabels != nil { - h = rs.extraLabels(h) + h = rs.extraLabels(h, rFlags) } config.RemoteOpts = append( config.RemoteOpts, @@ -98,7 +102,7 @@ type defaultSnapshotterOpts struct { snapshotter string } -func (dsn *defaultSnapshotterOpts) apply(config *pull.Config, _ref string) { +func (dsn *defaultSnapshotterOpts) apply(config *pull.Config, _ref string, rFlags RemoteSnapshotterFlags) { config.RemoteOpts = append( config.RemoteOpts, containerd.WithPullSnapshotter(dsn.snapshotter)) @@ -109,10 +113,10 @@ func (dsn *defaultSnapshotterOpts) isRemote() bool { return false } -func stargzExtraLabels(f func(images.Handler) images.Handler) func(images.Handler) images.Handler { +func stargzExtraLabels(f func(images.Handler) images.Handler, rFlags RemoteSnapshotterFlags) func(images.Handler) images.Handler { return source.AppendExtraLabelsHandler(prefetchSize, f) } -func sociExtraLabels(f func(images.Handler) images.Handler) func(images.Handler) images.Handler { - return socisource.AppendDefaultLabelsHandlerWrapper("", f) +func sociExtraLabels(f func(images.Handler) images.Handler, rFlags RemoteSnapshotterFlags) func(images.Handler) images.Handler { + return socisource.AppendDefaultLabelsHandlerWrapper(rFlags.SociIndexDigest, f) } diff --git a/pkg/imgutil/snapshotter_test.go b/pkg/imgutil/snapshotter_test.go index 5ca8115daa9..f50c863c296 100644 --- a/pkg/imgutil/snapshotter_test.go +++ b/pkg/imgutil/snapshotter_test.go @@ -93,7 +93,8 @@ func sameOpts(want snapshotterOpts) func(*testing.T, snapshotterOpts) { func getAndApplyRemoteOpts(t *testing.T, sn string) *containerd.RemoteContext { config := &pull.Config{} snOpts := getSnapshotterOpts(sn) - snOpts.apply(config, testRef) + rFlags := RemoteSnapshotterFlags{} + snOpts.apply(config, testRef, rFlags) rc := &containerd.RemoteContext{} for _, o := range config.RemoteOpts { diff --git a/pkg/ipfs/image.go b/pkg/ipfs/image.go index f5df458ae65..0519eefbf15 100644 --- a/pkg/ipfs/image.go +++ b/pkg/ipfs/image.go @@ -40,7 +40,7 @@ import ( const ipfsPathEnv = "IPFS_PATH" // EnsureImage pull the specified image from IPFS. -func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter string, scheme string, ref string, mode imgutil.PullMode, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, ipfsPath string) (*imgutil.EnsuredImage, error) { +func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter string, scheme string, ref string, mode imgutil.PullMode, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, ipfsPath string, rFlags imgutil.RemoteSnapshotterFlags) (*imgutil.EnsuredImage, error) { switch mode { case "always", "missing", "never": // NOP @@ -73,7 +73,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr if err != nil { return nil, err } - return imgutil.PullImage(ctx, client, stdout, stderr, snapshotter, r, ref, ocispecPlatforms, unpack, quiet) + return imgutil.PullImage(ctx, client, stdout, stderr, snapshotter, r, ref, ocispecPlatforms, unpack, quiet, rFlags) } // Push pushes the specified image to IPFS. From 51d09871430a3c3d5126086ade5f1a296c677496 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Nov 2023 00:18:45 +0000 Subject: [PATCH 0237/1066] build(deps): bump github.com/klauspost/compress from 1.17.2 to 1.17.3 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.2 to 1.17.3. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.2...v1.17.3) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0ed4a199dd7..a2ac6bb2735 100644 --- a/go.mod +++ b/go.mod @@ -87,7 +87,7 @@ require ( github.com/google/uuid v1.3.1 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.2 + github.com/klauspost/compress v1.17.3 github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/go.sum b/go.sum index 65ace81def9..f360038e460 100644 --- a/go.sum +++ b/go.sum @@ -167,8 +167,8 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= +github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= From 76c57d2068fb447abaab91be520fedbf261305d8 Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Fri, 17 Nov 2023 11:26:59 +0800 Subject: [PATCH 0238/1066] fix: typo Signed-off-by: guoguangwu --- pkg/cmd/container/create.go | 2 +- pkg/containerutil/containerutil.go | 2 +- pkg/labels/labels.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index ca40bbe4c43..22f4ac10915 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -486,7 +486,7 @@ func withStop(stopSignal string, stopTimeout int, ensuredImage *imgutil.EnsuredI } c.Labels[containerd.StopSignalLabel] = stopSignal if stopTimeout != 0 { - c.Labels[labels.StopTimout] = strconv.Itoa(stopTimeout) + c.Labels[labels.StopTimeout] = strconv.Itoa(stopTimeout) } return nil } diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 31799827d59..79d328b3bf0 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -333,7 +333,7 @@ func Stop(ctx context.Context, container containerd.Container, timeout *time.Dur } if timeout == nil { - t, ok := l[labels.StopTimout] + t, ok := l[labels.StopTimeout] if !ok { // Default is 10 seconds. t = "10" diff --git a/pkg/labels/labels.go b/pkg/labels/labels.go index e11e96a9958..fc0b5a574dd 100644 --- a/pkg/labels/labels.go +++ b/pkg/labels/labels.go @@ -85,7 +85,7 @@ const ( Bypass4netns = Prefix + "bypass4netns" // StopTimeout is seconds to wait for stop a container. - StopTimout = Prefix + "stop-timeout" + StopTimeout = Prefix + "stop-timeout" MACAddress = Prefix + "mac-address" From 30eaca099d52d1b19b61bb526066e33d581fce49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Nov 2023 22:22:10 +0000 Subject: [PATCH 0239/1066] build(deps): bump github.com/compose-spec/compose-go Bumps [github.com/compose-spec/compose-go](https://github.com/compose-spec/compose-go) from 1.20.1 to 1.20.2. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v1.20.1...v1.20.2) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a2ac6bb2735..6d50195fc60 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.11.4 github.com/awslabs/soci-snapshotter v0.4.0 - github.com/compose-spec/compose-go v1.20.1 + github.com/compose-spec/compose-go v1.20.2 github.com/containerd/accelerated-container-image v1.0.0 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 diff --git a/go.sum b/go.sum index f360038e460..a07c728054f 100644 --- a/go.sum +++ b/go.sum @@ -25,8 +25,8 @@ github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go v1.20.1 h1:I6gCMGLl96kEf8XZwaozeTwnNfxA2eVsO46W+5ciTEg= -github.com/compose-spec/compose-go v1.20.1/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= +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.0 h1:BWc+VNimtSXUCiegKWhqcHxN9GV4ve3kJEL1968AWF8= github.com/containerd/accelerated-container-image v1.0.0/go.mod h1:LYLT4rKKzJn9Ts0I8uk1pivFmqil/Y3WZT0u+9zb6BA= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= From 8e9ca2b1ed669cb7c9c2f6144a4d04f88b302839 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Nov 2023 22:22:42 +0000 Subject: [PATCH 0240/1066] build(deps): bump github.com/go-jose/go-jose/v3 from 3.0.0 to 3.0.1 Bumps [github.com/go-jose/go-jose/v3](https://github.com/go-jose/go-jose) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/go-jose/go-jose/releases) - [Changelog](https://github.com/go-jose/go-jose/blob/v3/CHANGELOG.md) - [Commits](https://github.com/go-jose/go-jose/compare/v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: github.com/go-jose/go-jose/v3 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a2ac6bb2735..28d5e1498d2 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( 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 - github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect diff --git a/go.sum b/go.sum index f360038e460..cab76f01085 100644 --- a/go.sum +++ b/go.sum @@ -108,8 +108,8 @@ github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= +github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= From afe990dbe49c441131f7b72648eacf9770c99783 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 21 Nov 2023 13:42:51 +0000 Subject: [PATCH 0241/1066] remove incompatible in TestComposeExecTTY Signed-off-by: Kay Yan --- cmd/nerdctl/compose_exec.go | 26 +++++++++++--------------- cmd/nerdctl/compose_exec_linux_test.go | 16 +++++++--------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/cmd/nerdctl/compose_exec.go b/cmd/nerdctl/compose_exec.go index f4bebfc9b92..7f0ba6017bb 100644 --- a/cmd/nerdctl/compose_exec.go +++ b/cmd/nerdctl/compose_exec.go @@ -36,9 +36,7 @@ func newComposeExecCommand() *cobra.Command { } composeExecCommand.Flags().SetInterspersed(false) - composeExecCommand.Flags().BoolP("tty", "t", true, "Allocate a pseudo-TTY") // missing in Docker Compose v2? composeExecCommand.Flags().BoolP("no-TTY", "T", false, "Disable pseudo-TTY allocation. By default nerdctl compose exec allocates a TTY.") - composeExecCommand.Flags().BoolP("interactive", "i", true, "Keep STDIN open even if not attached") composeExecCommand.Flags().BoolP("detach", "d", false, "Detached mode: Run containers in the background") composeExecCommand.Flags().StringP("workdir", "w", "", "Working directory inside the container") // env needs to be StringArray, not StringSlice, to prevent "FOO=foo1,foo2" from being split to {"FOO=foo1", "foo2"} @@ -47,15 +45,13 @@ func newComposeExecCommand() *cobra.Command { composeExecCommand.Flags().StringP("user", "u", "", "Username or UID (format: [:])") composeExecCommand.Flags().Int("index", 1, "index of the container if the service has multiple instances.") - composeExecCommand.PreRunE = func(cmd *cobra.Command, args []string) error { - flags := cmd.Flags() - if noTTY, _ := flags.GetBool("no-TTY"); noTTY { - if err := flags.Set("tty", "false"); err != nil { - return err - } - } - return nil - } + composeExecCommand.Flags().BoolP("interactive", "i", true, "Keep STDIN open even if not attached") + composeExecCommand.Flags().MarkHidden("interactive") + // The -t does not has effect to keep the compatibility with docker. + // The proposal of -t is to keep "muscle memory" with compose v1: https://github.com/docker/compose/issues/9207 + // FYI: https://github.com/docker/compose/blob/v2.23.1/cmd/compose/exec.go#L77 + composeExecCommand.Flags().BoolP("tty", "t", true, "Allocate a pseudo-TTY") + composeExecCommand.Flags().MarkHidden("tty") return composeExecCommand } @@ -69,7 +65,7 @@ func composeExecAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - tty, err := cmd.Flags().GetBool("tty") + noTty, err := cmd.Flags().GetBool("no-TTY") if err != nil { return err } @@ -106,8 +102,8 @@ func composeExecAction(cmd *cobra.Command, args []string) error { return errors.New("currently flag -i and -d cannot be specified together (FIXME)") } // https://github.com/containerd/nerdctl/blob/v1.0.0/cmd/nerdctl/exec.go#L122 - if tty && detach { - return errors.New("currently flag -t and -d cannot be specified together (FIXME)") + if !noTty && detach { + return errors.New("currently flag -d should be specified with --no-TTY (FIXME)") } client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) @@ -129,7 +125,7 @@ func composeExecAction(cmd *cobra.Command, args []string) error { Index: index, Interactive: interactive, - Tty: tty, + Tty: !noTty, Detach: detach, WorkDir: workdir, Env: env, diff --git a/cmd/nerdctl/compose_exec_linux_test.go b/cmd/nerdctl/compose_exec_linux_test.go index 9a9da25e85d..f12dc530fa2 100644 --- a/cmd/nerdctl/compose_exec_linux_test.go +++ b/cmd/nerdctl/compose_exec_linux_test.go @@ -52,8 +52,8 @@ services: defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").AssertOK() // test basic functionality and `--workdir` flag - base.ComposeCmd("-f", comp.YAMLFullPath(), "exec", "-i=false", "-t=false", "svc0", "echo", "success").AssertOutExactly("success\n") - base.ComposeCmd("-f", comp.YAMLFullPath(), "exec", "-i=false", "-t=false", "--workdir", "/tmp", "svc0", "pwd").AssertOutExactly("/tmp\n") + base.ComposeCmd("-f", comp.YAMLFullPath(), "exec", "-i=false", "--no-TTY", "svc0", "echo", "success").AssertOutExactly("success\n") + base.ComposeCmd("-f", comp.YAMLFullPath(), "exec", "-i=false", "--no-TTY", "--workdir", "/tmp", "svc0", "pwd").AssertOutExactly("/tmp\n") // cannot `exec` on non-running service base.ComposeCmd("-f", comp.YAMLFullPath(), "exec", "svc1", "echo", "success").AssertFail() } @@ -79,7 +79,7 @@ services: // FYI: https://github.com/containerd/nerdctl/blob/e4b2b6da56555dc29ed66d0fd8e7094ff2bc002d/cmd/nerdctl/run_test.go#L177 base.Env = append(os.Environ(), "CORGE=corge-value-in-host", "GARPLY=garply-value-in-host") - base.ComposeCmd("-f", comp.YAMLFullPath(), "exec", "-i=false", "-t=false", + base.ComposeCmd("-f", comp.YAMLFullPath(), "exec", "-i=false", "--no-TTY", "--env", "FOO=foo1,foo2", "--env", "BAR=bar1 bar2", "--env", "BAZ=", @@ -153,7 +153,7 @@ services: } for userStr, expected := range testCases { - args := []string{"-f", comp.YAMLFullPath(), "exec", "-i=false", "-t=false"} + args := []string{"-f", comp.YAMLFullPath(), "exec", "-i=false", "--no-TTY"} if userStr != "" { args = append(args, "--user", userStr) } @@ -164,8 +164,6 @@ services: func TestComposeExecTTY(t *testing.T) { // `-i` in `compose run & exec` is only supported in compose v2. - // Currently CI is using compose v1. - testutil.DockerIncompatible(t) base := testutil.NewBase(t) if testutil.GetTarget() == testutil.Nerdctl { testutil.RequireDaemonVersion(base, ">= 1.6.0-0") @@ -197,8 +195,8 @@ services: unbuffer := []string{"unbuffer"} base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), "exec", "svc0", "stty").AssertOutContains(sttyPartialOutput) // `-it` base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), "exec", "-i=false", "svc0", "stty").AssertOutContains(sttyPartialOutput) // `-t` - base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), "exec", "-t=false", "svc0", "stty").AssertFail() // `-i` - base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), "exec", "-i=false", "-t=false", "svc0", "stty").AssertFail() + base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), "exec", "--no-TTY", "svc0", "stty").AssertFail() // `-i` + base.ComposeCmdWithHelper(unbuffer, "-f", comp.YAMLFullPath(), "exec", "-i=false", "--no-TTY", "svc0", "stty").AssertFail() } func TestComposeExecWithIndex(t *testing.T) { @@ -243,7 +241,7 @@ services: return nil }) } - cmds := []string{"-f", comp.YAMLFullPath(), "exec", "-i=false", "-t=false", "--index", j, "svc0"} + cmds := []string{"-f", comp.YAMLFullPath(), "exec", "-i=false", "--no-TTY", "--index", j, "svc0"} base.ComposeCmd(append(cmds, "cat", "/etc/hosts")...). AssertOutWithFunc(func(stdout string) error { lines := strings.Split(stdout, "\n") From 2d508151b320446aeb8e5cb1f9bd3fd2e4ec9fe5 Mon Sep 17 00:00:00 2001 From: yanggang Date: Fri, 24 Nov 2023 02:38:31 +0000 Subject: [PATCH 0242/1066] Fix nerdctl system info : sort problem. Signed-off-by: yanggang --- pkg/cmd/system/info.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/system/info.go b/pkg/cmd/system/info.go index fb42ffd54d9..77aa78cb2b6 100644 --- a/pkg/cmd/system/info.go +++ b/pkg/cmd/system/info.go @@ -125,7 +125,7 @@ func prettyPrintInfoNative(w io.Writer, info *native.Info) error { } sorter := func(x []*introspection.Plugin) func(int, int) bool { return func(i, j int) bool { - return x[i].Type+"."+x[j].ID < x[j].Type+"."+x[j].ID + return x[i].Type+"."+x[i].ID < x[j].Type+"."+x[j].ID } } sort.Slice(enabledPlugins, sorter(enabledPlugins)) From 6e5c7f768a80cd711b1d1ae7ba936b792a1b46d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Nov 2023 08:44:56 +0000 Subject: [PATCH 0243/1066] build(deps): bump github.com/containerd/accelerated-container-image Bumps [github.com/containerd/accelerated-container-image](https://github.com/containerd/accelerated-container-image) from 1.0.0 to 1.0.2. - [Release notes](https://github.com/containerd/accelerated-container-image/releases) - [Commits](https://github.com/containerd/accelerated-container-image/compare/v1.0.0...v1.0.2) --- updated-dependencies: - dependency-name: github.com/containerd/accelerated-container-image dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8e601927f70..3bc643aee84 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Microsoft/hcsshim v0.11.4 github.com/awslabs/soci-snapshotter v0.4.0 github.com/compose-spec/compose-go v1.20.2 - github.com/containerd/accelerated-container-image v1.0.0 + github.com/containerd/accelerated-container-image v1.0.2 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.7.9 diff --git a/go.sum b/go.sum index 679afd995c4..c129a96790c 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,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.0 h1:BWc+VNimtSXUCiegKWhqcHxN9GV4ve3kJEL1968AWF8= -github.com/containerd/accelerated-container-image v1.0.0/go.mod h1:LYLT4rKKzJn9Ts0I8uk1pivFmqil/Y3WZT0u+9zb6BA= +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/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.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= From ec728349b758fa995688758c9208ba48763839eb Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sat, 25 Nov 2023 10:29:15 +0900 Subject: [PATCH 0244/1066] update containerd (1.7.9) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 18 +++++++++--------- Dockerfile | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2a98c56dcb4..5e3f595de3f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,9 +79,9 @@ jobs: - ubuntu: 20.04 containerd: v1.6.24 - ubuntu: 20.04 - containerd: v1.7.8 + containerd: v1.7.9 - ubuntu: 22.04 - containerd: v1.7.8 + containerd: v1.7.9 - ubuntu: 22.04 containerd: main env: @@ -113,7 +113,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 22.04 - containerd: v1.7.8 + containerd: v1.7.9 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -160,10 +160,10 @@ jobs: containerd: v1.6.24 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.8 + containerd: v1.7.9 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.8 + containerd: v1.7.9 target: test-integration-rootless - ubuntu: 22.04 containerd: main @@ -172,10 +172,10 @@ jobs: containerd: v1.6.24 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.8 + containerd: v1.7.9 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.8 + containerd: v1.7.9 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main @@ -267,7 +267,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: repository: containerd/containerd - ref: v1.7.8 + ref: v1.7.9 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -275,7 +275,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.8 + ctrdVersion: 1.7.9 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index 7b9d2d71987..5ea2d80e3ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.8 +ARG CONTAINERD_VERSION=v1.7.9 ARG RUNC_VERSION=v1.1.10 ARG CNI_PLUGINS_VERSION=v1.3.0 From e080801632858765ec1c6ac6da8c302ea3de064c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sat, 25 Nov 2023 10:33:56 +0900 Subject: [PATCH 0245/1066] update Kubo (0.24.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5ea2d80e3ae..6f325afa0a5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ ARG BYPASS4NETNS_VERSION=v0.3.0 ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 # Extra deps: IPFS -ARG KUBO_VERSION=v0.23.0 +ARG KUBO_VERSION=v0.24.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug From aeeb338b0fb7df144277510e6d0ce4cab5ff96e1 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sat, 25 Nov 2023 10:34:10 +0900 Subject: [PATCH 0246/1066] update Nydus (2.2.4) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6f325afa0a5..043d2367e34 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,7 +48,7 @@ ARG GO_VERSION=1.21 ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.11.0 -ARG NYDUS_VERSION=v2.2.3 +ARG NYDUS_VERSION=v2.2.4 ARG SOCI_SNAPSHOTTER_VERSION=0.4.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.3.0 AS xx From d6c7f0f3e1af709349e82d28e1f7ef0c75f66167 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 22:13:54 +0000 Subject: [PATCH 0247/1066] build(deps): bump golang.org/x/crypto from 0.15.0 to 0.16.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.15.0 to 0.16.0. - [Commits](https://github.com/golang/crypto/compare/v0.15.0...v0.16.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 3bc643aee84..8fae9da5fa0 100644 --- a/go.mod +++ b/go.mod @@ -51,11 +51,11 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 - golang.org/x/crypto v0.15.0 + golang.org/x/crypto v0.16.0 golang.org/x/net v0.18.0 golang.org/x/sync v0.5.0 - golang.org/x/sys v0.14.0 - golang.org/x/term v0.14.0 + golang.org/x/sys v0.15.0 + golang.org/x/term v0.15.0 golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 diff --git a/go.sum b/go.sum index c129a96790c..1ae82463cdc 100644 --- a/go.sum +++ b/go.sum @@ -328,8 +328,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= -golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230725012225-302865e7556b h1:tK7yjGqVRzYdXsBcfD2MLhFAhHfDgGLm2rY1ub7FA9k= golang.org/x/exp v0.0.0-20230725012225-302865e7556b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= @@ -388,11 +388,11 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= -golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From a8aaac297eb3b61fbf44b7d8c9234e021fd8402e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 05:42:39 +0000 Subject: [PATCH 0248/1066] build(deps): bump golang.org/x/net from 0.18.0 to 0.19.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.18.0 to 0.19.0. - [Commits](https://github.com/golang/net/compare/v0.18.0...v0.19.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8fae9da5fa0..bf2a3c261ec 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 golang.org/x/crypto v0.16.0 - golang.org/x/net v0.18.0 + golang.org/x/net v0.19.0 golang.org/x/sync v0.5.0 golang.org/x/sys v0.15.0 golang.org/x/term v0.15.0 diff --git a/go.sum b/go.sum index 1ae82463cdc..d1499e6575a 100644 --- a/go.sum +++ b/go.sum @@ -352,8 +352,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 71bf53b3b2d5ef73b763fb8fe745e4bfbedcae25 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 28 Nov 2023 15:00:02 +0900 Subject: [PATCH 0249/1066] update golangci-lint (1.55.2) Fix: ``` pkg/cmd/compose/compose.go:83:10: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) } else { return false, volGetErr } pkg/cmd/container/create.go:658:9: indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) (revive) } else { return err } ``` Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 2 +- pkg/cmd/compose/compose.go | 6 +++--- pkg/cmd/container/create.go | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5e3f595de3f..35871422422 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,7 +48,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v3.7.0 with: - version: v1.54.2 + version: v1.55.2 args: --verbose - name: yamllint-lint run: yamllint . diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 287706f2e5c..65be64b8965 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -76,13 +76,13 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op return nil, err } options.VolumeExists = func(volName string) (bool, error) { - if _, volGetErr := volStore.Get(volName, false); volGetErr == nil { + _, volGetErr := volStore.Get(volName, false) + if volGetErr == nil { return true, nil } else if errors.Is(volGetErr, errdefs.ErrNotFound) { return false, nil - } else { - return false, volGetErr } + return false, volGetErr } options.ImageExists = func(ctx context.Context, rawRef string) (bool, error) { diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 22f4ac10915..c39d036c628 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -642,7 +642,8 @@ func propagateContainerdLabelsToOCIAnnotations() oci.SpecOpts { } func writeCIDFile(path, id string) error { - if _, err := os.Stat(path); err == nil { + _, err := os.Stat(path) + if err == nil { return fmt.Errorf("container ID file found, make sure the other container isn't running or delete %s", path) } else if errors.Is(err, os.ErrNotExist) { f, err := os.Create(path) @@ -655,9 +656,8 @@ func writeCIDFile(path, id string) error { return err } return nil - } else { - return err } + return err } // generateLogConfig creates a LogConfig for the current container store From ed633b3ba4d0d7ee60f95a32a0a709a65d826a67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Nov 2023 22:40:03 +0000 Subject: [PATCH 0250/1066] build(deps): bump github.com/containerd/containerd from 1.7.9 to 1.7.10 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.9 to 1.7.10. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.9...v1.7.10) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bf2a3c261ec..849b4db1348 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.0.2 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 - github.com/containerd/containerd v1.7.9 + github.com/containerd/containerd v1.7.10 github.com/containerd/continuity v0.4.3 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.9 diff --git a/go.sum b/go.sum index d1499e6575a..77d04557499 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKk github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.9 h1:KOhK01szQbM80YfW1H6RZKh85PHGqY/9OcEZ35Je8sc= -github.com/containerd/containerd v1.7.9/go.mod h1:0/W44LWEYfSHoxBtsHIiNU/duEkgpMokemafHVCpq9Y= +github.com/containerd/containerd v1.7.10 h1:2nfZyT8BV0C3iKu/SsGxKVAf9dp5W7l9nA8JmWmDGuo= +github.com/containerd/containerd v1.7.10/go.mod h1:0/W44LWEYfSHoxBtsHIiNU/duEkgpMokemafHVCpq9Y= 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/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= From 21dc100a2230350bfabe859724c9c9e3e3783905 Mon Sep 17 00:00:00 2001 From: Kenichiro Kadowaki Date: Wed, 29 Nov 2023 23:38:06 +0000 Subject: [PATCH 0251/1066] fix typo Signed-off-by: Kenichiro Kadowaki --- pkg/logging/logging.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index c55e6b81683..f59936f8f18 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -50,10 +50,10 @@ type Driver interface { } type DriverFactory func(map[string]string) (Driver, error) -type LogOpsValidateFunc func(logOptMap map[string]string) error +type LogOptsValidateFunc func(logOptMap map[string]string) error var drivers = make(map[string]DriverFactory) -var driversLogOptsValidateFunctions = make(map[string]LogOpsValidateFunc) +var driversLogOptsValidateFunctions = make(map[string]LogOptsValidateFunc) func ValidateLogOpts(logDriver string, logOpts map[string]string) error { if value, ok := driversLogOptsValidateFunctions[logDriver]; ok && value != nil { @@ -62,7 +62,7 @@ func ValidateLogOpts(logDriver string, logOpts map[string]string) error { return nil } -func RegisterDriver(name string, f DriverFactory, validateFunc LogOpsValidateFunc) { +func RegisterDriver(name string, f DriverFactory, validateFunc LogOptsValidateFunc) { drivers[name] = f driversLogOptsValidateFunctions[name] = validateFunc } From 0e73e3edf021361a3338ebe881d353907f995335 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 30 Nov 2023 16:38:35 +0900 Subject: [PATCH 0252/1066] update containerd (1.7.10) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 24 ++++++++++++------------ Dockerfile | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 35871422422..6888083677c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,11 +77,11 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.24 + containerd: v1.6.25 - ubuntu: 20.04 - containerd: v1.7.9 + containerd: v1.7.10 - ubuntu: 22.04 - containerd: v1.7.9 + containerd: v1.7.10 - ubuntu: 22.04 containerd: main env: @@ -113,7 +113,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 22.04 - containerd: v1.7.9 + containerd: v1.7.10 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -157,25 +157,25 @@ jobs: # ubuntu-22.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.24 + containerd: v1.6.25 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.9 + containerd: v1.7.10 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.9 + containerd: v1.7.10 target: test-integration-rootless - ubuntu: 22.04 containerd: main target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.6.24 + containerd: v1.6.25 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.9 + containerd: v1.7.10 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.9 + containerd: v1.7.10 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main @@ -267,7 +267,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: repository: containerd/containerd - ref: v1.7.9 + ref: v1.7.10 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -275,7 +275,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.9 + ctrdVersion: 1.7.10 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index 043d2367e34..aa40ea1eee4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.9 +ARG CONTAINERD_VERSION=v1.7.10 ARG RUNC_VERSION=v1.1.10 ARG CNI_PLUGINS_VERSION=v1.3.0 From 198797f2556995599cd81b5ed7a1e671d7502789 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 22:05:41 +0000 Subject: [PATCH 0253/1066] build(deps): bump docker/metadata-action from 5.0.0 to 5.2.0 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.0.0 to 5.2.0. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/v5.0.0...v5.2.0) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 49d633b8ad3..a56d7b4e293 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -52,7 +52,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v5.0.0 + uses: docker/metadata-action@v5.2.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} From f709735a40ae522be9e131d73ac306dda7ce7c07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Dec 2023 22:58:08 +0000 Subject: [PATCH 0254/1066] build(deps): bump github.com/klauspost/compress from 1.17.3 to 1.17.4 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.3 to 1.17.4. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.3...v1.17.4) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 849b4db1348..d781ff557f4 100644 --- a/go.mod +++ b/go.mod @@ -87,7 +87,7 @@ require ( github.com/google/uuid v1.3.1 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.3 + github.com/klauspost/compress v1.17.4 github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/go.sum b/go.sum index 77d04557499..abf5d4e34b9 100644 --- a/go.sum +++ b/go.sum @@ -167,8 +167,8 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= From 722040c412e1f4f44ff1915cd9d6ee33990db443 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 18:04:29 +0000 Subject: [PATCH 0255/1066] build(deps): bump github.com/containernetworking/plugins Bumps [github.com/containernetworking/plugins](https://github.com/containernetworking/plugins) from 1.3.0 to 1.4.0. - [Release notes](https://github.com/containernetworking/plugins/releases) - [Commits](https://github.com/containernetworking/plugins/compare/v1.3.0...v1.4.0) --- updated-dependencies: - dependency-name: github.com/containernetworking/plugins dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 10 +++++----- go.sum | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index d781ff557f4..8b6c9f491ec 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/containerd/stargz-snapshotter/ipfs v0.15.1 github.com/containerd/typeurl/v2 v2.1.1 github.com/containernetworking/cni v1.1.2 - github.com/containernetworking/plugins v1.3.0 + github.com/containernetworking/plugins v1.4.0 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.4 @@ -77,13 +77,13 @@ require ( github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/go-jose/go-jose/v3 v3.0.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.3.1 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -127,8 +127,8 @@ require ( go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect golang.org/x/exp v0.0.0-20230725012225-302865e7556b // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/tools v0.11.0 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/tools v0.14.0 // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/grpc v1.59.0 // indirect diff --git a/go.sum b/go.sum index abf5d4e34b9..d66a0834b80 100644 --- a/go.sum +++ b/go.sum @@ -63,8 +63,8 @@ github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9Fqctt github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ= github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= -github.com/containernetworking/plugins v1.3.0 h1:QVNXMT6XloyMUoO2wUOqWTC1hWFV62Q6mVDp5H1HnjM= -github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0= +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/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8= @@ -111,8 +111,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -150,8 +150,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -226,11 +226,11 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= +github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= 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= @@ -338,8 +338,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.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= @@ -408,8 +408,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8= -golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From f2030d29112c7f44f228a5830736c4db1bdfeb6c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 5 Dec 2023 03:59:30 +0900 Subject: [PATCH 0256/1066] update CNI plugins (1.4.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.3.0 | 2 -- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.0 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.3.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.0 diff --git a/Dockerfile b/Dockerfile index aa40ea1eee4..1f84b8102c9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ # Basic deps ARG CONTAINERD_VERSION=v1.7.10 ARG RUNC_VERSION=v1.1.10 -ARG CNI_PLUGINS_VERSION=v1.3.0 +ARG CNI_PLUGINS_VERSION=v1.4.0 # Extra deps: Build ARG BUILDKIT_VERSION=v0.12.3 diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.3.0 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.3.0 deleted file mode 100644 index 202f83df0ab..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.3.0 +++ /dev/null @@ -1,2 +0,0 @@ -754a71ed60a4bd08726c3af705a7d55ee3df03122b12e389fdba4bea35d7dd7e cni-plugins-linux-amd64-v1.3.0.tgz -de7a666fd6ad83a228086bd55756db62ef335a193d1b143d910b69f079e30598 cni-plugins-linux-arm64-v1.3.0.tgz diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.0 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.0 new file mode 100644 index 00000000000..f78938c4f04 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.0 @@ -0,0 +1,2 @@ +c2485ddb3ffc176578ae30ae58137f0b88e50f7c7f2af7d53a569276b2949a33 cni-plugins-linux-amd64-v1.4.0.tgz +304d4389d5b732b7a73513d002c4895f731d030682d40653f411e10e39114194 cni-plugins-linux-arm64-v1.4.0.tgz From f600416931734cbba495b7b42881664ac0e65846 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:50:18 +0000 Subject: [PATCH 0257/1066] build(deps): bump docker/metadata-action from 5.2.0 to 5.3.0 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.2.0 to 5.3.0. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/v5.2.0...v5.3.0) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index a56d7b4e293..991c99893a2 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -52,7 +52,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v5.2.0 + uses: docker/metadata-action@v5.3.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} From 06628f63692352ee48e9ab72a196348cd5b615cd Mon Sep 17 00:00:00 2001 From: Zoe Date: Tue, 5 Dec 2023 13:01:03 +0800 Subject: [PATCH 0258/1066] nerdctl run: reset the default value of limits. With the oci spec, we have the default rlimits RLIMIT_NOFILE=1024:1024, If we start a pod in kubelet, this value we be reset to nil by cri. We use the nerdctl to start containers in production, this difference will cause user confused. When run a container if don't get any ulimit opts, reset the rlimits to nil. This will remove the default 1024 file limit. ```go if len(ulimitOpts) == 0 { ulimitOpts = append(ulimitOpts, withRlimits(nil)) } ``` Warning: this PR will make `nerdctl run` behave differently than before. Signed-off-by: Zoe --- pkg/cmd/container/run_linux.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index 5216e9c6548..cf22e642715 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -95,6 +95,13 @@ func setPlatformOptions(ctx context.Context, client *containerd.Client, id, uts if err != nil { return nil, err } + + // If without any ulimitOpts, we need to reset the default value from spec + // which has 1024 as file limit. Make this behavior same as containerd/cri. + if len(ulimitOpts) == 0 { + ulimitOpts = append(ulimitOpts, withRlimits(nil)) + } + opts = append(opts, ulimitOpts...) if options.Sysctl != nil { opts = append(opts, WithSysctls(strutil.ConvertKVStringsToMap(options.Sysctl))) From a4c33929a733fc025476e4310e6b6842e4f30e8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 22:28:28 +0000 Subject: [PATCH 0259/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.3 to 0.13.4. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.3...v0.13.4) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 8b6c9f491ec..741ee4b477b 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.9 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.3 + github.com/containerd/nydus-snapshotter v0.13.4 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 github.com/containerd/stargz-snapshotter/ipfs v0.15.1 @@ -126,11 +126,11 @@ require ( 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 - golang.org/x/exp v0.0.0-20230725012225-302865e7556b // 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-20230822172742-b8732ec3820d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // 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/grpc v1.59.0 // indirect google.golang.org/protobuf v1.31.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect diff --git a/go.sum b/go.sum index d66a0834b80..7a4feb5df5d 100644 --- a/go.sum +++ b/go.sum @@ -47,8 +47,8 @@ github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= 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.3 h1:aa4tz0l2Z+vLDuCCx5Ic6f1AQd9ZH/R0B5C/QXGY774= -github.com/containerd/nydus-snapshotter v0.13.3/go.mod h1:XWAz9ytsjBuKPVXDKP3xoMlcSKNsGnjXlEup6DuzUIo= +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/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= @@ -331,8 +331,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230725012225-302865e7556b h1:tK7yjGqVRzYdXsBcfD2MLhFAhHfDgGLm2rY1ub7FA9k= -golang.org/x/exp v0.0.0-20230725012225-302865e7556b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -420,10 +420,10 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= -google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +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/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= From a56dcfac74eeebac353b73cd44c9bd9b2a4bda7f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 22:39:23 +0000 Subject: [PATCH 0260/1066] build(deps): bump actions/setup-go from 4 to 5 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 689f1eab8c7..af5c1baa700 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: timeout-minutes: 40 steps: - uses: actions/checkout@v4.1.1 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: 1.21.x - name: "Compile binaries" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6888083677c..5c3daba554c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,7 @@ jobs: with: path: src/github.com/containerd/nerdctl fetch-depth: 100 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} cache-dependency-path: src/github.com/containerd/nerdctl @@ -40,7 +40,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} check-latest: true @@ -60,7 +60,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} check-latest: true @@ -205,7 +205,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} cache: true @@ -220,7 +220,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} cache: true @@ -258,7 +258,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: fetch-depth: 1 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} cache: true From 8567678ecc8e5de8d8ae60663706b2a01a48e72e Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Wed, 6 Dec 2023 18:54:01 +0000 Subject: [PATCH 0261/1066] Dedup mounts for /etc/hosts /etc/resolv.conf Signed-off-by: Kay Yan --- pkg/containerutil/container_network_manager.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 01eba80ed22..edba4de6c8c 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -385,6 +385,19 @@ func (m *hostNetworkManager) InternalNetworkingOptionLabels(_ context.Context) ( return opts, nil } +// withDedupMounts Returns the specOpts if the mountPath is not in existing mounts. +// for https://github.com/containerd/nerdctl/issues/2685 +func withDedupMounts(mountPath string, defaultSpec oci.SpecOpts) oci.SpecOpts { + return func(ctx context.Context, client oci.Client, c *containers.Container, s *oci.Spec) error { + for _, m := range s.Mounts { + if m.Destination == mountPath { + return nil + } + } + return defaultSpec(ctx, client, c, s) + } +} + // ContainerNetworkingOpts Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent // the network specs which need to be applied to the container with the given ID. func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containerID string) ([]oci.SpecOpts, []containerd.NewContainerOpts, error) { @@ -392,8 +405,8 @@ func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containe cOpts := []containerd.NewContainerOpts{} specs := []oci.SpecOpts{ oci.WithHostNamespace(specs.NetworkNamespace), - oci.WithHostHostsFile, - oci.WithHostResolvconf, + withDedupMounts("/etc/hosts", oci.WithHostHostsFile), + withDedupMounts("/etc/resolv.conf", oci.WithHostResolvconf), } // `/etc/hostname` does not exist on FreeBSD From 139022f83406231bf08bf8cbd401704a56338b55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Dec 2023 10:46:31 +0000 Subject: [PATCH 0262/1066] build(deps): bump github.com/containerd/containerd from 1.7.10 to 1.7.11 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.10 to 1.7.11. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.10...v1.7.11) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: Akihiro Suda --- go.mod | 4 +++- go.sum | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 741ee4b477b..3337446bc62 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.0.2 github.com/containerd/cgroups/v3 v3.0.2 github.com/containerd/console v1.0.3 - github.com/containerd/containerd v1.7.10 + github.com/containerd/containerd v1.7.11 github.com/containerd/continuity v0.4.3 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.9 @@ -76,6 +76,7 @@ require ( 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 + github.com/felixge/httpsnoop v1.0.3 // indirect github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -123,6 +124,7 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect 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 diff --git a/go.sum b/go.sum index 7a4feb5df5d..96dcd8aff53 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKk github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.10 h1:2nfZyT8BV0C3iKu/SsGxKVAf9dp5W7l9nA8JmWmDGuo= -github.com/containerd/containerd v1.7.10/go.mod h1:0/W44LWEYfSHoxBtsHIiNU/duEkgpMokemafHVCpq9Y= +github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw= +github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE= 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/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= @@ -103,6 +103,8 @@ github.com/fahedouch/go-logrotate v0.2.0 h1:UR9Fv8MDVfWwnkirmFHck+tRSWzqOwRjVRLM github.com/fahedouch/go-logrotate v0.2.0/go.mod h1:1RL/yr7LntS4zadAC6FT6yB/C1CQt3V6eHAZzymfwzE= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= @@ -317,6 +319,8 @@ go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwf go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= 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= From de9854575419e540a14905627bcadc4f48666e5f Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 11 Dec 2023 11:15:08 +0900 Subject: [PATCH 0263/1066] update containerd (1.7.11) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 24 ++++++++++++------------ Dockerfile | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5c3daba554c..2e6ac21683b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,11 +77,11 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.25 + containerd: v1.6.26 - ubuntu: 20.04 - containerd: v1.7.10 + containerd: v1.7.11 - ubuntu: 22.04 - containerd: v1.7.10 + containerd: v1.7.11 - ubuntu: 22.04 containerd: main env: @@ -113,7 +113,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 22.04 - containerd: v1.7.10 + containerd: v1.7.11 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -157,25 +157,25 @@ jobs: # ubuntu-22.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.25 + containerd: v1.6.26 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.10 + containerd: v1.7.11 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.10 + containerd: v1.7.11 target: test-integration-rootless - ubuntu: 22.04 containerd: main target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.6.25 + containerd: v1.6.26 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.10 + containerd: v1.7.11 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.10 + containerd: v1.7.11 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main @@ -267,7 +267,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: repository: containerd/containerd - ref: v1.7.10 + ref: v1.7.11 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -275,7 +275,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.10 + ctrdVersion: 1.7.11 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index 1f84b8102c9..8693cd33cdb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.10 +ARG CONTAINERD_VERSION=v1.7.11 ARG RUNC_VERSION=v1.1.10 ARG CNI_PLUGINS_VERSION=v1.4.0 From 24aa6e2766793f60e7a95bdf703bd958ee5bcf3b Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 12 Dec 2023 00:41:27 +0900 Subject: [PATCH 0264/1066] update BuildKit (0.12.4) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.3 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.4 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.3 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.4 diff --git a/Dockerfile b/Dockerfile index 8693cd33cdb..67992512f15 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.10 ARG CNI_PLUGINS_VERSION=v1.4.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.12.3 +ARG BUILDKIT_VERSION=v0.12.4 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.3 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.3 deleted file mode 100644 index 3e1148e4704..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.3 +++ /dev/null @@ -1,2 +0,0 @@ -01682ab9e8e7cada519396b5f7b72c964c0c30da0c2eb7ee46caf30622717fa1 buildkit-v0.12.3.linux-amd64.tar.gz -a6809c7983834f5a4dd3a92a421a9ff9a306e774ce2866d53636e8d5a3f2e82b buildkit-v0.12.3.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.4 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.4 new file mode 100644 index 00000000000..ff290731061 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.4 @@ -0,0 +1,2 @@ +75ffe406e4284b77af35447d829767cfa935eb7dd2ea2e3407223d6885bd8ebd buildkit-v0.12.4.linux-amd64.tar.gz +9166eeaff11721122b9398d6385c7b73d6e4df86797e537c16ac6b6d05eab899 buildkit-v0.12.4.linux-arm64.tar.gz From e538124a80eef757bda66c95075912c955594d54 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 22:34:25 +0000 Subject: [PATCH 0265/1066] build(deps): bump github.com/pelletier/go-toml/v2 from 2.1.0 to 2.1.1 Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.1.0 to 2.1.1. - [Release notes](https://github.com/pelletier/go-toml/releases) - [Changelog](https://github.com/pelletier/go-toml/blob/v2/.goreleaser.yaml) - [Commits](https://github.com/pelletier/go-toml/compare/v2.1.0...v2.1.1) --- updated-dependencies: - dependency-name: github.com/pelletier/go-toml/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3337446bc62..4e462e3420a 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc5 github.com/opencontainers/runtime-spec v1.1.0 - github.com/pelletier/go-toml/v2 v2.1.0 + github.com/pelletier/go-toml/v2 v2.1.1 github.com/rootless-containers/bypass4netns v0.3.0 github.com/rootless-containers/rootlesskit v1.1.1 github.com/spf13/cobra v1.8.0 diff --git a/go.sum b/go.sum index 96dcd8aff53..66b956b5968 100644 --- a/go.sum +++ b/go.sum @@ -245,8 +245,8 @@ github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaL github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= +github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= From ae004af58255463d28fbf938a5bedaf4b1324d4d Mon Sep 17 00:00:00 2001 From: Henry Wang Date: Wed, 13 Dec 2023 18:44:57 +0000 Subject: [PATCH 0266/1066] fix deadlinks in the notation doc Signed-off-by: Henry Wang --- docs/notation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/notation.md b/docs/notation.md index 34cd7682365..8e155c84e93 100644 --- a/docs/notation.md +++ b/docs/notation.md @@ -10,7 +10,7 @@ under the hood with make use of flags `--sign` while pushing the container image container image. * Ensure notation executable in your `$PATH`. -* You can install notation by following this page: https://notaryproject.dev/docs/installation/cli/ +* You can install notation by following this page: https://notaryproject.dev/docs/user-guides/installation/cli/ * Notation follows the RC of OCI spec v1.1.0. Follow the [instruction](https://notaryproject.dev/docs/quickstart/#create-an-oci-compatible-registry) to set up the local registry with the compliance for testing purpose. Prepare your environment: @@ -50,7 +50,7 @@ $ nerdctl push --sign=notation --notation-key-name test localhost:5000/my-test Verify the container image while pulling: -> REMINDER: Image won't be pulled if there are no matching signatures with the cert in the [trust policy](https://notaryproject.dev/docs/concepts/trust-store-trust-policy-specification/#trust-policy) in case you passed `--verify` flag. +> REMINDER: Image won't be pulled if there are no matching signatures with the cert in the [trust policy](https://github.com/notaryproject/specifications/blob/main/specs/trust-store-trust-policy.md#trust-policy) in case you passed `--verify` flag. ```shell # Create `trustpolicy.json` under $XDG_CONFIG_HOME/notation (XDG_CONFIG_HOME is ~/.config below) From 990d7eca8408ef04f7d9a2ef28577bbc5abb3fd9 Mon Sep 17 00:00:00 2001 From: Vishwas Siravara Date: Wed, 13 Dec 2023 13:42:40 -0800 Subject: [PATCH 0267/1066] implement persistent logging for contaiers running in foreground Signed-off-by: Vishwas Siravara --- .github/workflows/test.yml | 2 +- Dockerfile | 2 +- cmd/nerdctl/container_logs_test.go | 63 ++++++++ cmd/nerdctl/container_run.go | 2 +- go.mod | 8 +- go.sum | 11 ++ pkg/cioutil/containe_io_windows.go | 111 +++++++++++++++ pkg/cioutil/container_io.go | 221 +++++++++++++++++++++++++++++ pkg/cioutil/container_io_unix.go | 136 ++++++++++++++++++ pkg/containerutil/containerutil.go | 4 +- pkg/taskutil/taskutil.go | 9 +- 11 files changed, 559 insertions(+), 10 deletions(-) create mode 100644 pkg/cioutil/containe_io_windows.go create mode 100644 pkg/cioutil/container_io.go create mode 100644 pkg/cioutil/container_io_unix.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2e6ac21683b..a9a22221d01 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -70,7 +70,7 @@ jobs: test-integration: runs-on: "ubuntu-${{ matrix.ubuntu }}" - timeout-minutes: 40 + timeout-minutes: 60 strategy: fail-fast: false matrix: diff --git a/Dockerfile b/Dockerfile index 67992512f15..ccd1b23ff64 100644 --- a/Dockerfile +++ b/Dockerfile @@ -313,7 +313,7 @@ RUN curl -L -o nydus-static.tgz "https://github.com/dragonflyoss/image-service/r mv nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/bin/ && \ rm nydus-static.tgz CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/cmd/nerdctl/...", \ - "--", "-timeout=30m", "-args", "-test.kill-daemon"] + "--", "-timeout=60m", "-args", "-test.kill-daemon"] FROM test-integration AS test-integration-rootless # Install SSH for creating systemd user session. diff --git a/cmd/nerdctl/container_logs_test.go b/cmd/nerdctl/container_logs_test.go index 3f78ba8e2ce..66b0dc2ee81 100644 --- a/cmd/nerdctl/container_logs_test.go +++ b/cmd/nerdctl/container_logs_test.go @@ -18,6 +18,7 @@ package main import ( "fmt" + "runtime" "strings" "testing" "time" @@ -143,3 +144,65 @@ func TestLogsWithFailingContainer(t *testing.T) { base.Cmd("logs", "-f", containerName).AssertNoOut("baz") base.Cmd("rm", "-f", containerName).AssertOK() } + +func TestLogsWithForegroundContainers(t *testing.T) { + t.Parallel() + if runtime.GOOS == "windows" { + t.Skip("dual logging is not supported on Windows") + } + base := testutil.NewBase(t) + tid := testutil.Identifier(t) + + // unbuffer(1) emulates tty, which is required by `nerdctl run -t`. + // unbuffer(1) can be installed with `apt-get install expect`. + unbuffer := []string{"unbuffer"} + + testCases := []struct { + name string + flags []string + tty bool + }{ + { + name: "foreground", + flags: nil, + tty: false, + }, + { + name: "interactive", + flags: []string{"-i"}, + tty: false, + }, + { + name: "PTY", + flags: []string{"-t"}, + tty: true, + }, + { + name: "interactivePTY", + flags: []string{"-i", "-t"}, + tty: true, + }, + } + + for _, tc := range testCases { + tc := tc + func(t *testing.T) { + containerName := tid + "-" + tc.name + var cmdArgs []string + defer base.Cmd("rm", "-f", containerName).Run() + cmdArgs = append(cmdArgs, "run", "--name", containerName) + cmdArgs = append(cmdArgs, tc.flags...) + cmdArgs = append(cmdArgs, testutil.CommonImage, "sh", "-euxc", "echo foo; echo bar") + + if tc.tty { + base.CmdWithHelper(unbuffer, cmdArgs...).AssertOK() + } else { + base.Cmd(cmdArgs...).AssertOK() + } + + base.Cmd("logs", containerName).AssertOutContains("foo") + base.Cmd("logs", containerName).AssertOutContains("bar") + base.Cmd("logs", containerName).AssertNoOut("baz") + }(t) + } +} diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 44720eea3af..c1684e17e7a 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -373,7 +373,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, - con, logURI, createOpt.DetachKeys, detachC) + con, logURI, createOpt.DetachKeys, createOpt.GOptions.Namespace, detachC) if err != nil { return err } diff --git a/go.mod b/go.mod index 4e462e3420a..48fac826961 100644 --- a/go.mod +++ b/go.mod @@ -61,6 +61,12 @@ require ( gotest.tools/v3 v3.5.1 ) +require ( + github.com/containerd/go-runc v1.0.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // 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 @@ -68,7 +74,7 @@ require ( github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/cilium/ebpf v0.9.1 // indirect github.com/containerd/cgroups v1.1.0 // indirect - github.com/containerd/fifo v1.1.0 // indirect + github.com/containerd/fifo v1.1.0 github.com/containerd/ttrpc v1.2.2 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect github.com/containers/ocicrypt v1.1.9 // indirect diff --git a/go.sum b/go.sum index 66b956b5968..3a08c7f75e3 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,7 @@ github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaD github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw= @@ -45,6 +46,8 @@ github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9 github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC2XV0= github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= +github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= 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= @@ -159,6 +162,11 @@ github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBx 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/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= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= @@ -239,6 +247,7 @@ github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/ github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk= github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= +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= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= @@ -264,6 +273,7 @@ github.com/rootless-containers/bypass4netns v0.3.0/go.mod h1:IXHPjkQlJRygNBCN0hS github.com/rootless-containers/rootlesskit v1.1.1 h1:F5psKWoWY9/VjZ3ifVcaosjvFZJOagX85U22M0/EQZE= github.com/rootless-containers/rootlesskit v1.1.1/go.mod h1:UD5GoA3dqKCJrnvnhVgQQnweMF2qZnf9KLw8EewcMZI= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -379,6 +389,7 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/pkg/cioutil/containe_io_windows.go b/pkg/cioutil/containe_io_windows.go new file mode 100644 index 00000000000..ac1c09625bf --- /dev/null +++ b/pkg/cioutil/containe_io_windows.go @@ -0,0 +1,111 @@ +//go:build windows + +/* + 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 cioutil + +import ( + "fmt" + "io" + "os/exec" + + "github.com/Microsoft/go-winio" + "github.com/containerd/containerd/cio" + "github.com/containerd/log" +) + +// copyIO is from https://github.com/containerd/containerd/blob/148d21b1ae0718b75718a09ecb307bb874270f59/cio/io_windows.go#L44 +func copyIO(_ *exec.Cmd, fifos *cio.FIFOSet, ioset *cio.Streams) (_ *ncio, retErr error) { + ncios := &ncio{cmd: nil, config: fifos.Config} + + defer func() { + if retErr != nil { + _ = ncios.Close() + } + }() + + if fifos.Stdin != "" { + l, err := winio.ListenPipe(fifos.Stdin, nil) + if err != nil { + return nil, fmt.Errorf("failed to create stdin pipe %s: %w", fifos.Stdin, err) + } + ncios.closers = append(ncios.closers, l) + + go func() { + c, err := l.Accept() + if err != nil { + log.L.WithError(err).Errorf("failed to accept stdin connection on %s", fifos.Stdin) + return + } + + p := bufPool.Get().(*[]byte) + defer bufPool.Put(p) + + io.CopyBuffer(c, ioset.Stdin, *p) + c.Close() + l.Close() + }() + } + + if fifos.Stdout != "" { + l, err := winio.ListenPipe(fifos.Stdout, nil) + if err != nil { + return nil, fmt.Errorf("failed to create stdout pipe %s: %w", fifos.Stdout, err) + } + ncios.closers = append(ncios.closers, l) + + go func() { + c, err := l.Accept() + if err != nil { + log.L.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Stdout) + return + } + + p := bufPool.Get().(*[]byte) + defer bufPool.Put(p) + + io.CopyBuffer(ioset.Stdout, c, *p) + c.Close() + l.Close() + }() + } + + if fifos.Stderr != "" { + l, err := winio.ListenPipe(fifos.Stderr, nil) + if err != nil { + return nil, fmt.Errorf("failed to create stderr pipe %s: %w", fifos.Stderr, err) + } + ncios.closers = append(ncios.closers, l) + + go func() { + c, err := l.Accept() + if err != nil { + log.L.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Stderr) + return + } + + p := bufPool.Get().(*[]byte) + defer bufPool.Put(p) + + io.CopyBuffer(ioset.Stderr, c, *p) + c.Close() + l.Close() + }() + } + + return ncios, nil +} diff --git a/pkg/cioutil/container_io.go b/pkg/cioutil/container_io.go new file mode 100644 index 00000000000..24fb89186ba --- /dev/null +++ b/pkg/cioutil/container_io.go @@ -0,0 +1,221 @@ +/* + 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 cioutil + +import ( + "context" + "errors" + "fmt" + "io" + "net/url" + "os" + "os/exec" + "runtime" + "sync" + "syscall" + "time" + + "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/defaults" + "github.com/containerd/containerd/pkg/process" +) + +const binaryIOProcTermTimeout = 12 * time.Second // Give logger process 10 seconds for cleanup + +// ncio is a basic container IO implementation. +type ncio struct { + cmd *exec.Cmd + config cio.Config + wg *sync.WaitGroup + closers []io.Closer + cancel context.CancelFunc +} + +var bufPool = sync.Pool{ + New: func() interface{} { + buffer := make([]byte, 32<<10) + return &buffer + }, +} + +func (c *ncio) Config() cio.Config { + return c.config +} + +func (c *ncio) Wait() { + if c.wg != nil { + c.wg.Wait() + } +} + +func (c *ncio) Close() error { + + var lastErr error + + if c.cmd != nil && c.cmd.Process != nil { + + // Send SIGTERM first, so logger process has a chance to flush and exit properly + if err := c.cmd.Process.Signal(syscall.SIGTERM); err != nil { + lastErr = fmt.Errorf("failed to send SIGTERM: %w", err) + + if err := c.cmd.Process.Kill(); err != nil { + lastErr = errors.Join(lastErr, fmt.Errorf("failed to kill process after faulty SIGTERM: %w", err)) + } + + } + + done := make(chan error, 1) + go func() { + done <- c.cmd.Wait() + }() + + select { + case err := <-done: + return err + case <-time.After(binaryIOProcTermTimeout): + + err := c.cmd.Process.Kill() + if err != nil { + lastErr = fmt.Errorf("failed to kill shim logger process: %w", err) + } + + } + } + + for _, closer := range c.closers { + if closer == nil { + continue + } + if err := closer.Close(); err != nil { + lastErr = err + } + } + return lastErr +} + +func (c *ncio) Cancel() { + if c.cancel != nil { + c.cancel() + } +} + +func NewContainerIO(namespace string, logURI string, tty bool, stdin io.Reader, stdout, stderr io.Writer) cio.Creator { + return func(id string) (_ cio.IO, err error) { + var ( + cmd *exec.Cmd + closers []func() error + streams = &cio.Streams{ + Terminal: tty, + } + ) + + defer func() { + if err == nil { + return + } + result := []error{err} + for _, fn := range closers { + result = append(result, fn()) + } + err = errors.Join(result...) + }() + + if stdin != nil { + streams.Stdin = stdin + } + + var stdoutWriters []io.Writer + if stdout != nil { + stdoutWriters = append(stdoutWriters, stdout) + } + + var stderrWriters []io.Writer + if stderr != nil { + stderrWriters = append(stderrWriters, stderr) + } + + if runtime.GOOS != "windows" { + // starting logging binary logic is from https://github.com/containerd/containerd/blob/194a1fdd2cde35bc019ef138f30485e27fe0913e/cmd/containerd-shim-runc-v2/process/io.go#L247 + stdoutr, stdoutw, err := os.Pipe() + if err != nil { + return nil, err + } + closers = append(closers, stdoutr.Close, stdoutw.Close) + + stderrr, stderrw, err := os.Pipe() + if err != nil { + return nil, err + } + closers = append(closers, stderrr.Close, stderrw.Close) + + r, w, err := os.Pipe() + if err != nil { + return nil, err + } + closers = append(closers, r.Close, w.Close) + + u, err := url.Parse(logURI) + if err != nil { + return nil, err + } + cmd = process.NewBinaryCmd(u, id, namespace) + cmd.ExtraFiles = append(cmd.ExtraFiles, stdoutr, stderrr, w) + + if err := cmd.Start(); err != nil { + return nil, fmt.Errorf("failed to start binary process with cmdArgs %v: %w", cmd.Args, err) + } + + closers = append(closers, func() error { return cmd.Process.Kill() }) + + // close our side of the pipe after start + if err := w.Close(); err != nil { + return nil, fmt.Errorf("failed to close write pipe after start: %w", err) + } + + // wait for the logging binary to be ready + b := make([]byte, 1) + if _, err := r.Read(b); err != nil && err != io.EOF { + return nil, fmt.Errorf("failed to read from logging binary: %w", err) + } + + stdoutWriters = append(stdoutWriters, stdoutw) + stderrWriters = append(stderrWriters, stderrw) + } + + streams.Stdout = io.MultiWriter(stdoutWriters...) + streams.Stderr = io.MultiWriter(stderrWriters...) + + if streams.FIFODir == "" { + streams.FIFODir = defaults.DefaultFIFODir + } + fifos, err := cio.NewFIFOSetInDir(streams.FIFODir, id, streams.Terminal) + if err != nil { + return nil, err + } + + if streams.Stdin == nil { + fifos.Stdin = "" + } + if streams.Stdout == nil { + fifos.Stdout = "" + } + if streams.Stderr == nil { + fifos.Stderr = "" + } + return copyIO(cmd, fifos, streams) + } +} diff --git a/pkg/cioutil/container_io_unix.go b/pkg/cioutil/container_io_unix.go new file mode 100644 index 00000000000..fd0632c3781 --- /dev/null +++ b/pkg/cioutil/container_io_unix.go @@ -0,0 +1,136 @@ +//go:build !windows + +/* + 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 cioutil + +import ( + "context" + "fmt" + "io" + "os/exec" + "sync" + "syscall" + + "github.com/containerd/containerd/cio" + "github.com/containerd/fifo" +) + +type pipes struct { + Stdin io.WriteCloser + Stdout io.ReadCloser + Stderr io.ReadCloser +} + +func (p *pipes) closers() []io.Closer { + return []io.Closer{p.Stdin, p.Stdout, p.Stderr} +} + +// copyIO is from https://github.com/containerd/containerd/blob/148d21b1ae0718b75718a09ecb307bb874270f59/cio/io_unix.go#L55 +func copyIO(cmd *exec.Cmd, fifos *cio.FIFOSet, ioset *cio.Streams) (*ncio, error) { + var ctx, cancel = context.WithCancel(context.Background()) + pipes, err := openFifos(ctx, fifos) + if err != nil { + cancel() + return nil, err + } + + if fifos.Stdin != "" { + go func() { + p := bufPool.Get().(*[]byte) + defer bufPool.Put(p) + + io.CopyBuffer(pipes.Stdin, ioset.Stdin, *p) + pipes.Stdin.Close() + }() + } + + var wg = &sync.WaitGroup{} + if fifos.Stdout != "" { + wg.Add(1) + go func() { + p := bufPool.Get().(*[]byte) + defer bufPool.Put(p) + + io.CopyBuffer(ioset.Stdout, pipes.Stdout, *p) + pipes.Stdout.Close() + wg.Done() + }() + } + + if !fifos.Terminal && fifos.Stderr != "" { + wg.Add(1) + go func() { + p := bufPool.Get().(*[]byte) + defer bufPool.Put(p) + + io.CopyBuffer(ioset.Stderr, pipes.Stderr, *p) + pipes.Stderr.Close() + wg.Done() + }() + } + + return &ncio{ + cmd: cmd, + config: fifos.Config, + wg: wg, + closers: append(pipes.closers(), fifos), + cancel: func() { + cancel() + for _, c := range pipes.closers() { + if c != nil { + c.Close() + } + } + }, + }, nil +} + +func openFifos(ctx context.Context, fifos *cio.FIFOSet) (f pipes, retErr error) { + defer func() { + if retErr != nil { + fifos.Close() + } + }() + + if fifos.Stdin != "" { + if f.Stdin, retErr = fifo.OpenFifo(ctx, fifos.Stdin, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); retErr != nil { + return f, fmt.Errorf("failed to open stdin fifo: %w", retErr) + } + defer func() { + if retErr != nil && f.Stdin != nil { + f.Stdin.Close() + } + }() + } + if fifos.Stdout != "" { + if f.Stdout, retErr = fifo.OpenFifo(ctx, fifos.Stdout, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); retErr != nil { + return f, fmt.Errorf("failed to open stdout fifo: %w", retErr) + } + defer func() { + if retErr != nil && f.Stdout != nil { + f.Stdout.Close() + } + }() + } + if !fifos.Terminal && fifos.Stderr != "" { + if f.Stderr, retErr = fifo.OpenFifo(ctx, fifos.Stderr, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); retErr != nil { + return f, fmt.Errorf("failed to open stderr fifo: %w", retErr) + } + } + return f, nil +} diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 79d328b3bf0..23d03545177 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -243,7 +243,7 @@ func Start(ctx context.Context, container containerd.Container, flagA bool, clie } logURI := lab[labels.LogURI] - + namespace := lab[labels.Namespace] cStatus := formatter.ContainerStatus(ctx, container) if cStatus == "Up" { log.G(ctx).Warnf("container %s is already running", container.ID()) @@ -266,7 +266,7 @@ 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, detachC) + task, err := taskutil.NewTask(ctx, client, container, flagA, false, flagT, true, con, logURI, detachKeys, namespace, detachC) if err != nil { return err } diff --git a/pkg/taskutil/taskutil.go b/pkg/taskutil/taskutil.go index 62e622f716f..022da8c7df2 100644 --- a/pkg/taskutil/taskutil.go +++ b/pkg/taskutil/taskutil.go @@ -31,6 +31,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" "github.com/containerd/log" + "github.com/containerd/nerdctl/pkg/cioutil" "github.com/containerd/nerdctl/pkg/consoleutil" "github.com/containerd/nerdctl/pkg/infoutil" "golang.org/x/term" @@ -38,7 +39,7 @@ 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 string, detachC chan<- struct{}) (containerd.Task, error) { + flagA, 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 { @@ -93,6 +94,7 @@ func NewTask(ctx context.Context, client *containerd.Client, container container args[0]: args[1], }) } else if flagT && !flagD { + if con == nil { return nil, errors.New("got nil con with flagT=true") } @@ -108,9 +110,8 @@ func NewTask(ctx context.Context, client *containerd.Client, container container return nil, err } } - ioCreator = cio.NewCreator(cio.WithStreams(in, os.Stdout, nil), cio.WithTerminal) + ioCreator = cioutil.NewContainerIO(namespace, logURI, true, in, os.Stdout, os.Stderr) } else if flagD && logURI != "" { - // TODO: support logURI for `nerdctl run -it` u, err := url.Parse(logURI) if err != nil { return nil, err @@ -136,7 +137,7 @@ func NewTask(ctx context.Context, client *containerd.Client, container container } in = stdinC } - ioCreator = cio.NewCreator(cio.WithStreams(in, os.Stdout, os.Stderr)) + ioCreator = cioutil.NewContainerIO(namespace, logURI, false, in, os.Stdout, os.Stderr) } t, err := container.NewTask(ctx, ioCreator) if err != nil { From b6436017ed6c318c2b28c24270e6c26479ef41eb Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 14 Dec 2023 14:34:21 +0000 Subject: [PATCH 0268/1066] fix etchosts in host network Signed-off-by: Kay Yan --- .../container_run_network_linux_test.go | 28 +++++++++++++++ .../container_network_manager.go | 36 +++++++++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index e8b3d375b9d..62d6ad978cc 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -493,6 +493,34 @@ func TestRunContainerWithMACAddress(t *testing.T) { } } +func TestHostsFileMounts(t *testing.T) { + base := testutil.NewBase(t) + + base.Cmd("run", "--rm", testutil.CommonImage, + "sh", "-euxc", "echo >> /etc/hosts").AssertOK() + base.Cmd("run", "--rm", "--network", "host", testutil.CommonImage, + "sh", "-euxc", "echo >> /etc/hosts").AssertOK() + base.Cmd("run", "--rm", "-v", "/etc/hosts:/etc/hosts:ro", "--network", "host", testutil.CommonImage, + "sh", "-euxc", "echo >> /etc/hosts").AssertFail() + // add a line into /etc/hosts and remove it. + base.Cmd("run", "--rm", "-v", "/etc/hosts:/etc/hosts", "--network", "host", testutil.CommonImage, + "sh", "-euxc", "echo >> /etc/hosts").AssertOK() + base.Cmd("run", "--rm", "-v", "/etc/hosts:/etc/hosts", "--network", "host", testutil.CommonImage, + "sh", "-euxc", "head -n -1 /etc/hosts > temp && cat temp > /etc/hosts").AssertOK() + + base.Cmd("run", "--rm", testutil.CommonImage, + "sh", "-euxc", "echo >> /etc/resolv.conf").AssertOK() + base.Cmd("run", "--rm", "--network", "host", testutil.CommonImage, + "sh", "-euxc", "echo >> /etc/resolv.conf").AssertOK() + base.Cmd("run", "--rm", "-v", "/etc/resolv.conf:/etc/resolv.conf:ro", "--network", "host", testutil.CommonImage, + "sh", "-euxc", "echo >> /etc/resolv.conf").AssertFail() + // add a line into /etc/resolv.conf and remove it. + base.Cmd("run", "--rm", "-v", "/etc/resolv.conf:/etc/resolv.conf", "--network", "host", testutil.CommonImage, + "sh", "-euxc", "echo >> /etc/resolv.conf").AssertOK() + base.Cmd("run", "--rm", "-v", "/etc/resolv.conf:/etc/resolv.conf", "--network", "host", testutil.CommonImage, + "sh", "-euxc", "head -n -1 /etc/resolv.conf > temp && cat temp > /etc/resolv.conf").AssertOK() +} + func TestRunContainerWithStaticIP6(t *testing.T) { if rootlessutil.IsRootless() { t.Skip("Static IP6 assignment is not supported rootless mode yet.") diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index edba4de6c8c..6b29661c8a9 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -398,15 +398,47 @@ func withDedupMounts(mountPath string, defaultSpec oci.SpecOpts) oci.SpecOpts { } } +func copyFileContent(src string, dst string) error { + data, err := os.ReadFile(src) + if err != nil { + return err + } + err = os.WriteFile(dst, data, 0644) + if err != nil { + return err + } + return nil +} + // ContainerNetworkingOpts Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent // the network specs which need to be applied to the container with the given ID. func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containerID string) ([]oci.SpecOpts, []containerd.NewContainerOpts, error) { cOpts := []containerd.NewContainerOpts{} + + dataStore, err := clientutil.DataStore(m.globalOptions.DataRoot, m.globalOptions.Address) + if err != nil { + return nil, nil, err + } + + stateDir, err := ContainerStateDirPath(m.globalOptions.Namespace, dataStore, containerID) + if err != nil { + return nil, nil, err + } + + resolvConfPath := filepath.Join(stateDir, "resolv.conf") + copyFileContent("/etc/resolv.conf", resolvConfPath) + + etcHostsPath, err := hostsstore.AllocHostsFile(dataStore, m.globalOptions.Namespace, containerID) + if err != nil { + return nil, nil, err + } + copyFileContent("/etc/hosts", etcHostsPath) + specs := []oci.SpecOpts{ oci.WithHostNamespace(specs.NetworkNamespace), - withDedupMounts("/etc/hosts", oci.WithHostHostsFile), - withDedupMounts("/etc/resolv.conf", oci.WithHostResolvconf), + withDedupMounts("/etc/hosts", withCustomHosts(etcHostsPath)), + withDedupMounts("/etc/resolv.conf", withCustomResolvConf(resolvConfPath)), } // `/etc/hostname` does not exist on FreeBSD From 255716ea8f1a9fa70bea069396ac51f039448c34 Mon Sep 17 00:00:00 2001 From: Hiroshi Miura Date: Sun, 17 Dec 2023 09:07:06 +0900 Subject: [PATCH 0269/1066] docs: Fix typo in command-reference.md Signed-off-by: Hiroshi Miura --- docs/command-reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/command-reference.md b/docs/command-reference.md index a67d9fa5e98..ba535cacf14 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1170,7 +1170,7 @@ Flags: ### :nerd_face: :blue_square: nerdctl namespace update -Udapte labels for a namespace. +Update labels for a namespace. Usage: `nerdctl namespace update NAMESPACE` From ef00a6d6be5dbabfbc693d3c85dc1a02d64d094e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 22:06:42 +0000 Subject: [PATCH 0270/1066] build(deps): bump docker/metadata-action from 5.3.0 to 5.4.0 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.3.0 to 5.4.0. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/v5.3.0...v5.4.0) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 991c99893a2..96da665d27c 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -52,7 +52,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v5.3.0 + uses: docker/metadata-action@v5.4.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} From ffd76b5ba59985a3db5e4f06f7fcf8044ee644a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 22:44:19 +0000 Subject: [PATCH 0271/1066] build(deps): bump golang.org/x/crypto from 0.16.0 to 0.17.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.16.0 to 0.17.0. - [Commits](https://github.com/golang/crypto/compare/v0.16.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4e462e3420a..a961bccf109 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 - golang.org/x/crypto v0.16.0 + golang.org/x/crypto v0.17.0 golang.org/x/net v0.19.0 golang.org/x/sync v0.5.0 golang.org/x/sys v0.15.0 diff --git a/go.sum b/go.sum index 66b956b5968..b578b7abab2 100644 --- a/go.sum +++ b/go.sum @@ -332,8 +332,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= From ea3a4e0201d71a9b5997ff7974021e9648e290b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 22:44:49 +0000 Subject: [PATCH 0272/1066] build(deps): bump github.com/awslabs/soci-snapshotter Bumps [github.com/awslabs/soci-snapshotter](https://github.com/awslabs/soci-snapshotter) from 0.4.0 to 0.4.1. - [Release notes](https://github.com/awslabs/soci-snapshotter/releases) - [Changelog](https://github.com/awslabs/soci-snapshotter/blob/main/RELEASES.md) - [Commits](https://github.com/awslabs/soci-snapshotter/compare/v0.4.0...v0.4.1) --- updated-dependencies: - dependency-name: github.com/awslabs/soci-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4e462e3420a..9b7f1a211d3 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ 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/awslabs/soci-snapshotter v0.4.0 + 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/cgroups/v3 v3.0.2 diff --git a/go.sum b/go.sum index 66b956b5968..207b0592078 100644 --- a/go.sum +++ b/go.sum @@ -13,8 +13,8 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc 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/awslabs/soci-snapshotter v0.4.0 h1:dA9lOYbzSUaYMahB8qXQZTVXUszhc0w8rwjRs6EPd24= -github.com/awslabs/soci-snapshotter v0.4.0/go.mod h1:+ST8F4E/b6b6pnFBJKprdvzkxyXODMs0FC2TmclkgJc= +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= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= From c2d71273e742f8d1f1f261362789c8b7d39026c0 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 19 Dec 2023 11:23:15 +0000 Subject: [PATCH 0273/1066] fix groupadd in compose Signed-off-by: Kay Yan --- pkg/composer/serviceparser/serviceparser.go | 4 ++++ pkg/composer/serviceparser/serviceparser_test.go | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index cf8c9a2d05c..b914437b250 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -673,6 +673,10 @@ func newContainer(project *types.Project, parsed *Service, i int) (*Container, e c.RunArgs = append(c.RunArgs, "--user="+svc.User) } + for _, v := range svc.GroupAdd { + c.RunArgs = append(c.RunArgs, fmt.Sprintf("--group-add=%s", v)) + } + for _, v := range svc.Volumes { vStr, mkdir, err := serviceVolumeConfigToFlagV(v, project) if err != nil { diff --git a/pkg/composer/serviceparser/serviceparser_test.go b/pkg/composer/serviceparser/serviceparser_test.go index 860edf77280..72d96b1ab09 100644 --- a/pkg/composer/serviceparser/serviceparser_test.go +++ b/pkg/composer/serviceparser/serviceparser_test.go @@ -117,6 +117,9 @@ services: options: max-size: "5K" max-file: "2" + user: 1001:1001 + group_add: + - "1001" db: image: mariadb:10.5 @@ -174,6 +177,8 @@ volumes: assert.Assert(t, in(wp1.RunArgs, "--add-host=test.com:172.19.1.1")) assert.Assert(t, in(wp1.RunArgs, "--add-host=test2.com:172.19.1.2")) assert.Assert(t, in(wp1.RunArgs, "--shm-size=1073741824")) + assert.Assert(t, in(wp1.RunArgs, "--user=1001:1001")) + assert.Assert(t, in(wp1.RunArgs, "--group-add=1001")) dbSvc, err := project.GetService("db") assert.NilError(t, err) From 392daca120391017486fcb79c0321962d5c48f66 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 19 Dec 2023 18:39:27 +0900 Subject: [PATCH 0274/1066] go.mod: clean up Follow-up to PR 2683 Signed-off-by: Akihiro Suda --- go.mod | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index b33f62f9608..a2bc937201b 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.7.11 github.com/containerd/continuity v0.4.3 + github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.9 github.com/containerd/log v0.1.0 @@ -61,12 +62,6 @@ require ( gotest.tools/v3 v3.5.1 ) -require ( - github.com/containerd/go-runc v1.0.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // 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 @@ -74,7 +69,7 @@ require ( github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/cilium/ebpf v0.9.1 // indirect github.com/containerd/cgroups v1.1.0 // indirect - github.com/containerd/fifo v1.1.0 + github.com/containerd/go-runc v1.0.0 // indirect github.com/containerd/ttrpc v1.2.2 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect github.com/containers/ocicrypt v1.1.9 // indirect @@ -92,6 +87,8 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.3.1 // 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 github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.17.4 From e4bf8b99b8b875fbcc1fdc3dabda12127821acc3 Mon Sep 17 00:00:00 2001 From: TinaMor Date: Mon, 6 Nov 2023 13:21:42 +0300 Subject: [PATCH 0275/1066] Fix #2199 to allow users to bind a named pipe on Windows. - Allow users to bind a named pipe on Windows - Refactor windows volume spec split - Split mount code for Linux and Windows environments - Adds a check in create.go#L298 to log a warning only when there is an error Signed-off-by: Christine Murimi --- cmd/nerdctl/container_run_mount_linux_test.go | 18 +- .../container_run_mount_windows_test.go | 214 +++++++++++++ go.mod | 1 + go.sum | 2 + pkg/cmd/container/create.go | 4 +- pkg/mountutil/mountutil.go | 242 ++++++++++---- pkg/mountutil/mountutil_freebsd.go | 10 +- pkg/mountutil/mountutil_linux.go | 14 +- pkg/mountutil/mountutil_linux_test.go | 171 ++++++++++ pkg/mountutil/mountutil_other.go | 66 ++++ pkg/mountutil/mountutil_windows.go | 197 +++++++++++- pkg/mountutil/mountutil_windows_test.go | 295 ++++++++++++++++++ pkg/mountutil/mountutilmock/os.mock.go | 56 ++++ .../mountutilmock/volumestore.mock.go | 121 +++++++ 14 files changed, 1328 insertions(+), 83 deletions(-) create mode 100644 cmd/nerdctl/container_run_mount_windows_test.go create mode 100644 pkg/mountutil/mountutil_other.go create mode 100644 pkg/mountutil/mountutilmock/os.mock.go create mode 100644 pkg/mountutil/mountutilmock/volumestore.mock.go diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container_run_mount_linux_test.go index bed8f0936b1..19793c97340 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container_run_mount_linux_test.go @@ -85,8 +85,22 @@ func TestRunVolume(t *testing.T) { func TestRunAnonymousVolume(t *testing.T) { t.Parallel() base := testutil.NewBase(t) - base.Cmd("run", "--rm", "-v", "/foo", testutil.AlpineImage, - "mountpoint", "-q", "/foo").AssertOK() + base.Cmd("run", "--rm", "-v", "/foo", testutil.AlpineImage).AssertOK() + base.Cmd("run", "--rm", "-v", "TestVolume2:/foo", testutil.AlpineImage).AssertOK() + base.Cmd("run", "--rm", "-v", "TestVolume", testutil.AlpineImage).AssertOK() + + // Destination must be an absolute path not named volume + base.Cmd("run", "--rm", "-v", "TestVolume2:TestVolumes", testutil.AlpineImage).AssertFail() +} + +func TestRunVolumeRelativePath(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + base.Cmd("run", "--rm", "-v", "./foo:/mnt/foo", testutil.AlpineImage).AssertOK() + base.Cmd("run", "--rm", "-v", "./foo", testutil.AlpineImage).AssertOK() + + // Destination must be an absolute path not a relative path + base.Cmd("run", "--rm", "-v", "./foo:./foo", testutil.AlpineImage).AssertFail() } func TestRunAnonymousVolumeWithTypeMountFlag(t *testing.T) { diff --git a/cmd/nerdctl/container_run_mount_windows_test.go b/cmd/nerdctl/container_run_mount_windows_test.go new file mode 100644 index 00000000000..a560151b74c --- /dev/null +++ b/cmd/nerdctl/container_run_mount_windows_test.go @@ -0,0 +1,214 @@ +/* + 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" + "os" + "testing" + + "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/pkg/testutil" + "gotest.tools/v3/assert" +) + +func TestRunMountVolume(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + tID := testutil.Identifier(t) + rwDir, err := os.MkdirTemp(t.TempDir(), "rw") + if err != nil { + t.Fatal(err) + } + roDir, err := os.MkdirTemp(t.TempDir(), "ro") + if err != nil { + t.Fatal(err) + } + rwVolName := tID + "-rw" + roVolName := tID + "-ro" + for _, v := range []string{rwVolName, roVolName} { + defer base.Cmd("volume", "rm", "-f", v).Run() + base.Cmd("volume", "create", v).AssertOK() + } + + containerName := tID + defer base.Cmd("rm", "-f", containerName).AssertOK() + base.Cmd("run", + "-d", + "--name", containerName, + "-v", fmt.Sprintf("%s:C:/mnt1", rwDir), + "-v", fmt.Sprintf("%s:C:/mnt2:ro", roDir), + "-v", fmt.Sprintf("%s:C:/mnt3", rwVolName), + "-v", fmt.Sprintf("%s:C:/mnt4:ro", roVolName), + testutil.CommonImage, + "ping localhost -t", + ).AssertOK() + + base.Cmd("exec", containerName, "cmd", "/c", "echo -n str1 > C:/mnt1/file1").AssertOK() + base.Cmd("exec", containerName, "cmd", "/c", "echo -n str2 > C:/mnt2/file2").AssertFail() + base.Cmd("exec", containerName, "cmd", "/c", "echo -n str3 > C:/mnt3/file3").AssertOK() + base.Cmd("exec", containerName, "cmd", "/c", "echo -n str4 > C:/mnt4/file4").AssertFail() + base.Cmd("rm", "-f", containerName).AssertOK() + + base.Cmd("run", + "--rm", + "-v", fmt.Sprintf("%s:C:/mnt1", rwDir), + "-v", fmt.Sprintf("%s:C:/mnt3", rwVolName), + testutil.CommonImage, + "cat", "C:/mnt1/file1", "C:/mnt3/file3", + ).AssertOutContainsAll("str1", "str3") + base.Cmd("run", + "--rm", + "-v", fmt.Sprintf("%s:C:/mnt3/mnt1", rwDir), + "-v", fmt.Sprintf("%s:C:/mnt3", rwVolName), + testutil.CommonImage, + "cat", "C:/mnt3/mnt1/file1", "C:/mnt3/file3", + ).AssertOutContainsAll("str1", "str3") +} + +func TestRunMountVolumeInspect(t *testing.T) { + base := testutil.NewBase(t) + testContainer := testutil.Identifier(t) + testVolume := testutil.Identifier(t) + + defer base.Cmd("volume", "rm", "-f", testVolume).Run() + base.Cmd("volume", "create", testVolume).AssertOK() + inspectVolume := base.InspectVolume(testVolume) + namedVolumeSource := inspectVolume.Mountpoint + + base.Cmd( + "run", "-d", "--name", testContainer, + "-v", "C:/mnt1", + "-v", "C:/mnt2:C:/mnt2", + "-v", "\\\\.\\pipe\\containerd-containerd:\\\\.\\pipe\\containerd-containerd", + "-v", fmt.Sprintf("%s:C:/mnt3", testVolume), + testutil.CommonImage, + ).AssertOK() + + inspect := base.InspectContainer(testContainer) + // convert array to map to get by key of Destination + actual := make(map[string]dockercompat.MountPoint) + for i := range inspect.Mounts { + actual[inspect.Mounts[i].Destination] = inspect.Mounts[i] + } + + expected := []struct { + dest string + mountPoint dockercompat.MountPoint + }{ + // anonymous volume + { + dest: "C:\\mnt1", + mountPoint: dockercompat.MountPoint{ + Type: "volume", + Source: "", // source of anonymous volume is a generated path, so here will not check it. + Destination: "C:\\mnt1", + }, + }, + + // bind + { + dest: "C:\\mnt2", + mountPoint: dockercompat.MountPoint{ + Type: "bind", + Source: "C:\\mnt2", + Destination: "C:\\mnt2", + }, + }, + + // named pipe + { + dest: "\\\\.\\pipe\\containerd-containerd", + mountPoint: dockercompat.MountPoint{ + Type: "npipe", + Source: "\\\\.\\pipe\\containerd-containerd", + Destination: "\\\\.\\pipe\\containerd-containerd", + }, + }, + + // named volume + { + dest: "C:\\mnt3", + mountPoint: dockercompat.MountPoint{ + Type: "volume", + Name: testVolume, + Source: namedVolumeSource, + Destination: "C:\\mnt3", + }, + }, + } + + for i := range expected { + testCase := expected[i] + t.Logf("test volume[dest=%q]", testCase.dest) + + mountPoint, ok := actual[testCase.dest] + assert.Assert(base.T, ok) + + assert.Equal(base.T, testCase.mountPoint.Type, mountPoint.Type) + assert.Equal(base.T, testCase.mountPoint.Destination, mountPoint.Destination) + + if testCase.mountPoint.Source == "" { + // for anonymous volumes, we want to make sure that the source is not the same as the destination + assert.Assert(base.T, mountPoint.Source != testCase.mountPoint.Destination) + } else { + assert.Equal(base.T, testCase.mountPoint.Source, mountPoint.Source) + } + + if testCase.mountPoint.Name != "" { + assert.Equal(base.T, testCase.mountPoint.Name, mountPoint.Name) + } + } +} + +func TestRunMountAnonymousVolume(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + base.Cmd("run", "--rm", "-v", "TestVolume:C:/mnt", testutil.CommonImage).AssertOK() + + // For docker-campatibility, Unrecognised volume spec: invalid volume specification: 'TestVolume' + base.Cmd("run", "--rm", "-v", "TestVolume", testutil.CommonImage).AssertFail() + + // Destination must be an absolute path not named volume + base.Cmd("run", "--rm", "-v", "TestVolume2:TestVolumes", testutil.CommonImage).AssertFail() +} + +func TestRunMountRelativePath(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + base.Cmd("run", "--rm", "-v", "./mnt:C:/mnt1", testutil.CommonImage, "cmd").AssertOK() + + // Destination cannot be a relative path + base.Cmd("run", "--rm", "-v", "./mnt", testutil.CommonImage).AssertFail() + base.Cmd("run", "--rm", "-v", "./mnt:./mnt1", testutil.CommonImage, "cmd").AssertFail() +} + +func TestRunMountNamedPipeVolume(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + base.Cmd("run", "--rm", "-v", `\\.\pipe\containerd-containerd`, testutil.CommonImage).AssertFail() +} + +func TestRunMountVolumeSpec(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + base.Cmd("run", "--rm", "-v", `InvalidPathC:\TestVolume:C:\Mount`, testutil.CommonImage).AssertFail() + base.Cmd("run", "--rm", "-v", `C:\TestVolume:C:\Mount:ro,rw:boot`, testutil.CommonImage).AssertFail() + + // If -v is an empty string, it will be ignored + base.Cmd("run", "--rm", "-v", "", testutil.CommonImage).AssertOK() +} diff --git a/go.mod b/go.mod index a2bc937201b..a04b6691e10 100644 --- a/go.mod +++ b/go.mod @@ -52,6 +52,7 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 + go.uber.org/mock v0.3.0 golang.org/x/crypto v0.17.0 golang.org/x/net v0.19.0 golang.org/x/sync v0.5.0 diff --git a/go.sum b/go.sum index 7cde17cec67..78cfdf6c33a 100644 --- a/go.sum +++ b/go.sum @@ -338,6 +338,8 @@ go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319 go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= +go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index c39d036c628..43f5e6828d4 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -295,7 +295,9 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa // perform network setup/teardown in the main nerdctl executable. if containerErr == nil && runtime.GOOS == "windows" { netSetupErr = netManager.SetupNetworking(ctx, id) - log.G(ctx).WithError(netSetupErr).Warnf("networking setup error has occurred") + if netSetupErr != nil { + log.G(ctx).WithError(netSetupErr).Warnf("networking setup error has occurred") + } } if containerErr != nil || netSetupErr != nil { diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index bb46743ab02..bb938d073a8 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -25,6 +25,7 @@ import ( "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/log" @@ -35,9 +36,11 @@ import ( ) const ( - Bind = "bind" - Volume = "volume" - Tmpfs = "tmpfs" + Bind = "bind" + Volume = "volume" + Tmpfs = "tmpfs" + Npipe = "npipe" + pathSeparator = string(os.PathSeparator) ) type Processed struct { @@ -49,90 +52,84 @@ type Processed struct { Opts []oci.SpecOpts } +type volumeSpec struct { + Type string + Name string + Source string + AnonymousVolume string +} + func ProcessFlagV(s string, volStore volumestore.VolumeStore, createDir bool) (*Processed, error) { var ( - res Processed + res *Processed + volSpec volumeSpec src, dst string options []string ) - s = strings.TrimLeft(s, ":") - split := strings.Split(s, ":") + split, err := splitVolumeSpec(s) + if err != nil { + return nil, fmt.Errorf("failed to split volume mount specification: %v", err) + } + switch len(split) { case 1: - dst = s - res.AnonymousVolume = idgen.GenerateID() - log.L.Debugf("creating anonymous volume %q, for %q", res.AnonymousVolume, s) - anonVol, err := volStore.Create(res.AnonymousVolume, []string{}) + // validate destination + dst = split[0] + if _, err := validateAnonymousVolumeDestination(dst); err != nil { + return nil, err + } + + // create anonymous volume + volSpec, err = handleAnonymousVolumes(dst, volStore) if err != nil { - return nil, fmt.Errorf("failed to create an anonymous volume %q: %w", res.AnonymousVolume, err) + return nil, err } - src = anonVol.Mountpoint - res.Type = Volume - case 2, 3: - res.Type = Bind - src, dst = split[0], split[1] - if !strings.Contains(src, "/") { - // assume src is a volume name - res.Name = src - vol, err := volStore.Get(src, false) - if err != nil { - if errors.Is(err, errdefs.ErrNotFound) { - vol, err = volStore.Create(src, nil) - if err != nil { - return nil, fmt.Errorf("failed to create volume %q: %w", src, err) - } - } else { - return nil, fmt.Errorf("failed to get volume %q: %w", src, err) - } - } - // src is now full path - src = vol.Mountpoint - res.Type = Volume + + src = volSpec.Source + res = &Processed{ + Type: volSpec.Type, + AnonymousVolume: volSpec.AnonymousVolume, } - if !filepath.IsAbs(src) { - log.L.Warnf("expected an absolute path, got a relative path %q (allowed for nerdctl, but disallowed for Docker, so unrecommended)", src) - var err error - src, err = filepath.Abs(src) - if err != nil { - return nil, fmt.Errorf("failed to get the absolute path of %q: %w", src, err) - } + case 2, 3: + // Vaildate destination + dst = split[1] + dst = strings.TrimLeft(dst, ":") + if _, err := isValidPath(dst); err != nil { + return nil, err } - if createDir { - if _, err := os.Stat(src); err != nil { - if !os.IsNotExist(err) { - return nil, fmt.Errorf("failed to stat %q: %w", src, err) - } - if err := os.MkdirAll(src, 0o755); err != nil { - return nil, fmt.Errorf("failed to mkdir %q: %w", src, err) - } - } + + // Get volume spec + src = split[0] + volSpec, err = handleVolumeToMount(src, dst, volStore, createDir) + if err != nil { + return nil, err } - if !filepath.IsAbs(dst) { - return nil, fmt.Errorf("expected an absolute path, got %q", dst) + src = volSpec.Source + res = &Processed{ + Type: volSpec.Type, + Name: volSpec.Name, + AnonymousVolume: volSpec.AnonymousVolume, } - rawOpts := "" + + // Parse volume options if len(split) == 3 { - rawOpts = split[2] - } - res.Mode = rawOpts + res.Mode = split[2] - // always call parseVolumeOptions for bind mount to allow the parser to add some default options - var err error - var specOpts []oci.SpecOpts - options, specOpts, err = parseVolumeOptions(res.Type, src, rawOpts) - if err != nil { - return nil, fmt.Errorf("failed to parse volume options (%q, %q, %q): %w", res.Type, src, rawOpts, err) + rawOpts := res.Mode + + options, res.Opts, err = getVolumeOptions(src, res.Type, rawOpts) + if err != nil { + return nil, err + } } - res.Opts = append(res.Opts, specOpts...) default: return nil, fmt.Errorf("failed to parse %q", s) } - fstype := "nullfs" + fstype := DefaultMountType if runtime.GOOS != "freebsd" { - fstype = "none" found := false for _, opt := range options { switch opt { @@ -150,8 +147,8 @@ func ProcessFlagV(s string, volStore volumestore.VolumeStore, createDir bool) (* } res.Mount = specs.Mount{ Type: fstype, - Source: src, - Destination: dst, + Source: cleanMount(src), + Destination: cleanMount(dst), Options: options, } if userns.RunningInUserNS() { @@ -161,5 +158,116 @@ func ProcessFlagV(s string, volStore volumestore.VolumeStore, createDir bool) (* } res.Mount.Options = strutil.DedupeStrSlice(append(res.Mount.Options, unpriv...)) } - return &res, nil + + return res, nil +} + +func handleBindMounts(source string, createDir bool) (volumeSpec, error) { + var res volumeSpec + res.Type = Bind + res.Source = source + + // Handle relative paths + if !filepath.IsAbs(source) { + log.L.Warnf("expected an absolute path, got a relative path %q (allowed for nerdctl, but disallowed for Docker, so unrecommended)", source) + absPath, err := filepath.Abs(source) + if err != nil { + return res, fmt.Errorf("failed to get the absolute path of %q: %w", source, err) + } + res.Source = absPath + } + + // Create dir if it does not exist + if err := createDirOnHost(source, createDir); err != nil { + return res, err + } + + return res, nil +} + +func handleAnonymousVolumes(s string, volStore volumestore.VolumeStore) (volumeSpec, error) { + var res volumeSpec + res.AnonymousVolume = idgen.GenerateID() + + log.L.Debugf("creating anonymous volume %q, for %q", res.AnonymousVolume, s) + anonVol, err := volStore.Create(res.AnonymousVolume, []string{}) + if err != nil { + return res, fmt.Errorf("failed to create an anonymous volume %q: %w", res.AnonymousVolume, err) + } + + res.Type = Volume + res.Source = anonVol.Mountpoint + return res, nil +} + +func handleNamedVolumes(source string, volStore volumestore.VolumeStore) (volumeSpec, error) { + var res volumeSpec + res.Name = source + vol, err := volStore.Get(res.Name, false) + if err != nil { + if errors.Is(err, errdefs.ErrNotFound) { + vol, err = volStore.Create(res.Name, nil) + if err != nil { + return res, fmt.Errorf("failed to create volume %q: %w", res.Name, err) + } + } else { + return res, fmt.Errorf("failed to get volume %q: %w", res.Name, err) + } + } + // src is now an absolute path + res.Type = Volume + res.Source = vol.Mountpoint + + return res, nil +} + +func getVolumeOptions(src string, vType string, rawOpts string) ([]string, []oci.SpecOpts, error) { + // always call parseVolumeOptions for bind mount to allow the parser to add some default options + var err error + var specOpts []oci.SpecOpts + options, specOpts, err := parseVolumeOptions(vType, src, rawOpts) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse volume options (%q, %q, %q): %w", vType, src, rawOpts, err) + } + + specOpts = append(specOpts, specOpts...) + return options, specOpts, nil +} + +func createDirOnHost(src string, createDir bool) error { + _, err := os.Stat(src) + if err == nil { + return nil + } + + if !createDir { + + /** + * In pkg\mountutil\mountutil_linux.go:432, we disallow creating directories on host if not found + * The user gets an error if the directory does not exist: + * error mounting "/foo" to rootfs at "/foo": stat /foo: no such file or directory: unknown. + * We log this error to give the user a hint that they may need to create the directory on the host. + * https://docs.docker.com/storage/bind-mounts/ + */ + if os.IsNotExist(err) { + log.L.Warnf("mount source %q does not exist. Please make sure to create the directory on the host.", src) + return nil + } + return fmt.Errorf("failed to stat %q: %w", src, err) + } + + if !os.IsNotExist(err) { + return fmt.Errorf("failed to stat %q: %w", src, err) + } + if err := os.MkdirAll(src, 0o755); err != nil { + return fmt.Errorf("failed to mkdir %q: %w", src, err) + } + return nil +} + +func isNamedVolume(s string) bool { + err := identifiers.Validate(s) + + // If the volume name is invalid, we assume it is a path + return err == nil } diff --git a/pkg/mountutil/mountutil_freebsd.go b/pkg/mountutil/mountutil_freebsd.go index 85613c32622..637bdfebc2b 100644 --- a/pkg/mountutil/mountutil_freebsd.go +++ b/pkg/mountutil/mountutil_freebsd.go @@ -26,14 +26,18 @@ import ( "github.com/containerd/nerdctl/pkg/mountutil/volumestore" ) +const ( + DefaultMountType = "nullfs" + + // FreeBSD doesn't support bind mounts. + DefaultPropagationMode = "" +) + func UnprivilegedMountFlags(path string) ([]string, error) { m := []string{} return m, nil } -// FreeBSD doesn't support bind mounts. -const DefaultPropagationMode = "" - // parseVolumeOptions parses specified optsRaw with using information of // the volume type and the src directory when necessary. func parseVolumeOptions(vType, src, optsRaw string) ([]string, []oci.SpecOpts, error) { diff --git a/pkg/mountutil/mountutil_linux.go b/pkg/mountutil/mountutil_linux.go index 2a3f145c2f0..ef46bdd6de1 100644 --- a/pkg/mountutil/mountutil_linux.go +++ b/pkg/mountutil/mountutil_linux.go @@ -44,6 +44,15 @@ import ( NOTICE: https://github.com/moby/moby/blob/v20.10.5/NOTICE */ +const ( + DefaultMountType = "none" + + // DefaultPropagationMode is the default propagation of mounts + // where user doesn't specify mount propagation explicitly. + // See also: https://github.com/moby/moby/blob/v20.10.7/volume/mounts/linux_parser.go#L145 + DefaultPropagationMode = "rprivate" +) + // UnprivilegedMountFlags is from https://github.com/moby/moby/blob/v20.10.5/daemon/oci_linux.go#L420-L450 // // Get the set of mount flags that are set on the mount that contains the given @@ -78,11 +87,6 @@ func UnprivilegedMountFlags(path string) ([]string, error) { return flags, nil } -// DefaultPropagationMode is the default propagation of mounts -// where user doesn't specify mount propagation explicitly. -// See also: https://github.com/moby/moby/blob/v20.10.7/volume/mounts/linux_parser.go#L145 -const DefaultPropagationMode = "rprivate" - // parseVolumeOptions parses specified optsRaw with using information of // the volume type and the src directory when necessary. func parseVolumeOptions(vType, src, optsRaw string) ([]string, []oci.SpecOpts, error) { diff --git a/pkg/mountutil/mountutil_linux_test.go b/pkg/mountutil/mountutil_linux_test.go index 4ecf1f3f458..c707837ea29 100644 --- a/pkg/mountutil/mountutil_linux_test.go +++ b/pkg/mountutil/mountutil_linux_test.go @@ -23,7 +23,10 @@ import ( "github.com/containerd/containerd/mount" "github.com/containerd/containerd/oci" + "github.com/containerd/nerdctl/pkg/inspecttypes/native" + mocks "github.com/containerd/nerdctl/pkg/mountutil/mountutilmock" "github.com/opencontainers/runtime-spec/specs-go" + "go.uber.org/mock/gomock" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) @@ -206,3 +209,171 @@ func TestProcessTmpfs(t *testing.T) { assert.DeepEqual(t, expected, x.Mount.Options) } } + +func TestProcessFlagV(t *testing.T) { + tests := []struct { + rawSpec string + wants *Processed + err string + }{ + // Bind volumes: absolute path + { + rawSpec: "/mnt/foo:/mnt/foo:ro", + wants: &Processed{ + Type: "bind", + Mount: specs.Mount{ + Type: "none", + Destination: `/mnt/foo`, + Source: `/mnt/foo`, + Options: []string{"ro", "rprivate", "rbind"}, + }}, + }, + // Bind volumes: relative path + { + rawSpec: `./TestVolume/Path:/mnt/foo`, + wants: &Processed{ + Type: "bind", + Mount: specs.Mount{ + Type: "none", + Source: "", // will not check source of relative paths + Destination: `/mnt/foo`, + Options: []string{"rbind"}, + }}, + }, + // Named volumes + { + rawSpec: `TestVolume:/mnt/foo`, + wants: &Processed{ + Type: "volume", + Name: "TestVolume", + Mount: specs.Mount{ + Type: "none", + Source: "", // source of anonymous volume is a generated path, so here will not check it. + Destination: `/mnt/foo`, + Options: []string{"rbind"}, + }}, + }, + { + rawSpec: `/mnt/foo:TestVolume`, + err: "expected an absolute path, got \"TestVolume\"", + }, + { + rawSpec: `/mnt/foo:./foo`, + err: "expected an absolute path, got \"./foo\"", + }, + } + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockVolumeStore := mocks.NewMockVolumeStore(ctrl) + mockVolumeStore. + EXPECT(). + Get(gomock.Any(), false). + Return(&native.Volume{Name: "test_volume", Mountpoint: "/test/volume", Size: 1024}, nil). + AnyTimes() + mockVolumeStore. + EXPECT(). + Create(gomock.Any(), nil). + Return(&native.Volume{Name: "test_volume", Mountpoint: "/test/volume"}, nil).AnyTimes() + + mockOs := mocks.NewMockOs(ctrl) + mockOs.EXPECT().Stat(gomock.Any()).Return(nil, nil).AnyTimes() + + for _, tt := range tests { + t.Run(tt.rawSpec, func(t *testing.T) { + processedVolSpec, err := ProcessFlagV(tt.rawSpec, mockVolumeStore, false) + if err != nil { + assert.Error(t, err, tt.err) + return + } + + assert.Equal(t, processedVolSpec.Type, tt.wants.Type) + assert.Equal(t, processedVolSpec.Mount.Type, tt.wants.Mount.Type) + assert.Equal(t, processedVolSpec.Mount.Destination, tt.wants.Mount.Destination) + assert.DeepEqual(t, processedVolSpec.Mount.Options, tt.wants.Mount.Options) + + if tt.wants.Name != "" { + assert.Equal(t, processedVolSpec.Name, tt.wants.Name) + } + if tt.wants.Mount.Source != "" { + assert.Equal(t, processedVolSpec.Mount.Source, tt.wants.Mount.Source) + } + }) + } +} + +func TestProcessFlagVAnonymousVolumes(t *testing.T) { + tests := []struct { + rawSpec string + wants *Processed + err string + }{ + { + rawSpec: `/mnt/foo`, + wants: &Processed{ + Type: "volume", + Mount: specs.Mount{ + Type: "none", + Source: "", // source of anonymous volume is a generated path, so here will not check it. + Destination: `/mnt/foo`, + }}, + }, + { + rawSpec: `./TestVolume/Path`, + wants: &Processed{ + Type: "volume", + Mount: specs.Mount{ + Type: "none", + Source: "", // source of anonymous volume is a generated path, so here will not check it. + Destination: `TestVolume/Path`, // cleanpath() removes the leading "./". Since we are mocking the os.Stat() call, this is fine. + }}, + }, + { + rawSpec: "TestVolume", + wants: &Processed{ + Type: "volume", + Mount: specs.Mount{ + Type: "none", + Source: "", // source of anonymous volume is a generated path, so here will not check it. + Destination: "TestVolume", + }}, + }, + { + rawSpec: `/mnt/foo::ro`, + err: "expected an absolute path, got \"\"", + }, + } + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockVolumeStore := mocks.NewMockVolumeStore(ctrl) + mockVolumeStore. + EXPECT(). + Create(gomock.Any(), []string{}). + Return(&native.Volume{Name: "test_volume", Mountpoint: "/test/volume"}, nil). + AnyTimes() + + for _, tt := range tests { + t.Run(tt.rawSpec, func(t *testing.T) { + processedVolSpec, err := ProcessFlagV(tt.rawSpec, mockVolumeStore, true) + if err != nil { + assert.ErrorContains(t, err, tt.err) + return + } + + assert.Equal(t, processedVolSpec.Type, tt.wants.Type) + assert.Assert(t, processedVolSpec.AnonymousVolume != "") + assert.Equal(t, processedVolSpec.Mount.Type, tt.wants.Mount.Type) + assert.Equal(t, processedVolSpec.Mount.Destination, tt.wants.Mount.Destination) + + if tt.wants.Mount.Source != "" { + assert.Equal(t, processedVolSpec.Mount.Source, tt.wants.Mount.Source) + } + + // for anonymous volumes, we want to make sure that the source is not the same as the destination + assert.Assert(t, processedVolSpec.Mount.Source != processedVolSpec.Mount.Destination) + }) + } +} diff --git a/pkg/mountutil/mountutil_other.go b/pkg/mountutil/mountutil_other.go new file mode 100644 index 00000000000..184926a1354 --- /dev/null +++ b/pkg/mountutil/mountutil_other.go @@ -0,0 +1,66 @@ +//go:build !windows + +/* + 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 mountutil + +import ( + "fmt" + "path/filepath" + "strings" + + "github.com/containerd/nerdctl/pkg/mountutil/volumestore" +) + +func splitVolumeSpec(s string) ([]string, error) { + s = strings.TrimLeft(s, ":") + split := strings.Split(s, ":") + return split, nil +} + +func handleVolumeToMount(source string, dst string, volStore volumestore.VolumeStore, createDir bool) (volumeSpec, error) { + switch { + // Handle named volumes + case isNamedVolume(source): + return handleNamedVolumes(source, volStore) + + // Handle bind volumes (file paths) + default: + return handleBindMounts(source, createDir) + } +} + +func cleanMount(p string) string { + return filepath.Clean(p) +} + +func isValidPath(s string) (bool, error) { + if filepath.IsAbs(s) { + return true, nil + } + + return false, fmt.Errorf("expected an absolute path, got %q", s) +} + +/* +For docker compatibility on non-Windows platforms: +Docker allows anonymous named volumes, relative paths, and absolute paths +to be mounted into a container. +*/ +func validateAnonymousVolumeDestination(s string) (bool, error) { + return true, nil +} diff --git a/pkg/mountutil/mountutil_windows.go b/pkg/mountutil/mountutil_windows.go index 5875198f2ed..35faafb72ee 100644 --- a/pkg/mountutil/mountutil_windows.go +++ b/pkg/mountutil/mountutil_windows.go @@ -1,3 +1,5 @@ +//go:build windows + /* Copyright The containerd Authors. @@ -14,10 +16,19 @@ limitations under the License. */ +/* + Portions from https://github.com/moby/moby/blob/f5c7673ff8fcbd359f75fb644b1365ca9d20f176/volume/mounts/windows_parser.go#L26 + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/master/NOTICE +*/ + package mountutil import ( "fmt" + "path/filepath" + "regexp" "strings" "github.com/containerd/containerd/errdefs" @@ -26,16 +37,22 @@ import ( "github.com/containerd/nerdctl/pkg/mountutil/volumestore" ) +const ( + // Defaults to an empty string + // https://github.com/microsoft/hcsshim/blob/5c75f29c1f5cb4d3498d66228637d07477bcb6a1/internal/hcsoci/resources_wcow.go#L140 + DefaultMountType = "" + + // DefaultPropagationMode is the default propagation of mounts + // where user doesn't specify mount propagation explicitly. + // See also: https://github.com/moby/moby/blob/v20.10.7/volume/mounts/windows_parser.go#L440-L442 + DefaultPropagationMode = "" +) + func UnprivilegedMountFlags(path string) ([]string, error) { m := []string{} return m, nil } -// DefaultPropagationMode is the default propagation of mounts -// where user doesn't specify mount propagation explicitly. -// See also: https://github.com/moby/moby/blob/v20.10.7/volume/mounts/windows_parser.go#L440-L442 -const DefaultPropagationMode = "" - // parseVolumeOptions parses specified optsRaw with using information of // the volume type and the src directory when necessary. func parseVolumeOptions(vType, src, optsRaw string) ([]string, []oci.SpecOpts, error) { @@ -68,3 +85,173 @@ func ProcessFlagTmpfs(s string) (*Processed, error) { func ProcessFlagMount(s string, volStore volumestore.VolumeStore) (*Processed, error) { return nil, errdefs.ErrNotImplemented } + +func handleVolumeToMount(source string, dst string, volStore volumestore.VolumeStore, createDir bool) (volumeSpec, error) { + // Validate source and destination types + if _, err := (validateNamedPipeSpec(source, dst)); err != nil { + return volumeSpec{}, err + } + + switch { + // Handle named volumes + case isNamedVolume(source): + return handleNamedVolumes(source, volStore) + + // Handle named pipes + case isNamedPipe(source): + return handleNpipeToMount(source) + + // Handle bind volumes (file paths) + default: + return handleBindMounts(source, createDir) + } +} + +func handleNpipeToMount(source string) (volumeSpec, error) { + res := volumeSpec{ + Type: Npipe, + Source: source, + } + return res, nil +} + +func splitVolumeSpec(raw string) ([]string, error) { + raw = strings.TrimSpace(raw) + raw = strings.TrimLeft(raw, ":") + if raw == "" { + return nil, fmt.Errorf("invalid empty volume specification") + } + + const ( + // Root drive or relative paths starting with . + rxHostDir = `(?:[a-zA-Z]:|\.)[\/\\]` + + // https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats + // Windows UNC paths and DOS device paths (and namde pipes) + rxUNC = `(?:\\{2}[a-zA-Z0-9_\-\.\?]+\\{1}[^\\*?"|\r\n]+)\\` + rxName = `[^\/\\:*?"<>|\r\n]+` + + rxSource = `((?P((` + rxHostDir + `|` + rxUNC + `)` + `(` + rxName + `[\/\\]?)+` + `|` + rxName + `)):)?` + rxDestination = `(?P(` + rxHostDir + `|` + rxUNC + `)` + `(` + rxName + `[\/\\]?)+` + `|` + rxName + `)` + rxMode = `(?::(?P(?i)\w+(,\w+)?))` + + rxWindows = `^` + rxSource + rxDestination + `(?:` + rxMode + `)?$` + ) + + compiledRegex, err := regexp.Compile(rxWindows) + if err != nil { + return nil, fmt.Errorf("error compiling regex: %s", err) + } + return splitRawSpec(raw, compiledRegex) +} + +func isNamedPipe(s string) bool { + pattern := `^\\{2}.\\pipe\\[^\/\\:*?"<>|\r\n]+$` + matches, err := regexp.MatchString(pattern, s) + if err != nil { + log.L.Errorf("Invalid pattern %s", pattern) + } + + return matches +} + +func cleanMount(p string) string { + if isNamedPipe(p) { + return p + } + return filepath.Clean(p) +} + +func isValidPath(s string) (bool, error) { + if isNamedPipe(s) || filepath.IsAbs(s) { + return true, nil + } + + return false, fmt.Errorf("expected an absolute path or a named pipe, got %q", s) +} + +/* +For docker compatibility on Windows platforms: +Docker only allows for absolute paths as anonymous volumes. +Docker does not allows anonymous named volumes or anonymous named piped +to be mounted into a container. +*/ +func validateAnonymousVolumeDestination(s string) (bool, error) { + if isNamedPipe(s) || isNamedVolume(s) { + return false, fmt.Errorf("invalid volume specification: %q. only directories can be mapped as anonymous volumes", s) + } + + if filepath.IsAbs(s) { + return true, nil + } + + return false, fmt.Errorf("expected an absolute path, got %q", s) +} + +func splitRawSpec(raw string, splitRegexp *regexp.Regexp) ([]string, error) { + match := splitRegexp.FindStringSubmatch(raw) + if len(match) == 0 { + return nil, fmt.Errorf("invalid volume specification: '%s'", raw) + } + + var split []string + matchgroups := make(map[string]string) + // Pull out the sub expressions from the named capture groups + for i, name := range splitRegexp.SubexpNames() { + matchgroups[name] = match[i] + } + if source, exists := matchgroups["source"]; exists { + if source == "." { + return nil, fmt.Errorf("invalid volume specification: %q", raw) + } + + if source != "" { + split = append(split, source) + } + } + + mode, modExists := matchgroups["mode"] + + if destination, exists := matchgroups["destination"]; exists { + if destination == "." { + return nil, fmt.Errorf("invalid volume specification: %q", raw) + } + + // If mode exists and destination is empty, set destination to an empty string + // source::ro + if destination != "" || modExists && mode != "" { + split = append(split, destination) + } + } + + if mode, exists := matchgroups["mode"]; exists { + if mode != "" { + split = append(split, mode) + } + } + return split, nil +} + +// Function to parse the source type +func parseSourceType(source string) string { + switch { + case isNamedVolume(source): + return Volume + case isNamedPipe(source): + return Npipe + // Add more cases for different source types as needed + default: + return Bind + } +} + +func validateNamedPipeSpec(source string, dst string) (bool, error) { + // Validate source and destination types + sourceType := parseSourceType(source) + destType := parseSourceType(dst) + + if (destType == Npipe && sourceType != Npipe) || (sourceType == Npipe && destType != Npipe) { + return false, fmt.Errorf("invalid volume specification. named pipes can only be mapped to named pipes") + } + return true, nil +} diff --git a/pkg/mountutil/mountutil_windows_test.go b/pkg/mountutil/mountutil_windows_test.go index d016273ac3d..ed69dfdf96b 100644 --- a/pkg/mountutil/mountutil_windows_test.go +++ b/pkg/mountutil/mountutil_windows_test.go @@ -17,9 +17,14 @@ package mountutil import ( + "fmt" "strings" "testing" + "github.com/containerd/nerdctl/pkg/inspecttypes/native" + mocks "github.com/containerd/nerdctl/pkg/mountutil/mountutilmock" + "github.com/opencontainers/runtime-spec/specs-go" + "go.uber.org/mock/gomock" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) @@ -78,3 +83,293 @@ func TestParseVolumeOptions(t *testing.T) { }) } } + +func TestSplitRawSpec(t *testing.T) { + tests := []struct { + rawSpec string + wants []string + }{ + // Absolute paths + { + rawSpec: `C:\TestVolume\Path:C:\TestVolume\Path:ro`, + wants: []string{`C:\TestVolume\Path`, `C:\TestVolume\Path`, "ro"}, + }, + { + rawSpec: `C:\TestVolume\Path:C:\TestVolume\Path:ro,rw`, + wants: []string{`C:\TestVolume\Path`, `C:\TestVolume\Path`, "ro,rw"}, + }, + { + rawSpec: `C:\TestVolume\Path:C:\TestVolume\Path:ro,undefined`, + wants: []string{`C:\TestVolume\Path`, `C:\TestVolume\Path`, "ro,undefined"}, + }, + { + rawSpec: `C:\TestVolume\Path:C:\TestVolume\Path`, + wants: []string{`C:\TestVolume\Path`, `C:\TestVolume\Path`}, + }, + { + rawSpec: `C:\TestVolume\Path`, + wants: []string{`C:\TestVolume\Path`}, + }, + { + rawSpec: `C:\Test Volume\Path`, // space in path + wants: []string{`C:\Test Volume\Path`}, + }, + + // Relative paths + { + rawSpec: `.\ContainerVolumes:C:\TestVolumes`, + wants: []string{`.\ContainerVolumes`, `C:\TestVolumes`}, + }, + { + rawSpec: `.\ContainerVolumes:.\ContainerVolumes`, + wants: []string{`.\ContainerVolumes`, `.\ContainerVolumes`}, + }, + + // Anonymous volumes + { + rawSpec: `.\ContainerVolumes`, + wants: []string{`.\ContainerVolumes`}, + }, + { + rawSpec: `TestVolume`, + wants: []string{`TestVolume`}, + }, + { + rawSpec: `:TestVolume`, + wants: []string{`TestVolume`}, + }, + + // UNC paths + { + rawSpec: `\\?\UNC\server\share\path:.\ContainerVolumesto`, + wants: []string{`\\?\UNC\server\share\path`, `.\ContainerVolumesto`}, + }, + { + rawSpec: `\\.\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test`, + wants: []string{`\\.\Volume{b75e2c83-0000-0000-0000-602f00000000}\Test`}, + }, + + // Named pipes + { + rawSpec: `\\.\pipe\containerd-containerd`, + wants: []string{`\\.\pipe\containerd-containerd`}, + }, + { + rawSpec: `\\.\pipe\containerd-containerd:\\.\pipe\containerd-containerd`, + wants: []string{`\\.\pipe\containerd-containerd`, `\\.\pipe\containerd-containerd`}, + }, + } + for _, tt := range tests { + t.Run(tt.rawSpec, func(t *testing.T) { + actual, err := splitVolumeSpec(tt.rawSpec) + if err != nil { + t.Errorf("failed to split raw spec %q: %v", tt.rawSpec, err) + return + + } + assert.Check(t, is.DeepEqual(tt.wants, actual)) + }) + } +} + +func TestSplitRawSpecInvalid(t *testing.T) { + tests := []string{ + "", // Empty string + " ", // Empty string + `.`, // Invalid relative path + `./`, // Invalid relative path + `../`, // Invalid relative path + `C:\`, // Cannot mount root directory + `~\TestVolume`, // Invalid relative path + `..\TestVolume`, // Invalid relative path + `ABC:\ContainerVolumes:C:\TestVolumes`, // Invalid drive letter + `UNC\server\share\path`, // Invalid path + } + + for _, path := range tests { + t.Run(path, func(t *testing.T) { + _, err := splitVolumeSpec(path) + if strings.TrimSpace(path) == "" { + assert.Error(t, err, "invalid empty volume specification") + return + } + if path == "." { + assert.Error(t, err, "invalid volume specification: \".\"") + return + } + assert.Error(t, err, fmt.Sprintf("invalid volume specification: '%s'", path)) + }) + } +} + +func TestProcessFlagV(t *testing.T) { + tests := []struct { + rawSpec string + wants *Processed + err string + }{ + // Bind volumes: absolute path + { + rawSpec: "C:/TestVolume/Path:C:/TestVolume/Path:ro", + wants: &Processed{ + Type: "bind", + Mount: specs.Mount{ + Type: "", + Destination: `C:\TestVolume\Path`, + Source: `C:\TestVolume\Path`, + Options: []string{"ro", "rbind"}, + }}, + }, + // Bind volumes: relative path + { + rawSpec: `.\TestVolume\Path:C:\TestVolume\Path`, + wants: &Processed{ + Type: "bind", + Mount: specs.Mount{ + Type: "", + Source: "", // will not check source of relative paths + Destination: `C:\TestVolume\Path`, + Options: []string{"rbind"}, + }}, + }, + // Named volumes + { + rawSpec: `TestVolume:C:\TestVolume\Path`, + wants: &Processed{ + Type: "volume", + Name: "TestVolume", + Mount: specs.Mount{ + Type: "", + Source: "", // source of anonymous volume is a generated path, so here will not check it. + Destination: `C:\TestVolume\Path`, + Options: []string{"rbind"}, + }}, + }, + // Named pipes + { + rawSpec: `\\.\pipe\containerd-containerd:\\.\pipe\containerd-containerd`, + wants: &Processed{ + Type: "npipe", + Mount: specs.Mount{ + Type: "", + Source: `\\.\pipe\containerd-containerd`, + Destination: `\\.\pipe\containerd-containerd`, + Options: []string{"rbind"}, + }}, + }, + { + rawSpec: `\\.\pipe\containerd-containerd:C:\TestVolume\Path`, + err: "invalid volume specification. named pipes can only be mapped to named pipes", + }, + { + rawSpec: `C:\TestVolume\Path:TestVolume`, + err: "expected an absolute path or a named pipe, got \"TestVolume\"", + }, + } + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockVolumeStore := mocks.NewMockVolumeStore(ctrl) + mockVolumeStore. + EXPECT(). + Get(gomock.Any(), false). + Return(&native.Volume{Name: "test_volume", Mountpoint: "C:\\test\\directory", Size: 1024}, nil). + AnyTimes() + mockVolumeStore. + EXPECT(). + Create(gomock.Any(), nil). + Return(&native.Volume{Name: "test_volume", Mountpoint: "C:\\test\\directory"}, nil).AnyTimes() + + mockOs := mocks.NewMockOs(ctrl) + mockOs.EXPECT().Stat(gomock.Any()).Return(nil, nil).AnyTimes() + + for _, tt := range tests { + t.Run(tt.rawSpec, func(t *testing.T) { + processedVolSpec, err := ProcessFlagV(tt.rawSpec, mockVolumeStore, true) + if err != nil { + assert.Error(t, err, tt.err) + return + } + + assert.Equal(t, processedVolSpec.Type, tt.wants.Type) + assert.Equal(t, processedVolSpec.Mount.Type, tt.wants.Mount.Type) + assert.Equal(t, processedVolSpec.Mount.Destination, tt.wants.Mount.Destination) + assert.DeepEqual(t, processedVolSpec.Mount.Options, tt.wants.Mount.Options) + + if tt.wants.Name != "" { + assert.Equal(t, processedVolSpec.Name, tt.wants.Name) + } + if tt.wants.Mount.Source != "" { + assert.Equal(t, processedVolSpec.Mount.Source, tt.wants.Mount.Source) + } + }) + } +} + +func TestProcessFlagVAnonymousVolumes(t *testing.T) { + tests := []struct { + rawSpec string + wants *Processed + err string + }{ + { + rawSpec: `C:\TestVolume\Path`, + wants: &Processed{ + Type: "volume", + Mount: specs.Mount{ + Type: "", + Source: "", // source of anonymous volume is a generated path, so here will not check it. + Destination: `C:\TestVolume\Path`, + }}, + }, + { + rawSpec: `.\TestVolume\Path`, + err: "expected an absolute path", + }, + { + rawSpec: `TestVolume`, + err: "only directories can be mapped as anonymous volumes", + }, + { + rawSpec: `C:\TestVolume\Path::ro`, + err: "failed to split volume mount specification", + }, + { + rawSpec: `\\.\pipe\containerd-containerd`, + err: "only directories can be mapped as anonymous volumes", + }, + } + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockVolumeStore := mocks.NewMockVolumeStore(ctrl) + mockVolumeStore. + EXPECT(). + Create(gomock.Any(), []string{}). + Return(&native.Volume{Name: "test_volume", Mountpoint: "C:\\test\\directory"}, nil). + AnyTimes() + + for _, tt := range tests { + t.Run(tt.rawSpec, func(t *testing.T) { + processedVolSpec, err := ProcessFlagV(tt.rawSpec, mockVolumeStore, true) + if err != nil { + assert.ErrorContains(t, err, tt.err) + return + } + + assert.Equal(t, processedVolSpec.Type, tt.wants.Type) + assert.Assert(t, processedVolSpec.AnonymousVolume != "") + assert.Equal(t, processedVolSpec.Mount.Type, tt.wants.Mount.Type) + assert.Equal(t, processedVolSpec.Mount.Destination, tt.wants.Mount.Destination) + + if tt.wants.Mount.Source != "" { + assert.Equal(t, processedVolSpec.Mount.Source, tt.wants.Mount.Source) + } + + // for anonymous volumes, we want to make sure that the source is not the same as the destination + assert.Assert(t, processedVolSpec.Mount.Source != processedVolSpec.Mount.Destination) + }) + } +} diff --git a/pkg/mountutil/mountutilmock/os.mock.go b/pkg/mountutil/mountutilmock/os.mock.go new file mode 100644 index 00000000000..3cc1718e5bd --- /dev/null +++ b/pkg/mountutil/mountutilmock/os.mock.go @@ -0,0 +1,56 @@ +/* + 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 mountutilmock + +import ( + "os" + "reflect" + + "go.uber.org/mock/gomock" +) + +type MockOs struct { + ctrl *gomock.Controller + recorder *MockOsMockRecorder +} + +type MockOsMockRecorder struct { + mock *MockOs +} + +func NewMockOs(ctrl *gomock.Controller) *MockOs { + mock := &MockOs{ctrl: ctrl} + mock.recorder = &MockOsMockRecorder{mock} + return mock +} + +func (m *MockOs) EXPECT() *MockOsMockRecorder { + return m.recorder +} + +func (m *MockOs) Stat(name string) (os.FileInfo, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Stat", name) + ret0, _ := ret[0].(os.FileInfo) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +func (m *MockOsMockRecorder) Stat(name any) *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Stat", reflect.TypeOf((*MockOs)(nil).Stat), name) +} diff --git a/pkg/mountutil/mountutilmock/volumestore.mock.go b/pkg/mountutil/mountutilmock/volumestore.mock.go new file mode 100644 index 00000000000..427d6138b55 --- /dev/null +++ b/pkg/mountutil/mountutilmock/volumestore.mock.go @@ -0,0 +1,121 @@ +/* + 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 mountutilmock + +import ( + "reflect" + + "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "go.uber.org/mock/gomock" +) + +// MockVolumeStore is a mock of VolumeStore interface +type MockVolumeStore struct { + ctrl *gomock.Controller + recorder *MockVolumeStoreMockRecorder +} + +// MockVolumeStoreMockRecorder is the mock recorder for MockVolumeStore +type MockVolumeStoreMockRecorder struct { + mock *MockVolumeStore +} + +// NewMockVolumeStore creates a new mock instance +func NewMockVolumeStore(ctrl *gomock.Controller) *MockVolumeStore { + mock := &MockVolumeStore{ctrl: ctrl} + mock.recorder = &MockVolumeStoreMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockVolumeStore) EXPECT() *MockVolumeStoreMockRecorder { + return m.recorder +} + +// Create mocks the Create method of VolumeStore +func (m *MockVolumeStore) Create(name string, labels []string) (*native.Volume, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Create", name, labels) + ret0, _ := ret[0].(*native.Volume) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Create indicates an expected call of Create +func (m *MockVolumeStoreMockRecorder) Create(name any, labels any) *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Create", reflect.TypeOf((*MockVolumeStore)(nil).Create), name, labels) +} + +// Get mocks the Get method of VolumeStore +func (m *MockVolumeStore) Get(name string, size bool) (*native.Volume, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", name, size) + ret0, _ := ret[0].(*native.Volume) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get +func (m *MockVolumeStoreMockRecorder) Get(name any, size any) *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Get", reflect.TypeOf((*MockVolumeStore)(nil).Get), name, size) +} + +// List mocks the List method of VolumeStore +func (m *MockVolumeStore) List(size bool) (map[string]native.Volume, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "List", size) + ret0, _ := ret[0].(map[string]native.Volume) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// List indicates an expected call of List +func (m *MockVolumeStoreMockRecorder) List(size any) *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType(m.mock, "List", reflect.TypeOf((*MockVolumeStore)(nil).List), size) +} + +// Remove mocks the Remove method of VolumeStore +func (m *MockVolumeStore) Remove(names []string) ([]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Remove", names) + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Remove indicates an expected call of Remove +func (m *MockVolumeStoreMockRecorder) Remove(names any) *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Remove", reflect.TypeOf((*MockVolumeStore)(nil).Remove), names) +} + +// Dir mocks the Dir method of VolumeStore +func (m *MockVolumeStore) Dir() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Dir") + ret0, _ := ret[0].(string) + return ret0 +} + +// Dir indicates an expected call of Dir +func (m *MockVolumeStoreMockRecorder) Dir() *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Dir", reflect.TypeOf((*MockVolumeStore)(nil).Dir)) +} From 843d8600b8a4ca749aa05591bb6bf10193b30906 Mon Sep 17 00:00:00 2001 From: Vishwas Siravara Date: Tue, 19 Dec 2023 16:02:37 -0800 Subject: [PATCH 0276/1066] fix typo in filename Signed-off-by: Vishwas Siravara --- pkg/cioutil/{containe_io_windows.go => container_io_windows.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkg/cioutil/{containe_io_windows.go => container_io_windows.go} (100%) diff --git a/pkg/cioutil/containe_io_windows.go b/pkg/cioutil/container_io_windows.go similarity index 100% rename from pkg/cioutil/containe_io_windows.go rename to pkg/cioutil/container_io_windows.go From 970fed9f96c6470533485ff0d24230f1fa9b37ed Mon Sep 17 00:00:00 2001 From: David Son Date: Wed, 20 Dec 2023 19:56:51 +0000 Subject: [PATCH 0277/1066] Remove "soci image rpull" from testing suite Since SOCI plans on removing this functionality from the CLI, we can preemptively remove our test's dependency on this component of the CLI by hardcoding the expected number of mounts per image. This is fine because the same image with the same SOCI config will always have the same amount of mounts. The only caveat is that one must know how many mounts to expect from a certain image. Additionally, small refactoring was done to allow for more future test coverage, and to allow TestSociRun to be as flexible as TestSociPull. Signed-off-by: David Son --- cmd/nerdctl/container_run_soci_linux_test.go | 82 +++++++++----------- cmd/nerdctl/image_pull_linux_test.go | 49 ++++-------- 2 files changed, 53 insertions(+), 78 deletions(-) diff --git a/cmd/nerdctl/container_run_soci_linux_test.go b/cmd/nerdctl/container_run_soci_linux_test.go index fe3cda5befa..2cde0118e3d 100644 --- a/cmd/nerdctl/container_run_soci_linux_test.go +++ b/cmd/nerdctl/container_run_soci_linux_test.go @@ -17,7 +17,6 @@ package main import ( - "os" "os/exec" "strings" "testing" @@ -27,60 +26,51 @@ import ( func TestRunSoci(t *testing.T) { testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - requiresSoci(base) - - //counting initial snapshot mounts - initialMounts, err := exec.Command("mount").Output() - if err != nil { - t.Fatal(err) - } - - remoteSnapshotsInitialCount := strings.Count(string(initialMounts), "fuse.rawBridge") - - if remoteSnapshotsInitialCount != 0 { - t.Fatalf("initial mounts count isn't zero") - } - - //validating `nerdctl --snapshotter=soci run` and `soci rpull` behave the same using mounts - runOutput := base.Cmd("--snapshotter=soci", "run", "--rm", testutil.FfmpegSociImage).Out() - base.T.Logf("run output: %s", runOutput) - - actualMounts, err := exec.Command("mount").Output() - if err != nil { - t.Fatal(err) + tests := []struct { + name string + image string + remoteSnapshotsExpectedCount int + }{ + { + name: "Run with SOCI", + image: testutil.FfmpegSociImage, + remoteSnapshotsExpectedCount: 11, + }, } - remoteSnapshotsActualCount := strings.Count(string(actualMounts), "fuse.rawBridge") - base.T.Logf("number of actual mounts: %v", remoteSnapshotsActualCount) - rmiOutput := base.Cmd("rmi", testutil.FfmpegSociImage).Out() - base.T.Logf("rmi output: %s", rmiOutput) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + base := testutil.NewBase(t) + requiresSoci(base) - sociExecutable, err := exec.LookPath("soci") - if err != nil { - t.Fatalf("SOCI is not installed.") - } + //counting initial snapshot mounts + initialMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } - rpullCmd := exec.Command(sociExecutable, []string{"image", "rpull", testutil.FfmpegSociImage}...) + remoteSnapshotsInitialCount := strings.Count(string(initialMounts), "fuse.rawBridge") - rpullCmd.Env = os.Environ() + runOutput := base.Cmd("--snapshotter=soci", "run", "--rm", testutil.FfmpegSociImage).Out() + base.T.Logf("run output: %s", runOutput) - err = rpullCmd.Run() - if err != nil { - t.Fatal(err) - } + actualMounts, err := exec.Command("mount").Output() + if err != nil { + t.Fatal(err) + } + remoteSnapshotsActualCount := strings.Count(string(actualMounts), "fuse.rawBridge") + base.T.Logf("number of actual mounts: %v", remoteSnapshotsActualCount) - expectedMounts, err := exec.Command("mount").Output() - if err != nil { - t.Fatal(err) - } + rmiOutput := base.Cmd("rmi", testutil.FfmpegSociImage).Out() + base.T.Logf("rmi output: %s", rmiOutput) - remoteSnapshotsExpectedCount := strings.Count(string(expectedMounts), "fuse.rawBridge") - base.T.Logf("number of expected mounts: %v", remoteSnapshotsExpectedCount) + base.T.Logf("number of expected mounts: %v", tt.remoteSnapshotsExpectedCount) - if remoteSnapshotsExpectedCount != remoteSnapshotsActualCount { - t.Fatalf("incorrect number of remote snapshots; expected=%d, actual=%d", - remoteSnapshotsExpectedCount, remoteSnapshotsActualCount) + if tt.remoteSnapshotsExpectedCount != (remoteSnapshotsActualCount - remoteSnapshotsInitialCount) { + t.Fatalf("incorrect number of remote snapshots; expected=%d, actual=%d", + tt.remoteSnapshotsExpectedCount, remoteSnapshotsActualCount-remoteSnapshotsInitialCount) + } + }) } } diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image_pull_linux_test.go index b2addb786e3..5c09157cdcc 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image_pull_linux_test.go @@ -149,16 +149,22 @@ CMD ["echo", "nerdctl-build-test-string"] func TestPullSoci(t *testing.T) { testutil.DockerIncompatible(t) tests := []struct { - name string - sociIndexDigest string + name string + sociIndexDigest string + image string + remoteSnapshotsExpectedCount int }{ { - name: "Run without specifying SOCI index", - sociIndexDigest: "", + name: "Run without specifying SOCI index", + sociIndexDigest: "", + image: testutil.FfmpegSociImage, + remoteSnapshotsExpectedCount: 11, }, { - name: "Run with bad SOCI index", - sociIndexDigest: "sha256:thisisabadindex0000000000000000000000000000000000000000000000000", + name: "Run with bad SOCI index", + sociIndexDigest: "sha256:thisisabadindex0000000000000000000000000000000000000000000000000", + image: testutil.FfmpegSociImage, + remoteSnapshotsExpectedCount: 11, }, } @@ -175,8 +181,7 @@ func TestPullSoci(t *testing.T) { remoteSnapshotsInitialCount := strings.Count(string(initialMounts), "fuse.rawBridge") - //validating `nerdctl --snapshotter=soci pull` and `soci rpull` behave the same using mounts - pullOutput := base.Cmd("--snapshotter=soci", "pull", testutil.FfmpegSociImage).Out() + pullOutput := base.Cmd("--snapshotter=soci", "pull", tt.image).Out() base.T.Logf("pull output: %s", pullOutput) actualMounts, err := exec.Command("mount").Output() @@ -184,36 +189,16 @@ func TestPullSoci(t *testing.T) { t.Fatal(err) } remoteSnapshotsActualCount := strings.Count(string(actualMounts), "fuse.rawBridge") - base.T.Logf("number of actual mounts: %v", remoteSnapshotsActualCount) + base.T.Logf("number of actual mounts: %v", remoteSnapshotsActualCount-remoteSnapshotsInitialCount) rmiOutput := base.Cmd("rmi", testutil.FfmpegSociImage).Out() base.T.Logf("rmi output: %s", rmiOutput) - sociExecutable, err := exec.LookPath("soci") - if err != nil { - t.Fatalf("SOCI is not installed.") - } - - rpullCmd := exec.Command(sociExecutable, []string{"image", "rpull", testutil.FfmpegSociImage}...) - - rpullCmd.Env = os.Environ() - - err = rpullCmd.Run() - if err != nil { - t.Fatal(err) - } - - expectedMounts, err := exec.Command("mount").Output() - if err != nil { - t.Fatal(err) - } - - remoteSnapshotsExpectedCount := strings.Count(string(expectedMounts), "fuse.rawBridge") - base.T.Logf("number of expected mounts: %v", remoteSnapshotsExpectedCount) + base.T.Logf("number of expected mounts: %v", tt.remoteSnapshotsExpectedCount) - if remoteSnapshotsExpectedCount != (remoteSnapshotsActualCount - remoteSnapshotsInitialCount) { + if tt.remoteSnapshotsExpectedCount != (remoteSnapshotsActualCount - remoteSnapshotsInitialCount) { t.Fatalf("incorrect number of remote snapshots; expected=%d, actual=%d", - remoteSnapshotsExpectedCount, remoteSnapshotsActualCount) + tt.remoteSnapshotsExpectedCount, remoteSnapshotsActualCount-remoteSnapshotsInitialCount) } }) } From f59c2bed15e9f9d62b0a15890c988b1ba1c72d79 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Fri, 29 Dec 2023 10:50:40 +0000 Subject: [PATCH 0278/1066] Add docs for trouble shooting nvidia gpu operator Signed-off-by: Kay Yan --- docs/gpu.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/gpu.md b/docs/gpu.md index cd200351a3c..4106facda16 100644 --- a/docs/gpu.md +++ b/docs/gpu.md @@ -62,3 +62,24 @@ services: - capabilities: ["utility"] count: all ``` + +## Trouble Shooting + +### `nerdctl run --gpus` fails when using the Nvidia gpu-operator + +If the Nvidia driver is installed by the [gpu-operator](https://github.com/NVIDIA/gpu-operator).The `nerdctl run` will fail with the error message `(FATA[0000] exec: "nvidia-container-cli": executable file not found in $PATH)`. + +So, the `nvidia-container-cli` needs to be added to the PATH environment variable. + +You can do this by adding the following line to your $HOME/.profile or /etc/profile (for a system-wide installation): +``` +export PATH=$PATH:/usr/local/nvidia/toolkit +``` + +The shared libraries also need to be added to the system. +``` +echo "/run/nvidia/driver/usr/lib/x86_64-linux-gnu" > /etc/ld.so.conf.d/nvidia.conf +ldconfig +``` + +And then, the `nerdctl run --gpus` can run successfully. From f60bbc65748971e1d6b79a8dad9ee8b5b2208df7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Dec 2023 22:38:54 +0000 Subject: [PATCH 0279/1066] build(deps): bump github.com/containerd/cgroups/v3 from 3.0.2 to 3.0.3 Bumps [github.com/containerd/cgroups/v3](https://github.com/containerd/cgroups) from 3.0.2 to 3.0.3. - [Release notes](https://github.com/containerd/cgroups/releases) - [Commits](https://github.com/containerd/cgroups/compare/v3.0.2...v3.0.3) --- updated-dependencies: - dependency-name: github.com/containerd/cgroups/v3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 5 ++--- go.sum | 19 +++++++------------ 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index a04b6691e10..4034eb486f2 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( 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/cgroups/v3 v3.0.2 + github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.7.11 github.com/containerd/continuity v0.4.3 @@ -68,7 +68,7 @@ require ( github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect - github.com/cilium/ebpf v0.9.1 // indirect + github.com/cilium/ebpf v0.11.0 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/go-runc v1.0.0 // indirect github.com/containerd/ttrpc v1.2.2 // indirect @@ -94,7 +94,6 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.17.4 github.com/klauspost/cpuid/v2 v2.2.3 // indirect - github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect diff --git a/go.sum b/go.sum index 78cfdf6c33a..acea838a6b4 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= -github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= +github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y= +github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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= @@ -31,8 +31,8 @@ github.com/containerd/accelerated-container-image v1.0.2 h1:4GmZg/8TrxAbTTpighui github.com/containerd/accelerated-container-image v1.0.2/go.mod h1:0/cMmA65Zervb+pO+sZvxvhqiO/pWoKdTf2zgbh59Zo= 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.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= -github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= +github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= +github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= @@ -44,10 +44,10 @@ 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= github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= -github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC2XV0= -github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0= github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC2XV0= +github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= 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= @@ -75,7 +75,6 @@ github.com/coreos/go-iptables v0.7.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFE github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= @@ -110,7 +109,7 @@ github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBd github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= @@ -183,9 +182,7 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -258,7 +255,6 @@ github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOS github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -266,7 +262,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rootless-containers/bypass4netns v0.3.0 h1:UwI55zWDZz7OGyN4YWgfCKdsI58VGY7OlghcLdxJX10= github.com/rootless-containers/bypass4netns v0.3.0/go.mod h1:IXHPjkQlJRygNBCN0hSSR3ITX6kDKr3aAaGHx6APd+g= From df43d623db452a3ca74200a0dbd33dacd56329b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Dec 2023 22:39:07 +0000 Subject: [PATCH 0280/1066] build(deps): bump go.uber.org/mock from 0.3.0 to 0.4.0 Bumps [go.uber.org/mock](https://github.com/uber/mock) from 0.3.0 to 0.4.0. - [Release notes](https://github.com/uber/mock/releases) - [Changelog](https://github.com/uber-go/mock/blob/main/CHANGELOG.md) - [Commits](https://github.com/uber/mock/compare/v0.3.0...v0.4.0) --- updated-dependencies: - dependency-name: go.uber.org/mock dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index a04b6691e10..68c9d2f20c5 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 - go.uber.org/mock v0.3.0 + go.uber.org/mock v0.4.0 golang.org/x/crypto v0.17.0 golang.org/x/net v0.19.0 golang.org/x/sync v0.5.0 diff --git a/go.sum b/go.sum index 78cfdf6c33a..d5c664d30e3 100644 --- a/go.sum +++ b/go.sum @@ -44,10 +44,10 @@ 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= github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= -github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC2XV0= -github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0= github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC2XV0= +github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= 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= @@ -338,8 +338,8 @@ go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319 go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= From c44427fbb97a7d9078c53b4a7199afdcb0344c07 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 1 Jan 2024 10:11:43 +0900 Subject: [PATCH 0281/1066] nerdctl rm: fix printing `error=""` on warning On printing warning, the error was just dismissed Signed-off-by: Akihiro Suda --- pkg/cmd/container/remove.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index d0d476fd48d..11e4a91c230 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -124,16 +124,16 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions return } if err := os.RemoveAll(stateDir); err != nil { - log.G(ctx).WithError(retErr).Warnf("failed to remove container state dir %s", stateDir) + log.G(ctx).WithError(err).Warnf("failed to remove container state dir %s", stateDir) } // enforce release name here in case the poststop hook name release fails if name != "" { if err := namst.Release(name, id); err != nil { - log.G(ctx).WithError(retErr).Warnf("failed to release container name %s", name) + log.G(ctx).WithError(err).Warnf("failed to release container name %s", name) } } if err := hostsstore.DeallocHostsFile(dataStore, ns, id); err != nil { - log.G(ctx).WithError(retErr).Warnf("failed to remove hosts file for container %q", id) + log.G(ctx).WithError(err).Warnf("failed to remove hosts file for container %q", id) } }() @@ -192,7 +192,7 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions } if err := networkManager.CleanupNetworking(ctx, c); err != nil { - log.G(ctx).WithError(retErr).Warnf("failed to clean up container networking: %s", err) + log.G(ctx).WithError(err).Warnf("failed to clean up container networking: %s", err) } } From 695f11a2c6cb023ff6a364d4dc28af495bafefe9 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 1 Jan 2024 10:15:42 +0900 Subject: [PATCH 0282/1066] cniNetworkManager: move Windows-specific variable to `_windows.go` Signed-off-by: Akihiro Suda --- pkg/containerutil/container_network_manager.go | 5 ++--- pkg/containerutil/container_network_manager_linux.go | 3 +++ pkg/containerutil/container_network_manager_other.go | 3 +++ pkg/containerutil/container_network_manager_windows.go | 4 ++++ 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 6b29661c8a9..67a49f2dd88 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -30,7 +30,6 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/netns" "github.com/containerd/nerdctl/pkg/api/types" "github.com/containerd/nerdctl/pkg/clientutil" "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" @@ -128,7 +127,7 @@ func NewNetworkingOptionsManager(globalOptions types.GlobalCommandOptions, netOp case nettype.Container: manager = &containerNetworkManager{globalOptions, netOpts, client} case nettype.CNI: - manager = &cniNetworkManager{globalOptions, netOpts, nil, client} + manager = &cniNetworkManager{globalOptions, netOpts, client, cniNetworkManagerPlatform{}} default: return nil, fmt.Errorf("unexpected container networking type: %q", netType) } @@ -471,8 +470,8 @@ func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containe type cniNetworkManager struct { globalOptions types.GlobalCommandOptions netOpts types.NetworkOptions - netNs *netns.NetNS client *containerd.Client + cniNetworkManagerPlatform } // NetworkOptions Returns a copy of the internal types.NetworkOptions. diff --git a/pkg/containerutil/container_network_manager_linux.go b/pkg/containerutil/container_network_manager_linux.go index b8ea83098f4..4702b2ce81b 100644 --- a/pkg/containerutil/container_network_manager_linux.go +++ b/pkg/containerutil/container_network_manager_linux.go @@ -34,6 +34,9 @@ import ( "github.com/containerd/nerdctl/pkg/rootlessutil" ) +type cniNetworkManagerPlatform struct { +} + // Verifies that the internal network settings are correct. func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithDefaultNetwork()) diff --git a/pkg/containerutil/container_network_manager_other.go b/pkg/containerutil/container_network_manager_other.go index 500872f57c3..af6c337e8b8 100644 --- a/pkg/containerutil/container_network_manager_other.go +++ b/pkg/containerutil/container_network_manager_other.go @@ -28,6 +28,9 @@ import ( "github.com/containerd/nerdctl/pkg/api/types" ) +type cniNetworkManagerPlatform struct { +} + // Verifies that the internal network settings are correct. func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { return fmt.Errorf("CNI networking currently unsupported on %s", runtime.GOOS) diff --git a/pkg/containerutil/container_network_manager_windows.go b/pkg/containerutil/container_network_manager_windows.go index 88abaeb6073..774c737ac82 100644 --- a/pkg/containerutil/container_network_manager_windows.go +++ b/pkg/containerutil/container_network_manager_windows.go @@ -30,6 +30,10 @@ import ( "github.com/containerd/nerdctl/pkg/ocihook" ) +type cniNetworkManagerPlatform struct { + netNs *netns.NetNS +} + // Verifies that the internal network settings are correct. func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithDefaultNetwork()) From 9afd9e3e9d541d9d18fd56d930ed38523aad043c Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 2 Jan 2024 14:00:21 +0000 Subject: [PATCH 0283/1066] update runc (v1.1.10) Signed-off-by: Kay Yan --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ccd1b23ff64..1e00f459ebb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v1.7.11 -ARG RUNC_VERSION=v1.1.10 +ARG RUNC_VERSION=v1.1.11 ARG CNI_PLUGINS_VERSION=v1.4.0 # Extra deps: Build From b04586627791dcdc16a347f9d593ba61d8733128 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 2 Jan 2024 11:17:08 +0900 Subject: [PATCH 0284/1066] logging: respect ctx The ctx is cancelled on SIGTERM Fix issue 2726 (regression in PR 2683) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 2 +- Dockerfile | 2 +- cmd/nerdctl/container_run_test.go | 14 ++++++++++++++ go.mod | 1 + go.sum | 2 ++ pkg/logging/logging.go | 26 +++++++++++++++++++++----- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a9a22221d01..2e6ac21683b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -70,7 +70,7 @@ jobs: test-integration: runs-on: "ubuntu-${{ matrix.ubuntu }}" - timeout-minutes: 60 + timeout-minutes: 40 strategy: fail-fast: false matrix: diff --git a/Dockerfile b/Dockerfile index 1e00f459ebb..c36a5ac26f5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -313,7 +313,7 @@ RUN curl -L -o nydus-static.tgz "https://github.com/dragonflyoss/image-service/r mv nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/bin/ && \ rm nydus-static.tgz CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/cmd/nerdctl/...", \ - "--", "-timeout=60m", "-args", "-test.kill-daemon"] + "--", "-timeout=30m", "-args", "-test.kill-daemon"] FROM test-integration AS test-integration-rootless # Install SSH for creating systemd user session. diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index b543c8811ae..e18aa7ac8e6 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -510,3 +510,17 @@ func TestRunAddHostRemainsWhenAnotherContainerCreated(t *testing.T) { base.Cmd("exec", containerName, "cat", "/etc/hosts").AssertOutWithFunc(checkEtcHosts) } + +// https://github.com/containerd/nerdctl/issues/2726 +func TestRunRmTime(t *testing.T) { + base := testutil.NewBase(t) + base.Cmd("pull", testutil.CommonImage) + t0 := time.Now() + base.Cmd("run", "--rm", testutil.CommonImage, "true").AssertOK() + t1 := time.Now() + took := t1.Sub(t0) + const deadline = 3 * time.Second + if took > deadline { + t.Fatalf("expected to have completed in %v, took %v", deadline, took) + } +} diff --git a/go.mod b/go.mod index 13fdefa3577..df6cc4b6c0c 100644 --- a/go.mod +++ b/go.mod @@ -40,6 +40,7 @@ require ( github.com/moby/sys/mount v0.3.3 github.com/moby/sys/signal v0.7.0 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/runtime-spec v1.1.0 diff --git a/go.sum b/go.sum index ab9c981260b..18f02d3fc39 100644 --- a/go.sum +++ b/go.sum @@ -214,6 +214,8 @@ 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= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index f59936f8f18..9339868f2a7 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -31,6 +31,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime/v2/logging" "github.com/containerd/log" + "github.com/muesli/cancelreader" ) const ( @@ -140,10 +141,25 @@ func LoadLogConfig(dataStore, ns, id string) (LogConfig, error) { return logConfig, nil } -func loggingProcessAdapter(driver Driver, dataStore string, config *logging.Config) error { +func loggingProcessAdapter(ctx context.Context, driver Driver, dataStore string, config *logging.Config) error { if err := driver.PreProcess(dataStore, config); err != nil { return err } + + stdoutR, err := cancelreader.NewReader(config.Stdout) + if err != nil { + return err + } + stderrR, err := cancelreader.NewReader(config.Stderr) + if err != nil { + return err + } + go func() { + <-ctx.Done() // delivered on SIGTERM + stdoutR.Cancel() + stderrR.Cancel() + }() + var wg sync.WaitGroup wg.Add(3) stdout := make(chan string, 10000) @@ -161,8 +177,8 @@ func loggingProcessAdapter(driver Driver, dataStore string, config *logging.Conf } } - go processLogFunc(config.Stdout, stdout) - go processLogFunc(config.Stderr, stderr) + go processLogFunc(stdoutR, stdout) + go processLogFunc(stderrR, stderr) go func() { defer wg.Done() driver.Process(stdout, stderr) @@ -175,7 +191,7 @@ func loggerFunc(dataStore string) (logging.LoggerFunc, error) { if dataStore == "" { return nil, errors.New("got empty data store") } - return func(_ context.Context, config *logging.Config, ready func() error) error { + return func(ctx context.Context, config *logging.Config, ready func() error) error { if config.Namespace == "" || config.ID == "" { return errors.New("got invalid config") } @@ -193,7 +209,7 @@ func loggerFunc(dataStore string) (logging.LoggerFunc, error) { return err } - return loggingProcessAdapter(driver, dataStore, config) + return loggingProcessAdapter(ctx, driver, dataStore, config) } else if !errors.Is(err, os.ErrNotExist) { // the file does not exist if the container was created with nerdctl < 0.20 return err From 2053c384f2c7e2ae51cb0b8a449b7ef3dd5dbf83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 22:24:10 +0000 Subject: [PATCH 0285/1066] build(deps): bump golang.org/x/term from 0.15.0 to 0.16.0 Bumps [golang.org/x/term](https://github.com/golang/term) from 0.15.0 to 0.16.0. - [Commits](https://github.com/golang/term/compare/v0.15.0...v0.16.0) --- updated-dependencies: - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index df6cc4b6c0c..be48cc3e308 100644 --- a/go.mod +++ b/go.mod @@ -57,8 +57,8 @@ require ( golang.org/x/crypto v0.17.0 golang.org/x/net v0.19.0 golang.org/x/sync v0.5.0 - golang.org/x/sys v0.15.0 - golang.org/x/term v0.15.0 + golang.org/x/sys v0.16.0 + golang.org/x/term v0.16.0 golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 diff --git a/go.sum b/go.sum index 18f02d3fc39..f18e63a3f47 100644 --- a/go.sum +++ b/go.sum @@ -402,11 +402,11 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From ce955db174265151dc84306b7261c3c70bdc214c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 01:37:09 +0000 Subject: [PATCH 0286/1066] build(deps): bump golang.org/x/sync from 0.5.0 to 0.6.0 Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.5.0 to 0.6.0. - [Commits](https://github.com/golang/sync/compare/v0.5.0...v0.6.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index be48cc3e308..9a2d911293b 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( go.uber.org/mock v0.4.0 golang.org/x/crypto v0.17.0 golang.org/x/net v0.19.0 - golang.org/x/sync v0.5.0 + golang.org/x/sync v0.6.0 golang.org/x/sys v0.16.0 golang.org/x/term v0.16.0 golang.org/x/text v0.14.0 diff --git a/go.sum b/go.sum index f18e63a3f47..97d3c3eafca 100644 --- a/go.sum +++ b/go.sum @@ -374,8 +374,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From 3fa62388da81ac1cca1f770234e0b61b7624b46e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 22:17:24 +0000 Subject: [PATCH 0287/1066] build(deps): bump docker/metadata-action from 5.4.0 to 5.5.0 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.4.0 to 5.5.0. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/v5.4.0...v5.5.0) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 96da665d27c..049911e5df0 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -52,7 +52,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v5.4.0 + uses: docker/metadata-action@v5.5.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} From aa11ded3c7e9764ed42b046bed28c47157314bc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 22:40:03 +0000 Subject: [PATCH 0288/1066] build(deps): bump github.com/docker/go-connections from 0.4.0 to 0.5.0 Bumps [github.com/docker/go-connections](https://github.com/docker/go-connections) from 0.4.0 to 0.5.0. - [Commits](https://github.com/docker/go-connections/compare/v0.4.0...v0.5.0) --- updated-dependencies: - dependency-name: github.com/docker/go-connections dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9a2d911293b..2bd7b607d78 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/cyphar/filepath-securejoin v0.2.4 github.com/docker/cli v24.0.7+incompatible github.com/docker/docker v24.0.7+incompatible - github.com/docker/go-connections v0.4.0 + github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.0 github.com/fatih/color v1.16.0 diff --git a/go.sum b/go.sum index 97d3c3eafca..3f930144dc3 100644 --- a/go.sum +++ b/go.sum @@ -91,8 +91,8 @@ github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= From d0179a635db1b33b163992c3c83715f74c9f127c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 22:38:40 +0000 Subject: [PATCH 0289/1066] build(deps): bump golang.org/x/net from 0.19.0 to 0.20.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.19.0 to 0.20.0. - [Commits](https://github.com/golang/net/compare/v0.19.0...v0.20.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 2bd7b607d78..ea41c9cf543 100644 --- a/go.mod +++ b/go.mod @@ -54,8 +54,8 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.17.0 - golang.org/x/net v0.19.0 + golang.org/x/crypto v0.18.0 + golang.org/x/net v0.20.0 golang.org/x/sync v0.6.0 golang.org/x/sys v0.16.0 golang.org/x/term v0.16.0 diff --git a/go.sum b/go.sum index 3f930144dc3..00647c7745b 100644 --- a/go.sum +++ b/go.sum @@ -341,8 +341,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= @@ -365,8 +365,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From a71209f8a3184c92a154556e4e0ee893a4662e91 Mon Sep 17 00:00:00 2001 From: baijia Date: Tue, 9 Jan 2024 20:24:29 +0800 Subject: [PATCH 0290/1066] fix: return error if volume create failed If processing volume create options failed, return error. Signed-off-by: baijia --- cmd/nerdctl/volume_create.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume_create.go index 9a10b46d326..4a90d082a77 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume_create.go @@ -55,7 +55,7 @@ func processVolumeCreateOptions(cmd *cobra.Command) (types.VolumeCreateOptions, func volumeCreateAction(cmd *cobra.Command, args []string) error { options, err := processVolumeCreateOptions(cmd) if err != nil { - return nil + return err } volumeName := "" if len(args) > 0 { From 8e09af1ef3a118e7c189da7c06f3ebf17785bb87 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 11 Jan 2024 17:09:25 +0900 Subject: [PATCH 0291/1066] shfmt containerd-rootless-setuptool.sh Signed-off-by: Akihiro Suda --- extras/rootless/containerd-rootless-setuptool.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extras/rootless/containerd-rootless-setuptool.sh b/extras/rootless/containerd-rootless-setuptool.sh index 6ce786c2808..50e278d6577 100755 --- a/extras/rootless/containerd-rootless-setuptool.sh +++ b/extras/rootless/containerd-rootless-setuptool.sh @@ -283,7 +283,7 @@ cmd_entrypoint_install_buildkit_containerd() { fi if [ ! -f "${XDG_CONFIG_HOME}/buildkit/buildkitd.toml" ]; then mkdir -p "${XDG_CONFIG_HOME}/buildkit" - cat <<-EOF > "${XDG_CONFIG_HOME}/buildkit/buildkitd.toml" + cat <<-EOF >"${XDG_CONFIG_HOME}/buildkit/buildkitd.toml" [worker.oci] enabled = false @@ -298,13 +298,13 @@ cmd_entrypoint_install_buildkit_containerd() { fi UNIT_NAME=${SYSTEMD_BUILDKIT_UNIT} BUILDKITD_FLAG= - if [ -n "${CONTAINERD_NAMESPACE:-}" ] ; then + if [ -n "${CONTAINERD_NAMESPACE:-}" ]; then UNIT_NAME="${CONTAINERD_NAMESPACE}-${SYSTEMD_BUILDKIT_UNIT}" BUILDKITD_FLAG="${BUILDKITD_FLAG} --addr=unix://${XDG_RUNTIME_DIR}/buildkit-${CONTAINERD_NAMESPACE}/buildkitd.sock --root=${XDG_DATA_HOME}/buildkit-${CONTAINERD_NAMESPACE} --containerd-worker-namespace=${CONTAINERD_NAMESPACE}" else WARNING "buildkitd has access to images in \"buildkit\" namespace by default. If you want to give buildkitd access to the images in \"default\" namespace, run this command with CONTAINERD_NAMESPACE=default" fi - if [ -n "${CONTAINERD_SNAPSHOTTER:-}" ] ; then + if [ -n "${CONTAINERD_SNAPSHOTTER:-}" ]; then BUILDKITD_FLAG="${BUILDKITD_FLAG} --containerd-worker-snapshotter=${CONTAINERD_SNAPSHOTTER}" fi cat <<-EOT | install_systemd_unit "${UNIT_NAME}" @@ -519,7 +519,7 @@ cmd_entrypoint_uninstall_buildkit_containerd() { init UNIT_NAME=${SYSTEMD_BUILDKIT_UNIT} BUILDKIT_ROOT="${XDG_DATA_HOME}/buildkit" - if [ -n "${CONTAINERD_NAMESPACE:-}" ] ; then + if [ -n "${CONTAINERD_NAMESPACE:-}" ]; then UNIT_NAME="${CONTAINERD_NAMESPACE}-${SYSTEMD_BUILDKIT_UNIT}" BUILDKIT_ROOT="${XDG_DATA_HOME}/buildkit-${CONTAINERD_NAMESPACE}" fi From 3b5717be55b370944edacc56e811a355b81cfde2 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 11 Jan 2024 17:09:48 +0900 Subject: [PATCH 0292/1066] containerd-rootless-setuptool.sh nsenter: inherit RootlessKit env Inherit `$ROOTLESSKIT_STATE_DIR`, etc. Fix issue 2741 Signed-off-by: Akihiro Suda --- extras/rootless/containerd-rootless-setuptool.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/extras/rootless/containerd-rootless-setuptool.sh b/extras/rootless/containerd-rootless-setuptool.sh index 50e278d6577..03e6252aa6f 100755 --- a/extras/rootless/containerd-rootless-setuptool.sh +++ b/extras/rootless/containerd-rootless-setuptool.sh @@ -139,10 +139,20 @@ cmd_entrypoint_check() { INFO "Requirements are satisfied" } +propagate_env_from() { + pid="$1" + env="$(sed -e "s/\x0/'\n/g" <"/proc/${pid}/environ" | sed -Ee "s/^[^=]*=/export \0'/g")" + shift + for key in $@; do + eval $(echo "$env" | grep "^export ${key=}") + done +} + # CLI subcommand: "nsenter" cmd_entrypoint_nsenter() { # No need to call init() pid=$(cat "$XDG_RUNTIME_DIR/containerd-rootless/child_pid") + propagate_env_from "$pid" ROOTLESSKIT_STATE_DIR ROOTLESSKIT_PARENT_EUID ROOTLESSKIT_PARENT_EGID exec nsenter --no-fork --wd="$(pwd)" --preserve-credentials -m -n -U -t "$pid" -- "$@" } From 050594006e5a9fa353870cc576cb134c7f269f23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 22:31:09 +0000 Subject: [PATCH 0293/1066] build(deps): bump github.com/rootless-containers/bypass4netns Bumps [github.com/rootless-containers/bypass4netns](https://github.com/rootless-containers/bypass4netns) from 0.3.0 to 0.4.0. - [Commits](https://github.com/rootless-containers/bypass4netns/compare/v0.3.0...v0.4.0) --- updated-dependencies: - dependency-name: github.com/rootless-containers/bypass4netns dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ea41c9cf543..bd206d11d81 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/opencontainers/image-spec v1.1.0-rc5 github.com/opencontainers/runtime-spec v1.1.0 github.com/pelletier/go-toml/v2 v2.1.1 - github.com/rootless-containers/bypass4netns v0.3.0 + github.com/rootless-containers/bypass4netns v0.4.0 github.com/rootless-containers/rootlesskit v1.1.1 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index 00647c7745b..d8a46bdcc38 100644 --- a/go.sum +++ b/go.sum @@ -265,8 +265,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rootless-containers/bypass4netns v0.3.0 h1:UwI55zWDZz7OGyN4YWgfCKdsI58VGY7OlghcLdxJX10= -github.com/rootless-containers/bypass4netns v0.3.0/go.mod h1:IXHPjkQlJRygNBCN0hSSR3ITX6kDKr3aAaGHx6APd+g= +github.com/rootless-containers/bypass4netns v0.4.0 h1:7pcI4XWnOMQkgCsPKMXxMzQKhZUjaQ8J1n+eIYiHS0Y= +github.com/rootless-containers/bypass4netns v0.4.0/go.mod h1:RPNWMSRT951DMtq9Xv72IZoJPWFeJL6Wg5pF79Lkano= github.com/rootless-containers/rootlesskit v1.1.1 h1:F5psKWoWY9/VjZ3ifVcaosjvFZJOagX85U22M0/EQZE= github.com/rootless-containers/rootlesskit v1.1.1/go.mod h1:UD5GoA3dqKCJrnvnhVgQQnweMF2qZnf9KLw8EewcMZI= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= From 410d59154116934d4f23adef49f44a43f8aa895a Mon Sep 17 00:00:00 2001 From: Dima Tisnek Date: Fri, 12 Jan 2024 10:19:25 +0900 Subject: [PATCH 0294/1066] Document that profiles are supported Signed-off-by: Dima Tisnek --- docs/compose.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/compose.md b/docs/compose.md index ac8cf696383..a07c91a5207 100644 --- a/docs/compose.md +++ b/docs/compose.md @@ -29,7 +29,6 @@ which was derived from [Docker Compose file version 3 specification](https://doc - `services..deploy.placement` - `services..deploy.endpoint_mode` - `services..healthcheck` -- `services..profiles` - `services..stop_grace_period` - `services..stop_signal` - `configs..external` From 5ee55f2847d6ba96f1cdb1bbe254399c947cf22a Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 11 Jan 2024 10:22:23 +0000 Subject: [PATCH 0295/1066] add allow option in build Signed-off-by: Kay Yan --- cmd/nerdctl/builder_build.go | 9 +++++++++ docs/command-reference.md | 1 + pkg/api/types/builder_types.go | 2 ++ pkg/cmd/builder/build.go | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index 567648f86b1..a74d3876e9a 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -51,6 +51,10 @@ If Dockerfile is not present and -f is not specified, it will look for Container buildCommand.Flags().StringP("output", "o", "", "Output destination (format: type=local,dest=path)") buildCommand.Flags().String("progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output") buildCommand.Flags().StringArray("secret", nil, "Secret file to expose to the build: id=mysecret,src=/local/secret") + buildCommand.Flags().StringArray("allow", nil, "Allow extra privileged entitlement, e.g. network.host, security.insecure") + buildCommand.RegisterFlagCompletionFunc("allow", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"network.host", "security.insecure"}, cobra.ShellCompDirectiveNoFileComp + }) buildCommand.Flags().StringArray("ssh", nil, "SSH agent socket or keys to expose to the build (format: default|[=|[,]])") buildCommand.Flags().BoolP("quiet", "q", false, "Suppress the build output and print image ID on success") buildCommand.Flags().StringArray("cache-from", nil, "External cache sources (eg. user/app:cache, type=local,src=path/to/dir)") @@ -129,6 +133,10 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu if err != nil { return types.BuilderBuildOptions{}, err } + allow, err := cmd.Flags().GetStringArray("allow") + if err != nil { + return types.BuilderBuildOptions{}, err + } ssh, err := cmd.Flags().GetStringArray("ssh") if err != nil { return types.BuilderBuildOptions{}, err @@ -170,6 +178,7 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu Label: label, NoCache: noCache, Secret: secret, + Allow: allow, SSH: ssh, CacheFrom: cacheFrom, CacheTo: cacheTo, diff --git a/docs/command-reference.md b/docs/command-reference.md index ba535cacf14..cbd79627998 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -681,6 +681,7 @@ Flags: - :whale: `type=image,name=example.com/image,push=true`: Push to a registry (see [`buildctl build`](https://github.com/moby/buildkit/tree/v0.9.0#imageregistry) documentation) - :whale: `--progress=(auto|plain|tty)`: Set type of progress output (auto, plain, tty). Use plain to show container output - :whale: `--secret`: Secret file to expose to the build: id=mysecret,src=/local/secret +- :whale: `--allow`: Allow extra privileged entitlement, e.g. network.host, security.insecure (It’s required to configure the buildkitd to enable the feature, see [`buildkitd.toml`](https://github.com/moby/buildkit/blob/master/docs/buildkitd.toml.md) documentation) - :whale: `--ssh`: SSH agent socket or keys to expose to the build (format: `default|[=|[,]]`) - :whale: `-q, --quiet`: Suppress the build output and print image ID on success - :whale: `--cache-from=CACHE`: External cache sources (eg. user/app:cache, type=local,src=path/to/dir) (compatible with `docker buildx build`) diff --git a/pkg/api/types/builder_types.go b/pkg/api/types/builder_types.go index c796c3568d3..460814e9c0d 100644 --- a/pkg/api/types/builder_types.go +++ b/pkg/api/types/builder_types.go @@ -43,6 +43,8 @@ type BuilderBuildOptions struct { Progress string // Secret file to expose to the build: id=mysecret,src=/local/secret Secret []string + // Allow extra privileged entitlement, e.g. network.host, security.insecure + Allow []string // SSH agent socket or keys to expose to the build (format: default|[=|[,]]) SSH []string // Quiet suppress the build output and print image ID on success diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index df575fcd955..fa2feeaa085 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -328,6 +328,10 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option buildctlArgs = append(buildctlArgs, "--secret="+s) } + for _, s := range strutil.DedupeStrSlice(options.Allow) { + buildctlArgs = append(buildctlArgs, "--allow="+s) + } + for _, s := range strutil.DedupeStrSlice(options.SSH) { buildctlArgs = append(buildctlArgs, "--ssh="+s) } From 4af27bd19f57b7b605e32c94260688ad9be73e19 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 12 Jan 2024 14:39:53 +0900 Subject: [PATCH 0296/1066] go.mod: module github.com/containerd/nerdctl/v2 Signed-off-by: Akihiro Suda --- Dockerfile | 6 ++-- Makefile | 2 +- README.md | 2 +- cmd/nerdctl/apparmor_inspect_linux.go | 6 ++-- cmd/nerdctl/apparmor_list_linux.go | 4 +-- cmd/nerdctl/apparmor_load_linux.go | 4 +-- cmd/nerdctl/apparmor_unload_linux.go | 4 +-- cmd/nerdctl/builder.go | 4 +-- cmd/nerdctl/builder_build.go | 12 ++++---- cmd/nerdctl/builder_build_test.go | 2 +- cmd/nerdctl/builder_linux_test.go | 2 +- cmd/nerdctl/completion.go | 6 ++-- cmd/nerdctl/completion_linux.go | 2 +- cmd/nerdctl/completion_linux_test.go | 2 +- cmd/nerdctl/compose.go | 2 +- cmd/nerdctl/compose_build.go | 6 ++-- cmd/nerdctl/compose_build_linux_test.go | 2 +- cmd/nerdctl/compose_config.go | 6 ++-- cmd/nerdctl/compose_config_test.go | 2 +- cmd/nerdctl/compose_cp.go | 8 ++--- cmd/nerdctl/compose_cp_linux_test.go | 2 +- cmd/nerdctl/compose_create.go | 6 ++-- cmd/nerdctl/compose_create_linux_test.go | 2 +- cmd/nerdctl/compose_down.go | 6 ++-- cmd/nerdctl/compose_down_linux_test.go | 4 +-- cmd/nerdctl/compose_exec.go | 6 ++-- cmd/nerdctl/compose_exec_linux_test.go | 2 +- cmd/nerdctl/compose_images.go | 12 ++++---- cmd/nerdctl/compose_images_linux_test.go | 2 +- cmd/nerdctl/compose_kill.go | 6 ++-- cmd/nerdctl/compose_kill_linux_test.go | 2 +- cmd/nerdctl/compose_logs.go | 6 ++-- cmd/nerdctl/compose_pause.go | 4 +-- cmd/nerdctl/compose_pause_linux_test.go | 2 +- cmd/nerdctl/compose_port.go | 6 ++-- cmd/nerdctl/compose_port_linux_test.go | 2 +- cmd/nerdctl/compose_ps.go | 12 ++++---- cmd/nerdctl/compose_ps_linux_test.go | 4 +-- cmd/nerdctl/compose_pull.go | 6 ++-- cmd/nerdctl/compose_pull_linux_test.go | 2 +- cmd/nerdctl/compose_push.go | 6 ++-- cmd/nerdctl/compose_restart.go | 6 ++-- cmd/nerdctl/compose_restart_linux_test.go | 2 +- cmd/nerdctl/compose_rm.go | 6 ++-- cmd/nerdctl/compose_rm_linux_test.go | 2 +- cmd/nerdctl/compose_run.go | 6 ++-- cmd/nerdctl/compose_run_linux_test.go | 6 ++-- cmd/nerdctl/compose_start.go | 8 ++--- cmd/nerdctl/compose_start_linux_test.go | 2 +- cmd/nerdctl/compose_stop.go | 6 ++-- cmd/nerdctl/compose_stop_linux_test.go | 2 +- cmd/nerdctl/compose_top.go | 12 ++++---- cmd/nerdctl/compose_top_linux_test.go | 6 ++-- cmd/nerdctl/compose_up.go | 6 ++-- cmd/nerdctl/compose_up_linux_test.go | 8 ++--- cmd/nerdctl/compose_up_test.go | 2 +- cmd/nerdctl/compose_version.go | 2 +- cmd/nerdctl/compose_version_test.go | 2 +- cmd/nerdctl/container_attach.go | 8 ++--- cmd/nerdctl/container_attach_linux_test.go | 2 +- cmd/nerdctl/container_commit.go | 6 ++-- cmd/nerdctl/container_commit_test.go | 2 +- cmd/nerdctl/container_cp_linux.go | 8 ++--- cmd/nerdctl/container_cp_linux_test.go | 4 +-- cmd/nerdctl/container_create.go | 8 ++--- cmd/nerdctl/container_create_linux_test.go | 4 +-- cmd/nerdctl/container_create_windows_test.go | 2 +- cmd/nerdctl/container_diff.go | 12 ++++---- cmd/nerdctl/container_diff_linux_test.go | 2 +- cmd/nerdctl/container_exec.go | 6 ++-- cmd/nerdctl/container_exec_linux_test.go | 2 +- cmd/nerdctl/container_exec_test.go | 2 +- cmd/nerdctl/container_inspect.go | 6 ++-- cmd/nerdctl/container_inspect_linux_test.go | 4 +-- cmd/nerdctl/container_inspect_windows_test.go | 2 +- cmd/nerdctl/container_kill.go | 6 ++-- cmd/nerdctl/container_list.go | 8 ++--- cmd/nerdctl/container_list_linux_test.go | 8 ++--- cmd/nerdctl/container_list_test.go | 2 +- cmd/nerdctl/container_list_windows_test.go | 8 ++--- cmd/nerdctl/container_logs.go | 6 ++-- cmd/nerdctl/container_logs_test.go | 2 +- cmd/nerdctl/container_pause.go | 6 ++-- cmd/nerdctl/container_port.go | 6 ++-- cmd/nerdctl/container_prune.go | 6 ++-- cmd/nerdctl/container_prune_linux_test.go | 2 +- cmd/nerdctl/container_remove.go | 6 ++-- cmd/nerdctl/container_remove_linux_test.go | 2 +- cmd/nerdctl/container_remove_windows_test.go | 2 +- cmd/nerdctl/container_rename.go | 6 ++-- cmd/nerdctl/container_rename_linux_test.go | 2 +- cmd/nerdctl/container_rename_windows_test.go | 2 +- cmd/nerdctl/container_restart.go | 6 ++-- cmd/nerdctl/container_restart_linux_test.go | 2 +- cmd/nerdctl/container_run.go | 24 +++++++-------- .../container_run_cgroup_linux_test.go | 4 +-- cmd/nerdctl/container_run_gpus_test.go | 2 +- cmd/nerdctl/container_run_linux_test.go | 6 ++-- .../container_run_log_driver_syslog_test.go | 8 ++--- cmd/nerdctl/container_run_mount_linux_test.go | 4 +-- .../container_run_mount_windows_test.go | 4 +-- cmd/nerdctl/container_run_network.go | 6 ++-- .../container_run_network_base_test.go | 4 +-- .../container_run_network_linux_test.go | 6 ++-- .../container_run_network_windows_test.go | 6 ++-- .../container_run_restart_linux_test.go | 4 +-- .../container_run_runtime_linux_test.go | 2 +- .../container_run_security_linux_test.go | 6 ++-- cmd/nerdctl/container_run_soci_linux_test.go | 2 +- .../container_run_stargz_linux_test.go | 2 +- cmd/nerdctl/container_run_test.go | 2 +- cmd/nerdctl/container_run_user_linux_test.go | 2 +- .../container_run_user_windows_test.go | 2 +- .../container_run_verify_linux_test.go | 4 +-- cmd/nerdctl/container_run_windows_test.go | 2 +- cmd/nerdctl/container_start.go | 8 ++--- cmd/nerdctl/container_start_linux_test.go | 2 +- cmd/nerdctl/container_start_test.go | 2 +- cmd/nerdctl/container_stats.go | 6 ++-- cmd/nerdctl/container_stats_linux_test.go | 6 ++-- cmd/nerdctl/container_stop.go | 6 ++-- cmd/nerdctl/container_stop_linux_test.go | 4 +-- cmd/nerdctl/container_top.go | 10 +++---- cmd/nerdctl/container_top_unix_test.go | 6 ++-- cmd/nerdctl/container_top_windows_test.go | 2 +- cmd/nerdctl/container_unpause.go | 6 ++-- cmd/nerdctl/container_update.go | 12 ++++---- cmd/nerdctl/container_wait.go | 6 ++-- cmd/nerdctl/container_wait_test.go | 2 +- cmd/nerdctl/flagutil.go | 2 +- cmd/nerdctl/image_convert.go | 6 ++-- cmd/nerdctl/image_convert_linux_test.go | 6 ++-- cmd/nerdctl/image_convert_test.go | 2 +- cmd/nerdctl/image_cryptutil.go | 6 ++-- cmd/nerdctl/image_encrypt_linux_test.go | 6 ++-- cmd/nerdctl/image_history.go | 8 ++--- cmd/nerdctl/image_inspect.go | 6 ++-- cmd/nerdctl/image_inspect_test.go | 2 +- cmd/nerdctl/image_list.go | 8 ++--- cmd/nerdctl/image_list_test.go | 4 +-- cmd/nerdctl/image_load.go | 6 ++-- cmd/nerdctl/image_load_linux_test.go | 2 +- cmd/nerdctl/image_prune.go | 6 ++-- cmd/nerdctl/image_prune_test.go | 2 +- cmd/nerdctl/image_pull.go | 8 ++--- cmd/nerdctl/image_pull_linux_test.go | 4 +-- cmd/nerdctl/image_push.go | 6 ++-- cmd/nerdctl/image_push_linux_test.go | 4 +-- cmd/nerdctl/image_remove.go | 6 ++-- cmd/nerdctl/image_remove_linux_test.go | 2 +- cmd/nerdctl/image_save.go | 6 ++-- cmd/nerdctl/image_save_linux_test.go | 2 +- cmd/nerdctl/image_save_test.go | 2 +- cmd/nerdctl/image_tag.go | 6 ++-- cmd/nerdctl/inspect.go | 12 ++++---- cmd/nerdctl/internal_oci_hook.go | 4 +-- cmd/nerdctl/ipfs_build_linux_test.go | 2 +- cmd/nerdctl/ipfs_compose_linux_test.go | 4 +-- cmd/nerdctl/ipfs_linux_test.go | 6 ++-- cmd/nerdctl/ipfs_registry_linux_test.go | 2 +- cmd/nerdctl/ipfs_registry_serve.go | 4 +-- cmd/nerdctl/login.go | 4 +-- cmd/nerdctl/login_linux_test.go | 4 +-- cmd/nerdctl/logout.go | 2 +- cmd/nerdctl/main.go | 12 ++++---- cmd/nerdctl/main_linux.go | 6 ++-- cmd/nerdctl/main_linux_test.go | 2 +- cmd/nerdctl/main_test.go | 2 +- cmd/nerdctl/main_unix.go | 6 ++-- cmd/nerdctl/multi_platform_linux_test.go | 6 ++-- cmd/nerdctl/namespace.go | 4 +-- cmd/nerdctl/namespace_create.go | 6 ++-- cmd/nerdctl/namespace_inspect.go | 6 ++-- cmd/nerdctl/namespace_remove.go | 6 ++-- cmd/nerdctl/namespace_update.go | 6 ++-- cmd/nerdctl/network_create.go | 8 ++--- cmd/nerdctl/network_create_linux_test.go | 2 +- cmd/nerdctl/network_inspect.go | 4 +-- cmd/nerdctl/network_inspect_test.go | 4 +-- cmd/nerdctl/network_list.go | 4 +-- cmd/nerdctl/network_list_linux_test.go | 2 +- cmd/nerdctl/network_prune.go | 6 ++-- cmd/nerdctl/network_prune_linux_test.go | 2 +- cmd/nerdctl/network_remove.go | 8 ++--- cmd/nerdctl/network_remove_linux_test.go | 4 +-- cmd/nerdctl/system_events.go | 6 ++-- cmd/nerdctl/system_info.go | 6 ++-- cmd/nerdctl/system_info_test.go | 6 ++-- cmd/nerdctl/system_prune.go | 6 ++-- cmd/nerdctl/system_prune_linux_test.go | 4 +-- cmd/nerdctl/version.go | 10 +++---- cmd/nerdctl/volume_create.go | 4 +-- cmd/nerdctl/volume_create_test.go | 2 +- cmd/nerdctl/volume_inspect.go | 4 +-- cmd/nerdctl/volume_inspect_test.go | 2 +- cmd/nerdctl/volume_list.go | 6 ++-- cmd/nerdctl/volume_list_test.go | 4 +-- cmd/nerdctl/volume_prune.go | 6 ++-- cmd/nerdctl/volume_prune_linux_test.go | 2 +- cmd/nerdctl/volume_remove.go | 6 ++-- cmd/nerdctl/volume_remove_linux_test.go | 2 +- go.mod | 2 +- hack/verify-pkg-isolation.sh | 2 +- pkg/api/types/global.go | 2 +- pkg/api/types/image_types.go | 2 +- pkg/api/types/network_types.go | 2 +- pkg/buildkitutil/buildkitutil.go | 2 +- pkg/bypass4netnsutil/bypass4netnsutil.go | 2 +- pkg/clientutil/client.go | 4 +-- pkg/cmd/apparmor/inspect_linux.go | 4 +-- pkg/cmd/apparmor/list_linux.go | 6 ++-- pkg/cmd/apparmor/load_linux.go | 2 +- pkg/cmd/apparmor/unload_linux.go | 2 +- pkg/cmd/builder/build.go | 10 +++---- pkg/cmd/builder/prune.go | 4 +-- pkg/cmd/compose/compose.go | 20 ++++++------- pkg/cmd/container/attach.go | 10 +++---- pkg/cmd/container/commit.go | 8 ++--- pkg/cmd/container/cp_linux.go | 6 ++-- pkg/cmd/container/create.go | 30 +++++++++---------- pkg/cmd/container/exec.go | 14 ++++----- pkg/cmd/container/inspect.go | 10 +++---- pkg/cmd/container/kill.go | 6 ++-- pkg/cmd/container/list.go | 10 +++---- pkg/cmd/container/list_util.go | 2 +- pkg/cmd/container/logs.go | 14 ++++----- pkg/cmd/container/pause.go | 6 ++-- pkg/cmd/container/prune.go | 2 +- pkg/cmd/container/remove.go | 16 +++++----- pkg/cmd/container/rename.go | 12 ++++---- pkg/cmd/container/restart.go | 6 ++-- pkg/cmd/container/run_cgroup_freebsd.go | 2 +- pkg/cmd/container/run_cgroup_linux.go | 6 ++-- pkg/cmd/container/run_cgroup_windows.go | 2 +- pkg/cmd/container/run_freebsd.go | 2 +- pkg/cmd/container/run_gpus.go | 2 +- pkg/cmd/container/run_linux.go | 12 ++++---- pkg/cmd/container/run_mount.go | 18 +++++------ pkg/cmd/container/run_restart.go | 2 +- pkg/cmd/container/run_security_linux.go | 8 ++--- pkg/cmd/container/run_ulimit.go | 2 +- pkg/cmd/container/run_windows.go | 2 +- pkg/cmd/container/start.go | 6 ++-- pkg/cmd/container/stats.go | 20 ++++++------- pkg/cmd/container/stats_freebsd.go | 4 +-- pkg/cmd/container/stats_linux.go | 4 +-- pkg/cmd/container/stats_windows.go | 4 +-- pkg/cmd/container/stop.go | 6 ++-- pkg/cmd/container/top.go | 4 +-- pkg/cmd/container/unpause.go | 6 ++-- pkg/cmd/container/wait.go | 4 +-- pkg/cmd/image/convert.go | 10 +++---- pkg/cmd/image/crypt.go | 6 ++-- pkg/cmd/image/inspect.go | 10 +++---- pkg/cmd/image/list.go | 6 ++-- pkg/cmd/image/load.go | 6 ++-- pkg/cmd/image/prune.go | 4 +-- pkg/cmd/image/pull.go | 14 ++++----- pkg/cmd/image/push.go | 18 +++++------ pkg/cmd/image/remove.go | 6 ++-- pkg/cmd/image/save.go | 8 ++--- pkg/cmd/image/tag.go | 6 ++-- pkg/cmd/ipfs/registry_serve.go | 4 +-- pkg/cmd/login/login.go | 6 ++-- pkg/cmd/namespace/create.go | 2 +- pkg/cmd/namespace/inspect.go | 6 ++-- pkg/cmd/namespace/remove.go | 2 +- pkg/cmd/namespace/update.go | 2 +- pkg/cmd/network/create.go | 4 +-- pkg/cmd/network/inspect.go | 12 ++++---- pkg/cmd/network/list.go | 6 ++-- pkg/cmd/network/prune.go | 6 ++-- pkg/cmd/network/remove.go | 6 ++-- pkg/cmd/system/events.go | 4 +-- pkg/cmd/system/info.go | 14 ++++----- pkg/cmd/system/prune.go | 12 ++++---- pkg/cmd/volume/create.go | 8 ++--- pkg/cmd/volume/inspect.go | 4 +-- pkg/cmd/volume/list.go | 6 ++-- pkg/cmd/volume/prune.go | 4 +-- pkg/cmd/volume/rm.go | 8 ++--- pkg/cmd/volume/volume.go | 4 +-- pkg/composer/build.go | 2 +- pkg/composer/composer.go | 4 +-- pkg/composer/container.go | 2 +- pkg/composer/copy.go | 2 +- pkg/composer/create.go | 4 +-- pkg/composer/down.go | 2 +- pkg/composer/exec.go | 4 +-- pkg/composer/logs.go | 6 ++-- pkg/composer/orphans.go | 4 +-- pkg/composer/pause.go | 4 +-- pkg/composer/port.go | 2 +- pkg/composer/pull.go | 2 +- pkg/composer/push.go | 2 +- pkg/composer/restart.go | 2 +- pkg/composer/rm.go | 8 ++--- pkg/composer/run.go | 4 +-- pkg/composer/serviceparser/build.go | 2 +- pkg/composer/serviceparser/build_test.go | 4 +-- pkg/composer/serviceparser/serviceparser.go | 2 +- .../serviceparser/serviceparser_test.go | 6 ++-- pkg/composer/stop.go | 6 ++-- pkg/composer/up.go | 4 +-- pkg/composer/up_network.go | 4 +-- pkg/composer/up_service.go | 4 +-- pkg/composer/up_volume.go | 4 +-- pkg/config/config.go | 2 +- pkg/containerinspector/containerinspector.go | 2 +- .../containerinspector_freebsd.go | 2 +- .../containerinspector_linux.go | 2 +- .../containerinspector_windows.go | 2 +- pkg/containerutil/config.go | 4 +-- .../container_network_manager.go | 18 +++++------ .../container_network_manager_linux.go | 14 ++++----- .../container_network_manager_other.go | 2 +- .../container_network_manager_windows.go | 6 ++-- pkg/containerutil/containerutil.go | 18 +++++------ pkg/containerutil/cp_linux.go | 4 +-- pkg/defaults/cgroup_linux.go | 2 +- pkg/defaults/defaults_linux.go | 2 +- pkg/dnsutil/dnsutil.go | 2 +- pkg/dnsutil/hostsstore/hostsstore.go | 2 +- pkg/dnsutil/hostsstore/updater.go | 2 +- pkg/flagutil/flagutil.go | 2 +- pkg/formatter/formatter.go | 2 +- pkg/idutil/containerwalker/containerwalker.go | 2 +- pkg/idutil/imagewalker/imagewalker.go | 2 +- pkg/idutil/netwalker/netwalker.go | 2 +- pkg/imageinspector/imageinspector.go | 4 +-- pkg/imgutil/commit/commit.go | 4 +-- pkg/imgutil/converter/zstd.go | 2 +- pkg/imgutil/filtering.go | 2 +- pkg/imgutil/imgutil.go | 8 ++--- pkg/imgutil/pull/pull.go | 4 +-- pkg/imgutil/push/push.go | 2 +- pkg/imgutil/snapshotter.go | 2 +- pkg/imgutil/snapshotter_test.go | 2 +- pkg/infoutil/infoutil.go | 10 +++---- pkg/infoutil/infoutil_freebsd.go | 2 +- pkg/infoutil/infoutil_linux.go | 8 ++--- pkg/infoutil/infoutil_test.go | 2 +- pkg/infoutil/infoutil_windows.go | 2 +- pkg/inspecttypes/dockercompat/dockercompat.go | 6 ++-- pkg/ipfs/image.go | 8 ++--- pkg/logging/cri_logger.go | 2 +- pkg/logging/fluentd_logger.go | 2 +- pkg/logging/journald_logger.go | 2 +- pkg/logging/json_logger.go | 4 +-- pkg/logging/log_viewer.go | 2 +- pkg/logging/syslog_logger.go | 2 +- pkg/mountutil/mountutil.go | 6 ++-- pkg/mountutil/mountutil_freebsd.go | 2 +- pkg/mountutil/mountutil_linux.go | 2 +- pkg/mountutil/mountutil_linux_test.go | 4 +-- pkg/mountutil/mountutil_other.go | 2 +- pkg/mountutil/mountutil_windows.go | 2 +- pkg/mountutil/mountutil_windows_test.go | 4 +-- .../mountutilmock/volumestore.mock.go | 2 +- pkg/mountutil/volumestore/volumestore.go | 6 ++-- pkg/namestore/namestore.go | 2 +- pkg/netutil/netutil.go | 10 +++---- pkg/netutil/netutil_linux_test.go | 2 +- pkg/netutil/netutil_test.go | 6 ++-- pkg/netutil/netutil_unix.go | 6 ++-- pkg/nsutil/nsutil_test.go | 2 +- pkg/ocihook/ocihook.go | 14 ++++----- pkg/ocihook/ocihook_linux.go | 4 +-- pkg/ocihook/rootless_linux.go | 2 +- pkg/platformutil/platformutil.go | 2 +- pkg/portutil/port_allocate_linux.go | 4 +-- pkg/portutil/portutil.go | 4 +-- pkg/portutil/portutil_test.go | 4 +-- pkg/signutil/cosignutil.go | 2 +- pkg/signutil/notationutil.go | 2 +- pkg/signutil/signutil.go | 2 +- pkg/snapshotterutil/sociutil.go | 2 +- pkg/taskutil/taskutil.go | 6 ++-- .../testregistry/testregistry_linux.go | 6 ++-- pkg/testutil/testsyslog/testsyslog.go | 4 +-- pkg/testutil/testutil.go | 14 ++++----- pkg/testutil/testutil_windows.go | 2 +- 382 files changed, 954 insertions(+), 954 deletions(-) diff --git a/Dockerfile b/Dockerfile index c36a5ac26f5..bff4e86274b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -312,7 +312,7 @@ RUN curl -L -o nydus-static.tgz "https://github.com/dragonflyoss/image-service/r tar xzf nydus-static.tgz && \ mv nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/bin/ && \ rm nydus-static.tgz -CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/cmd/nerdctl/...", \ +CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/v2/cmd/nerdctl/...", \ "--", "-timeout=30m", "-args", "-test.kill-daemon"] FROM test-integration AS test-integration-rootless @@ -338,7 +338,7 @@ RUN go test -o /usr/local/bin/nerdctl.test -c ./cmd/nerdctl COPY ./Dockerfile.d/test-integration-rootless.sh / CMD ["/test-integration-rootless.sh", \ "gotestsum", "--format=testname", "--rerun-fails=2", "--raw-command", \ - "--", "/usr/local/go/bin/go", "tool", "test2json", "-t", "-p", "github.com/containerd/nerdctl/cmd/nerdctl", \ + "--", "/usr/local/go/bin/go", "tool", "test2json", "-t", "-p", "github.com/containerd/nerdctl/v2/cmd/nerdctl", \ "/usr/local/bin/nerdctl.test", "-test.v", "-test.timeout=30m", "-test.kill-daemon"] # test for CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=slirp4netns @@ -347,7 +347,7 @@ COPY ./Dockerfile.d/home_rootless_.config_systemd_user_containerd.service.d_port RUN chown -R rootless:rootless /home/rootless/.config FROM test-integration AS test-integration-ipv6 -CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/cmd/nerdctl/...", \ +CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/v2/cmd/nerdctl/...", \ "--", "-timeout=30m", "-args", "-test.kill-daemon", "-test.ipv6"] FROM base AS demo diff --git a/Makefile b/Makefile index 8978d22b149..844ae7213bd 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ ifeq ($(GOOS),windows) BIN_EXT := .exe endif -PACKAGE := github.com/containerd/nerdctl +PACKAGE := github.com/containerd/nerdctl/v2 # distro builders might wanna override these PREFIX ?= /usr/local diff --git a/README.md b/README.md index 4d1ceb02ab6..98e7a3d9b33 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ Run `make && sudo make install`. See the header of [`go.mod`](./go.mod) for the minimum supported version of Go. -Using `go install github.com/containerd/nerdctl/cmd/nerdctl` is possible, but unrecommended because it does not fill version strings printed in `nerdctl version` +Using `go install github.com/containerd/nerdctl/v2/cmd/nerdctl` is possible, but unrecommended because it does not fill version strings printed in `nerdctl version` ### Test suite diff --git a/cmd/nerdctl/apparmor_inspect_linux.go b/cmd/nerdctl/apparmor_inspect_linux.go index 0071a22a824..18a4e3afd00 100644 --- a/cmd/nerdctl/apparmor_inspect_linux.go +++ b/cmd/nerdctl/apparmor_inspect_linux.go @@ -19,10 +19,10 @@ package main import ( "fmt" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/apparmor" - "github.com/containerd/nerdctl/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/cmd/apparmor" + "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/apparmor_list_linux.go b/cmd/nerdctl/apparmor_list_linux.go index aa0073b048e..99cc8eb5aa6 100644 --- a/cmd/nerdctl/apparmor_list_linux.go +++ b/cmd/nerdctl/apparmor_list_linux.go @@ -17,8 +17,8 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/apparmor" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/apparmor" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/apparmor_load_linux.go b/cmd/nerdctl/apparmor_load_linux.go index 38b7547242b..a7e25c3f71e 100644 --- a/cmd/nerdctl/apparmor_load_linux.go +++ b/cmd/nerdctl/apparmor_load_linux.go @@ -19,8 +19,8 @@ package main import ( "fmt" - "github.com/containerd/nerdctl/pkg/cmd/apparmor" - "github.com/containerd/nerdctl/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/cmd/apparmor" + "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/apparmor_unload_linux.go b/cmd/nerdctl/apparmor_unload_linux.go index 92fc289eb31..1fb5c840c4a 100644 --- a/cmd/nerdctl/apparmor_unload_linux.go +++ b/cmd/nerdctl/apparmor_unload_linux.go @@ -19,8 +19,8 @@ package main import ( "fmt" - "github.com/containerd/nerdctl/pkg/cmd/apparmor" - "github.com/containerd/nerdctl/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/cmd/apparmor" + "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index 5b8357c2fa2..595c068cfc3 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -23,8 +23,8 @@ import ( "strings" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/buildkitutil" - "github.com/containerd/nerdctl/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index a74d3876e9a..a4d159791ac 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -22,12 +22,12 @@ import ( "os" "strings" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/buildkitutil" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/builder" - "github.com/containerd/nerdctl/pkg/defaults" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/builder" + "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index 2341c850019..0091a7b6f2f 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -23,7 +23,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/builder_linux_test.go b/cmd/nerdctl/builder_linux_test.go index 5376698242d..bdf1cc402d5 100644 --- a/cmd/nerdctl/builder_linux_test.go +++ b/cmd/nerdctl/builder_linux_test.go @@ -22,7 +22,7 @@ import ( "os" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/completion.go b/cmd/nerdctl/completion.go index aefc30b45da..15dd83a3260 100644 --- a/cmd/nerdctl/completion.go +++ b/cmd/nerdctl/completion.go @@ -21,9 +21,9 @@ import ( "time" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/completion_linux.go b/cmd/nerdctl/completion_linux.go index e89d5e40960..52baa8b974a 100644 --- a/cmd/nerdctl/completion_linux.go +++ b/cmd/nerdctl/completion_linux.go @@ -17,7 +17,7 @@ package main import ( - "github.com/containerd/nerdctl/pkg/apparmorutil" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/completion_linux_test.go b/cmd/nerdctl/completion_linux_test.go index 20b95f7f412..0cde9191ee3 100644 --- a/cmd/nerdctl/completion_linux_test.go +++ b/cmd/nerdctl/completion_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestCompletion(t *testing.T) { diff --git a/cmd/nerdctl/compose.go b/cmd/nerdctl/compose.go index 863ce44d59c..c64e719d4db 100644 --- a/cmd/nerdctl/compose.go +++ b/cmd/nerdctl/compose.go @@ -17,7 +17,7 @@ package main import ( - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_build.go b/cmd/nerdctl/compose_build.go index be59dbad7b7..9a001af2c57 100644 --- a/cmd/nerdctl/compose_build.go +++ b/cmd/nerdctl/compose_build.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_build_linux_test.go b/cmd/nerdctl/compose_build_linux_test.go index e80bdd7895f..9e5cfbecc53 100644 --- a/cmd/nerdctl/compose_build_linux_test.go +++ b/cmd/nerdctl/compose_build_linux_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeBuild(t *testing.T) { diff --git a/cmd/nerdctl/compose_config.go b/cmd/nerdctl/compose_config.go index 90c506ce092..5a2b0be9820 100644 --- a/cmd/nerdctl/compose_config.go +++ b/cmd/nerdctl/compose_config.go @@ -19,9 +19,9 @@ package main import ( "fmt" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_config_test.go b/cmd/nerdctl/compose_config_test.go index 29d371e98e4..d2af27b5832 100644 --- a/cmd/nerdctl/compose_config_test.go +++ b/cmd/nerdctl/compose_config_test.go @@ -22,7 +22,7 @@ import ( "path/filepath" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/compose_cp.go b/cmd/nerdctl/compose_cp.go index 252b9e1c261..859ebb4f85e 100644 --- a/cmd/nerdctl/compose_cp.go +++ b/cmd/nerdctl/compose_cp.go @@ -19,10 +19,10 @@ package main import ( "errors" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_cp_linux_test.go b/cmd/nerdctl/compose_cp_linux_test.go index 8c65752db2c..46174e685e5 100644 --- a/cmd/nerdctl/compose_cp_linux_test.go +++ b/cmd/nerdctl/compose_cp_linux_test.go @@ -22,7 +22,7 @@ import ( "path/filepath" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/compose_create.go b/cmd/nerdctl/compose_create.go index 7b60ed8dc98..14c757aaab8 100644 --- a/cmd/nerdctl/compose_create.go +++ b/cmd/nerdctl/compose_create.go @@ -19,9 +19,9 @@ package main import ( "errors" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_create_linux_test.go b/cmd/nerdctl/compose_create_linux_test.go index 82d2ed50542..829e3ebded5 100644 --- a/cmd/nerdctl/compose_create_linux_test.go +++ b/cmd/nerdctl/compose_create_linux_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeCreate(t *testing.T) { diff --git a/cmd/nerdctl/compose_down.go b/cmd/nerdctl/compose_down.go index 236f96fd61a..19a5fe52bd6 100644 --- a/cmd/nerdctl/compose_down.go +++ b/cmd/nerdctl/compose_down.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_down_linux_test.go b/cmd/nerdctl/compose_down_linux_test.go index 583e2c98c61..7b8a393b523 100644 --- a/cmd/nerdctl/compose_down_linux_test.go +++ b/cmd/nerdctl/compose_down_linux_test.go @@ -21,8 +21,8 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeDownRemoveUsedNetwork(t *testing.T) { diff --git a/cmd/nerdctl/compose_exec.go b/cmd/nerdctl/compose_exec.go index 7f0ba6017bb..dee9ae91612 100644 --- a/cmd/nerdctl/compose_exec.go +++ b/cmd/nerdctl/compose_exec.go @@ -19,9 +19,9 @@ package main import ( "errors" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_exec_linux_test.go b/cmd/nerdctl/compose_exec_linux_test.go index f12dc530fa2..26d9f07738c 100644 --- a/cmd/nerdctl/compose_exec_linux_test.go +++ b/cmd/nerdctl/compose_exec_linux_test.go @@ -25,7 +25,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/compose_images.go b/cmd/nerdctl/compose_images.go index 36816769a0f..80ef81855eb 100644 --- a/cmd/nerdctl/compose_images.go +++ b/cmd/nerdctl/compose_images.go @@ -25,12 +25,12 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/pkg/progress" "github.com/containerd/containerd/snapshots" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" ) diff --git a/cmd/nerdctl/compose_images_linux_test.go b/cmd/nerdctl/compose_images_linux_test.go index b10b18309ad..dd4ae118b72 100644 --- a/cmd/nerdctl/compose_images_linux_test.go +++ b/cmd/nerdctl/compose_images_linux_test.go @@ -22,7 +22,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeImages(t *testing.T) { diff --git a/cmd/nerdctl/compose_kill.go b/cmd/nerdctl/compose_kill.go index 1e483273ff1..5a7cee00917 100644 --- a/cmd/nerdctl/compose_kill.go +++ b/cmd/nerdctl/compose_kill.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_kill_linux_test.go b/cmd/nerdctl/compose_kill_linux_test.go index 3a1d138bed3..59e95519636 100644 --- a/cmd/nerdctl/compose_kill_linux_test.go +++ b/cmd/nerdctl/compose_kill_linux_test.go @@ -21,7 +21,7 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeKill(t *testing.T) { diff --git a/cmd/nerdctl/compose_logs.go b/cmd/nerdctl/compose_logs.go index 79902f7bad2..46bd2df7203 100644 --- a/cmd/nerdctl/compose_logs.go +++ b/cmd/nerdctl/compose_logs.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_pause.go b/cmd/nerdctl/compose_pause.go index 429b7d853b0..7cf24cfb78b 100644 --- a/cmd/nerdctl/compose_pause.go +++ b/cmd/nerdctl/compose_pause.go @@ -17,8 +17,8 @@ package main import ( - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_pause_linux_test.go b/cmd/nerdctl/compose_pause_linux_test.go index e6fe615ec4d..34c259734c6 100644 --- a/cmd/nerdctl/compose_pause_linux_test.go +++ b/cmd/nerdctl/compose_pause_linux_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposePauseAndUnpause(t *testing.T) { diff --git a/cmd/nerdctl/compose_port.go b/cmd/nerdctl/compose_port.go index 92c3ea3189a..2156bd917e4 100644 --- a/cmd/nerdctl/compose_port.go +++ b/cmd/nerdctl/compose_port.go @@ -20,9 +20,9 @@ import ( "fmt" "strconv" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_port_linux_test.go b/cmd/nerdctl/compose_port_linux_test.go index 991ac6c847a..39eff5c00a9 100644 --- a/cmd/nerdctl/compose_port_linux_test.go +++ b/cmd/nerdctl/compose_port_linux_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposePort(t *testing.T) { diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose_ps.go index e9e569584fb..8d7d54e1b21 100644 --- a/cmd/nerdctl/compose_ps.go +++ b/cmd/nerdctl/compose_ps.go @@ -28,12 +28,12 @@ import ( "github.com/containerd/containerd/runtime/restart" gocni "github.com/containerd/go-cni" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/portutil" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/portutil" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" ) diff --git a/cmd/nerdctl/compose_ps_linux_test.go b/cmd/nerdctl/compose_ps_linux_test.go index 453829bbba4..55e0b5a756e 100644 --- a/cmd/nerdctl/compose_ps_linux_test.go +++ b/cmd/nerdctl/compose_ps_linux_test.go @@ -23,8 +23,8 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/tabutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/tabutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/compose_pull.go b/cmd/nerdctl/compose_pull.go index 9d004353fc5..babe2e65752 100644 --- a/cmd/nerdctl/compose_pull.go +++ b/cmd/nerdctl/compose_pull.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_pull_linux_test.go b/cmd/nerdctl/compose_pull_linux_test.go index d350892f1b3..4e86b053194 100644 --- a/cmd/nerdctl/compose_pull_linux_test.go +++ b/cmd/nerdctl/compose_pull_linux_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposePullWithService(t *testing.T) { diff --git a/cmd/nerdctl/compose_push.go b/cmd/nerdctl/compose_push.go index 2c899dabf39..bfdf02a9d4e 100644 --- a/cmd/nerdctl/compose_push.go +++ b/cmd/nerdctl/compose_push.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_restart.go b/cmd/nerdctl/compose_restart.go index adb47e3dee4..46ba6d31887 100644 --- a/cmd/nerdctl/compose_restart.go +++ b/cmd/nerdctl/compose_restart.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_restart_linux_test.go b/cmd/nerdctl/compose_restart_linux_test.go index ed1d2bd1466..4b16f136215 100644 --- a/cmd/nerdctl/compose_restart_linux_test.go +++ b/cmd/nerdctl/compose_restart_linux_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeRestart(t *testing.T) { diff --git a/cmd/nerdctl/compose_rm.go b/cmd/nerdctl/compose_rm.go index 6ac686f6b86..536b919890b 100644 --- a/cmd/nerdctl/compose_rm.go +++ b/cmd/nerdctl/compose_rm.go @@ -20,9 +20,9 @@ import ( "fmt" "strings" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_rm_linux_test.go b/cmd/nerdctl/compose_rm_linux_test.go index a699274883d..22ce6f5a487 100644 --- a/cmd/nerdctl/compose_rm_linux_test.go +++ b/cmd/nerdctl/compose_rm_linux_test.go @@ -21,7 +21,7 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeRemove(t *testing.T) { diff --git a/cmd/nerdctl/compose_run.go b/cmd/nerdctl/compose_run.go index c92c5ab1ae9..0cfe5cfd535 100644 --- a/cmd/nerdctl/compose_run.go +++ b/cmd/nerdctl/compose_run.go @@ -20,9 +20,9 @@ import ( "errors" "fmt" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_run_linux_test.go b/cmd/nerdctl/compose_run_linux_test.go index f0778e74e82..ea075f4e9d9 100644 --- a/cmd/nerdctl/compose_run_linux_test.go +++ b/cmd/nerdctl/compose_run_linux_test.go @@ -24,9 +24,9 @@ import ( "time" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/nettestutil" - "github.com/containerd/nerdctl/pkg/testutil/testregistry" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/compose_start.go b/cmd/nerdctl/compose_start.go index a5889b18aaa..0268ab4569b 100644 --- a/cmd/nerdctl/compose_start.go +++ b/cmd/nerdctl/compose_start.go @@ -23,10 +23,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" ) diff --git a/cmd/nerdctl/compose_start_linux_test.go b/cmd/nerdctl/compose_start_linux_test.go index 2a156052408..79ce8c990a8 100644 --- a/cmd/nerdctl/compose_start_linux_test.go +++ b/cmd/nerdctl/compose_start_linux_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeStart(t *testing.T) { diff --git a/cmd/nerdctl/compose_stop.go b/cmd/nerdctl/compose_stop.go index b35d4911143..ab6053d1d5a 100644 --- a/cmd/nerdctl/compose_stop.go +++ b/cmd/nerdctl/compose_stop.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_stop_linux_test.go b/cmd/nerdctl/compose_stop_linux_test.go index d618894ab33..dcb1250e8a5 100644 --- a/cmd/nerdctl/compose_stop_linux_test.go +++ b/cmd/nerdctl/compose_stop_linux_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeStop(t *testing.T) { diff --git a/cmd/nerdctl/compose_top.go b/cmd/nerdctl/compose_top.go index 54aa9ce2b41..52ea6a71800 100644 --- a/cmd/nerdctl/compose_top.go +++ b/cmd/nerdctl/compose_top.go @@ -20,12 +20,12 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_top_linux_test.go b/cmd/nerdctl/compose_top_linux_test.go index 38a94fa84e9..09c01062f03 100644 --- a/cmd/nerdctl/compose_top_linux_test.go +++ b/cmd/nerdctl/compose_top_linux_test.go @@ -20,9 +20,9 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeTop(t *testing.T) { diff --git a/cmd/nerdctl/compose_up.go b/cmd/nerdctl/compose_up.go index 019bb795d10..4fe07ae11d7 100644 --- a/cmd/nerdctl/compose_up.go +++ b/cmd/nerdctl/compose_up.go @@ -22,9 +22,9 @@ import ( "strconv" "strings" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/compose" - "github.com/containerd/nerdctl/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/compose" + "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_up_linux_test.go b/cmd/nerdctl/compose_up_linux_test.go index 481bbc5b16e..0580e10b28d 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/cmd/nerdctl/compose_up_linux_test.go @@ -25,12 +25,12 @@ import ( "time" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/docker/go-connections/nat" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/compose_up_test.go b/cmd/nerdctl/compose_up_test.go index 308993ff124..8431ab4ece6 100644 --- a/cmd/nerdctl/compose_up_test.go +++ b/cmd/nerdctl/compose_up_test.go @@ -23,7 +23,7 @@ import ( "runtime" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" ) diff --git a/cmd/nerdctl/compose_version.go b/cmd/nerdctl/compose_version.go index 99a73274876..0382300ea02 100644 --- a/cmd/nerdctl/compose_version.go +++ b/cmd/nerdctl/compose_version.go @@ -20,7 +20,7 @@ import ( "fmt" "strings" - "github.com/containerd/nerdctl/pkg/version" + "github.com/containerd/nerdctl/v2/pkg/version" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/compose_version_test.go b/cmd/nerdctl/compose_version_test.go index 2f3354745f3..222d41edd4d 100644 --- a/cmd/nerdctl/compose_version_test.go +++ b/cmd/nerdctl/compose_version_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeVersion(t *testing.T) { diff --git a/cmd/nerdctl/container_attach.go b/cmd/nerdctl/container_attach.go index 8a18be23918..4c8067322ae 100644 --- a/cmd/nerdctl/container_attach.go +++ b/cmd/nerdctl/container_attach.go @@ -18,10 +18,10 @@ package main import ( "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/consoleutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/consoleutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_attach_linux_test.go b/cmd/nerdctl/container_attach_linux_test.go index c1ab1356cb0..84a774c7e4a 100644 --- a/cmd/nerdctl/container_attach_linux_test.go +++ b/cmd/nerdctl/container_attach_linux_test.go @@ -21,7 +21,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_commit.go b/cmd/nerdctl/container_commit.go index ad09be63e37..2b56c1de641 100644 --- a/cmd/nerdctl/container_commit.go +++ b/cmd/nerdctl/container_commit.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_commit_test.go b/cmd/nerdctl/container_commit_test.go index c48209f1d24..b569ebfbcc2 100644 --- a/cmd/nerdctl/container_commit_test.go +++ b/cmd/nerdctl/container_commit_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestCommit(t *testing.T) { diff --git a/cmd/nerdctl/container_cp_linux.go b/cmd/nerdctl/container_cp_linux.go index f3f994794b5..9f38c394af7 100644 --- a/cmd/nerdctl/container_cp_linux.go +++ b/cmd/nerdctl/container_cp_linux.go @@ -19,10 +19,10 @@ package main import ( "fmt" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_cp_linux_test.go b/cmd/nerdctl/container_cp_linux_test.go index b71d694c838..807ea0f0619 100644 --- a/cmd/nerdctl/container_cp_linux_test.go +++ b/cmd/nerdctl/container_cp_linux_test.go @@ -24,8 +24,8 @@ import ( "syscall" "testing" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_create.go b/cmd/nerdctl/container_create.go index 60b7de34d3a..f196e02cb05 100644 --- a/cmd/nerdctl/container_create.go +++ b/cmd/nerdctl/container_create.go @@ -20,10 +20,10 @@ import ( "fmt" "runtime" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_create_linux_test.go b/cmd/nerdctl/container_create_linux_test.go index 403d463de8d..8a66c781c4a 100644 --- a/cmd/nerdctl/container_create_linux_test.go +++ b/cmd/nerdctl/container_create_linux_test.go @@ -21,8 +21,8 @@ import ( "runtime" "testing" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_create_windows_test.go b/cmd/nerdctl/container_create_windows_test.go index 643fce767b9..f52cda49819 100644 --- a/cmd/nerdctl/container_create_windows_test.go +++ b/cmd/nerdctl/container_create_windows_test.go @@ -20,7 +20,7 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestCreateProcessContainer(t *testing.T) { diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index 48db2be7891..d5eb238fbf1 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -29,12 +29,12 @@ import ( "github.com/containerd/containerd/platforms" "github.com/containerd/continuity/fs" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/idgen" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/idgen" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/opencontainers/image-spec/identity" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_diff_linux_test.go b/cmd/nerdctl/container_diff_linux_test.go index 7fd2c9ce71c..e74ba025333 100644 --- a/cmd/nerdctl/container_diff_linux_test.go +++ b/cmd/nerdctl/container_diff_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestDiff(t *testing.T) { diff --git a/cmd/nerdctl/container_exec.go b/cmd/nerdctl/container_exec.go index 6b3447cd94b..751c3915190 100644 --- a/cmd/nerdctl/container_exec.go +++ b/cmd/nerdctl/container_exec.go @@ -20,9 +20,9 @@ import ( "errors" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_exec_linux_test.go b/cmd/nerdctl/container_exec_linux_test.go index 37ffcb69d06..38c9a793d49 100644 --- a/cmd/nerdctl/container_exec_linux_test.go +++ b/cmd/nerdctl/container_exec_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestExecWithUser(t *testing.T) { diff --git a/cmd/nerdctl/container_exec_test.go b/cmd/nerdctl/container_exec_test.go index b96cc74756a..bcd1b41abe9 100644 --- a/cmd/nerdctl/container_exec_test.go +++ b/cmd/nerdctl/container_exec_test.go @@ -23,7 +23,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestExec(t *testing.T) { diff --git a/cmd/nerdctl/container_inspect.go b/cmd/nerdctl/container_inspect.go index 0124a93dcda..7fe6dd4435c 100644 --- a/cmd/nerdctl/container_inspect.go +++ b/cmd/nerdctl/container_inspect.go @@ -19,9 +19,9 @@ package main import ( "fmt" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_inspect_linux_test.go b/cmd/nerdctl/container_inspect_linux_test.go index 6eb0ba9b2f1..7c1cc721543 100644 --- a/cmd/nerdctl/container_inspect_linux_test.go +++ b/cmd/nerdctl/container_inspect_linux_test.go @@ -21,8 +21,8 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/docker/go-connections/nat" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_inspect_windows_test.go b/cmd/nerdctl/container_inspect_windows_test.go index 5ba9adbb08a..bc5cf33278b 100644 --- a/cmd/nerdctl/container_inspect_windows_test.go +++ b/cmd/nerdctl/container_inspect_windows_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_kill.go b/cmd/nerdctl/container_kill.go index fdf8e488c72..fe0e26ca501 100644 --- a/cmd/nerdctl/container_kill.go +++ b/cmd/nerdctl/container_kill.go @@ -18,9 +18,9 @@ package main import ( "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container_list.go index be2aaaae831..549df18ca08 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container_list.go @@ -24,10 +24,10 @@ import ( "text/tabwriter" "text/template" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_list_linux_test.go b/cmd/nerdctl/container_list_linux_test.go index 109e7f9469d..ea48531487c 100644 --- a/cmd/nerdctl/container_list_linux_test.go +++ b/cmd/nerdctl/container_list_linux_test.go @@ -23,10 +23,10 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/strutil" - "github.com/containerd/nerdctl/pkg/tabutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/tabutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_list_test.go b/cmd/nerdctl/container_list_test.go index 7ec299b62ed..9b48b67ef47 100644 --- a/cmd/nerdctl/container_list_test.go +++ b/cmd/nerdctl/container_list_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) // https://github.com/containerd/nerdctl/issues/2598 diff --git a/cmd/nerdctl/container_list_windows_test.go b/cmd/nerdctl/container_list_windows_test.go index e655a6cd1b3..5efbac82da3 100644 --- a/cmd/nerdctl/container_list_windows_test.go +++ b/cmd/nerdctl/container_list_windows_test.go @@ -21,10 +21,10 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/strutil" - "github.com/containerd/nerdctl/pkg/tabutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/tabutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_logs.go b/cmd/nerdctl/container_logs.go index 7ec46f80ccc..27e5dec0250 100644 --- a/cmd/nerdctl/container_logs.go +++ b/cmd/nerdctl/container_logs.go @@ -20,9 +20,9 @@ import ( "fmt" "strconv" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_logs_test.go b/cmd/nerdctl/container_logs_test.go index 66b0dc2ee81..b14824f84ad 100644 --- a/cmd/nerdctl/container_logs_test.go +++ b/cmd/nerdctl/container_logs_test.go @@ -23,7 +23,7 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestLogs(t *testing.T) { diff --git a/cmd/nerdctl/container_pause.go b/cmd/nerdctl/container_pause.go index 8e4f0c85f2f..bf8cf4f0107 100644 --- a/cmd/nerdctl/container_pause.go +++ b/cmd/nerdctl/container_pause.go @@ -18,9 +18,9 @@ package main import ( "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_port.go b/cmd/nerdctl/container_port.go index e2fb467f000..072df21ba25 100644 --- a/cmd/nerdctl/container_port.go +++ b/cmd/nerdctl/container_port.go @@ -22,9 +22,9 @@ import ( "strconv" "strings" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_prune.go b/cmd/nerdctl/container_prune.go index dc02b5a316b..1d1e19afa6d 100644 --- a/cmd/nerdctl/container_prune.go +++ b/cmd/nerdctl/container_prune.go @@ -20,9 +20,9 @@ import ( "fmt" "strings" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_prune_linux_test.go b/cmd/nerdctl/container_prune_linux_test.go index bfcda034719..0aec844714f 100644 --- a/cmd/nerdctl/container_prune_linux_test.go +++ b/cmd/nerdctl/container_prune_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestPruneContainer(t *testing.T) { diff --git a/cmd/nerdctl/container_remove.go b/cmd/nerdctl/container_remove.go index b6c0d39d472..05a7e059e38 100644 --- a/cmd/nerdctl/container_remove.go +++ b/cmd/nerdctl/container_remove.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_remove_linux_test.go b/cmd/nerdctl/container_remove_linux_test.go index 3020dfc42f4..71a060f2d41 100644 --- a/cmd/nerdctl/container_remove_linux_test.go +++ b/cmd/nerdctl/container_remove_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRemoveContainer(t *testing.T) { diff --git a/cmd/nerdctl/container_remove_windows_test.go b/cmd/nerdctl/container_remove_windows_test.go index 07ed0b44dd3..a93573c5ca5 100644 --- a/cmd/nerdctl/container_remove_windows_test.go +++ b/cmd/nerdctl/container_remove_windows_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_rename.go b/cmd/nerdctl/container_rename.go index 2f1d482a6c1..6e5857117e6 100644 --- a/cmd/nerdctl/container_rename.go +++ b/cmd/nerdctl/container_rename.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_rename_linux_test.go b/cmd/nerdctl/container_rename_linux_test.go index b082514fe1c..ae48b82f84f 100644 --- a/cmd/nerdctl/container_rename_linux_test.go +++ b/cmd/nerdctl/container_rename_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRename(t *testing.T) { diff --git a/cmd/nerdctl/container_rename_windows_test.go b/cmd/nerdctl/container_rename_windows_test.go index 38d78cd5473..698f6bf004f 100644 --- a/cmd/nerdctl/container_rename_windows_test.go +++ b/cmd/nerdctl/container_rename_windows_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRenameProcessContainer(t *testing.T) { diff --git a/cmd/nerdctl/container_restart.go b/cmd/nerdctl/container_restart.go index ae1b8d3d1e3..906c7ff6486 100644 --- a/cmd/nerdctl/container_restart.go +++ b/cmd/nerdctl/container_restart.go @@ -19,9 +19,9 @@ package main import ( "time" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_restart_linux_test.go b/cmd/nerdctl/container_restart_linux_test.go index 669d94d6640..374debc1d83 100644 --- a/cmd/nerdctl/container_restart_linux_test.go +++ b/cmd/nerdctl/container_restart_linux_test.go @@ -22,7 +22,7 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index c1684e17e7a..5d74b627680 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -23,18 +23,18 @@ import ( "github.com/containerd/console" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/consoleutil" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/defaults" - "github.com/containerd/nerdctl/pkg/errutil" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/logging" - "github.com/containerd/nerdctl/pkg/netutil" - "github.com/containerd/nerdctl/pkg/signalutil" - "github.com/containerd/nerdctl/pkg/taskutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/consoleutil" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/errutil" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/logging" + "github.com/containerd/nerdctl/v2/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/signalutil" + "github.com/containerd/nerdctl/v2/pkg/taskutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_run_cgroup_linux_test.go b/cmd/nerdctl/container_run_cgroup_linux_test.go index 0301ae58e66..16e0b0acdbf 100644 --- a/cmd/nerdctl/container_run_cgroup_linux_test.go +++ b/cmd/nerdctl/container_run_cgroup_linux_test.go @@ -26,8 +26,8 @@ import ( "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/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_run_gpus_test.go b/cmd/nerdctl/container_run_gpus_test.go index b9961aeccb5..392a978d618 100644 --- a/cmd/nerdctl/container_run_gpus_test.go +++ b/cmd/nerdctl/container_run_gpus_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) diff --git a/cmd/nerdctl/container_run_linux_test.go b/cmd/nerdctl/container_run_linux_test.go index 678ea108d46..e5b519c709f 100644 --- a/cmd/nerdctl/container_run_linux_test.go +++ b/cmd/nerdctl/container_run_linux_test.go @@ -32,9 +32,9 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/strutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" ) diff --git a/cmd/nerdctl/container_run_log_driver_syslog_test.go b/cmd/nerdctl/container_run_log_driver_syslog_test.go index a46f8f8936b..ca0ea993e7c 100644 --- a/cmd/nerdctl/container_run_log_driver_syslog_test.go +++ b/cmd/nerdctl/container_run_log_driver_syslog_test.go @@ -25,10 +25,10 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/testca" - "github.com/containerd/nerdctl/pkg/testutil/testsyslog" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testca" + "github.com/containerd/nerdctl/v2/pkg/testutil/testsyslog" syslog "github.com/yuchanns/srslog" ) diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container_run_mount_linux_test.go index 19793c97340..55527bf0ae7 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container_run_mount_linux_test.go @@ -24,8 +24,8 @@ import ( "testing" "github.com/containerd/containerd/mount" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" mobymount "github.com/moby/sys/mount" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_run_mount_windows_test.go b/cmd/nerdctl/container_run_mount_windows_test.go index a560151b74c..7c84bd17f15 100644 --- a/cmd/nerdctl/container_run_mount_windows_test.go +++ b/cmd/nerdctl/container_run_mount_windows_test.go @@ -21,8 +21,8 @@ import ( "os" "testing" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_run_network.go b/cmd/nerdctl/container_run_network.go index e2d25a047e0..64822221d4e 100644 --- a/cmd/nerdctl/container_run_network.go +++ b/cmd/nerdctl/container_run_network.go @@ -20,9 +20,9 @@ import ( "net" gocni "github.com/containerd/go-cni" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/portutil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/portutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_run_network_base_test.go b/cmd/nerdctl/container_run_network_base_test.go index d1cbfccc149..f072ac34ecb 100644 --- a/cmd/nerdctl/container_run_network_base_test.go +++ b/cmd/nerdctl/container_run_network_base_test.go @@ -26,8 +26,8 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index 62d6ad978cc..79139736203 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -26,9 +26,9 @@ import ( "testing" "github.com/containerd/containerd/errdefs" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" ) diff --git a/cmd/nerdctl/container_run_network_windows_test.go b/cmd/nerdctl/container_run_network_windows_test.go index 914627607ec..5a842cde06e 100644 --- a/cmd/nerdctl/container_run_network_windows_test.go +++ b/cmd/nerdctl/container_run_network_windows_test.go @@ -23,9 +23,9 @@ import ( "testing" "github.com/Microsoft/hcsshim" - "github.com/containerd/nerdctl/pkg/defaults" - "github.com/containerd/nerdctl/pkg/netutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_run_restart_linux_test.go b/cmd/nerdctl/container_run_restart_linux_test.go index be570699ac9..44e42b2393e 100644 --- a/cmd/nerdctl/container_run_restart_linux_test.go +++ b/cmd/nerdctl/container_run_restart_linux_test.go @@ -24,8 +24,8 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "gotest.tools/v3/assert" "gotest.tools/v3/poll" diff --git a/cmd/nerdctl/container_run_runtime_linux_test.go b/cmd/nerdctl/container_run_runtime_linux_test.go index fc33c21004a..90c61594009 100644 --- a/cmd/nerdctl/container_run_runtime_linux_test.go +++ b/cmd/nerdctl/container_run_runtime_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRunSysctl(t *testing.T) { diff --git a/cmd/nerdctl/container_run_security_linux_test.go b/cmd/nerdctl/container_run_security_linux_test.go index 49db43cbfe2..55ffdcf306b 100644 --- a/cmd/nerdctl/container_run_security_linux_test.go +++ b/cmd/nerdctl/container_run_security_linux_test.go @@ -24,9 +24,9 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/apparmorutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_run_soci_linux_test.go b/cmd/nerdctl/container_run_soci_linux_test.go index 2cde0118e3d..635f2710cf9 100644 --- a/cmd/nerdctl/container_run_soci_linux_test.go +++ b/cmd/nerdctl/container_run_soci_linux_test.go @@ -21,7 +21,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRunSoci(t *testing.T) { diff --git a/cmd/nerdctl/container_run_stargz_linux_test.go b/cmd/nerdctl/container_run_stargz_linux_test.go index 0e1c8266b3d..3c3c621f746 100644 --- a/cmd/nerdctl/container_run_stargz_linux_test.go +++ b/cmd/nerdctl/container_run_stargz_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRunStargz(t *testing.T) { diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index e18aa7ac8e6..6b70d362b6b 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -30,7 +30,7 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" "gotest.tools/v3/poll" diff --git a/cmd/nerdctl/container_run_user_linux_test.go b/cmd/nerdctl/container_run_user_linux_test.go index 23cdee352c6..114ba251d00 100644 --- a/cmd/nerdctl/container_run_user_linux_test.go +++ b/cmd/nerdctl/container_run_user_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRunUserGID(t *testing.T) { diff --git a/cmd/nerdctl/container_run_user_windows_test.go b/cmd/nerdctl/container_run_user_windows_test.go index 27cfd0697af..d6e45171680 100644 --- a/cmd/nerdctl/container_run_user_windows_test.go +++ b/cmd/nerdctl/container_run_user_windows_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRunUserName(t *testing.T) { diff --git a/cmd/nerdctl/container_run_verify_linux_test.go b/cmd/nerdctl/container_run_verify_linux_test.go index ad4bef7d802..80e9ac5d99e 100644 --- a/cmd/nerdctl/container_run_verify_linux_test.go +++ b/cmd/nerdctl/container_run_verify_linux_test.go @@ -21,8 +21,8 @@ import ( "os" "testing" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/testregistry" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_run_windows_test.go b/cmd/nerdctl/container_run_windows_test.go index 84cfa25294e..38faa432ec9 100644 --- a/cmd/nerdctl/container_run_windows_test.go +++ b/cmd/nerdctl/container_run_windows_test.go @@ -22,7 +22,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_start.go b/cmd/nerdctl/container_start.go index 8596adc3bea..bd67d40f092 100644 --- a/cmd/nerdctl/container_start.go +++ b/cmd/nerdctl/container_start.go @@ -18,10 +18,10 @@ package main import ( "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/consoleutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/consoleutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_start_linux_test.go b/cmd/nerdctl/container_start_linux_test.go index c83e310c40e..d7b35c6271b 100644 --- a/cmd/nerdctl/container_start_linux_test.go +++ b/cmd/nerdctl/container_start_linux_test.go @@ -21,7 +21,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_start_test.go b/cmd/nerdctl/container_start_test.go index b9721b18241..374ee77c821 100644 --- a/cmd/nerdctl/container_start_test.go +++ b/cmd/nerdctl/container_start_test.go @@ -20,7 +20,7 @@ import ( "runtime" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestStart(t *testing.T) { diff --git a/cmd/nerdctl/container_stats.go b/cmd/nerdctl/container_stats.go index 9d47f34c172..f8281c12328 100644 --- a/cmd/nerdctl/container_stats.go +++ b/cmd/nerdctl/container_stats.go @@ -18,9 +18,9 @@ package main import ( "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_stats_linux_test.go b/cmd/nerdctl/container_stats_linux_test.go index 4b6fcd14bdc..6cd7ca3aaf8 100644 --- a/cmd/nerdctl/container_stats_linux_test.go +++ b/cmd/nerdctl/container_stats_linux_test.go @@ -20,9 +20,9 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestStats(t *testing.T) { diff --git a/cmd/nerdctl/container_stop.go b/cmd/nerdctl/container_stop.go index 43a6f6bca44..0398e36ae44 100644 --- a/cmd/nerdctl/container_stop.go +++ b/cmd/nerdctl/container_stop.go @@ -20,9 +20,9 @@ import ( "time" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_stop_linux_test.go b/cmd/nerdctl/container_stop_linux_test.go index a3940188ca7..de5338f7998 100644 --- a/cmd/nerdctl/container_stop_linux_test.go +++ b/cmd/nerdctl/container_stop_linux_test.go @@ -22,8 +22,8 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/container_top.go b/cmd/nerdctl/container_top.go index 141a200432e..c51b23d7242 100644 --- a/cmd/nerdctl/container_top.go +++ b/cmd/nerdctl/container_top.go @@ -21,11 +21,11 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_top_unix_test.go b/cmd/nerdctl/container_top_unix_test.go index acf3676362b..45b39f2a64f 100644 --- a/cmd/nerdctl/container_top_unix_test.go +++ b/cmd/nerdctl/container_top_unix_test.go @@ -21,9 +21,9 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestTop(t *testing.T) { diff --git a/cmd/nerdctl/container_top_windows_test.go b/cmd/nerdctl/container_top_windows_test.go index f862cf328ae..93d9616ce83 100644 --- a/cmd/nerdctl/container_top_windows_test.go +++ b/cmd/nerdctl/container_top_windows_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestTopProcessContainer(t *testing.T) { diff --git a/cmd/nerdctl/container_unpause.go b/cmd/nerdctl/container_unpause.go index 021d3d445b5..26909f790b2 100644 --- a/cmd/nerdctl/container_unpause.go +++ b/cmd/nerdctl/container_unpause.go @@ -18,9 +18,9 @@ package main import ( "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index 73b39588271..d4f79775db9 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -27,12 +27,12 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/pkg/cri/util" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - nerdctlContainer "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + nerdctlContainer "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/typeurl/v2" "github.com/docker/go-units" runtimespec "github.com/opencontainers/runtime-spec/specs-go" diff --git a/cmd/nerdctl/container_wait.go b/cmd/nerdctl/container_wait.go index ae4ce9ffc3d..98156c44175 100644 --- a/cmd/nerdctl/container_wait.go +++ b/cmd/nerdctl/container_wait.go @@ -18,9 +18,9 @@ package main import ( "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_wait_test.go b/cmd/nerdctl/container_wait_test.go index 6a580cf143b..d2048dd6618 100644 --- a/cmd/nerdctl/container_wait_test.go +++ b/cmd/nerdctl/container_wait_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestWait(t *testing.T) { diff --git a/cmd/nerdctl/flagutil.go b/cmd/nerdctl/flagutil.go index cf50b59a30e..795d9d2a0cd 100644 --- a/cmd/nerdctl/flagutil.go +++ b/cmd/nerdctl/flagutil.go @@ -17,7 +17,7 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_convert.go b/cmd/nerdctl/image_convert.go index e2ed0fe3e74..0b27e593d77 100644 --- a/cmd/nerdctl/image_convert.go +++ b/cmd/nerdctl/image_convert.go @@ -19,9 +19,9 @@ package main import ( "compress/gzip" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_convert_linux_test.go b/cmd/nerdctl/image_convert_linux_test.go index 4b7eff95856..c6fb457d962 100644 --- a/cmd/nerdctl/image_convert_linux_test.go +++ b/cmd/nerdctl/image_convert_linux_test.go @@ -21,9 +21,9 @@ import ( "runtime" "testing" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/testregistry" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" "gotest.tools/v3/icmd" ) diff --git a/cmd/nerdctl/image_convert_test.go b/cmd/nerdctl/image_convert_test.go index bcca02a2b2c..2984c9a1369 100644 --- a/cmd/nerdctl/image_convert_test.go +++ b/cmd/nerdctl/image_convert_test.go @@ -20,7 +20,7 @@ import ( "runtime" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestImageConvertEStargz(t *testing.T) { diff --git a/cmd/nerdctl/image_cryptutil.go b/cmd/nerdctl/image_cryptutil.go index 039f7720205..47d5fdb0c52 100644 --- a/cmd/nerdctl/image_cryptutil.go +++ b/cmd/nerdctl/image_cryptutil.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_encrypt_linux_test.go b/cmd/nerdctl/image_encrypt_linux_test.go index 873d08b212a..d20daa60b9a 100644 --- a/cmd/nerdctl/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image_encrypt_linux_test.go @@ -26,9 +26,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/content" - "github.com/containerd/nerdctl/pkg/buildkitutil" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/testregistry" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index c5e53f0b0a7..d6024f9c17c 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -30,10 +30,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/pkg/progress" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/idutil/imagewalker" - "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" + "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/opencontainers/image-spec/identity" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_inspect.go b/cmd/nerdctl/image_inspect.go index a255324ba2c..28a4ffe8a3f 100644 --- a/cmd/nerdctl/image_inspect.go +++ b/cmd/nerdctl/image_inspect.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_inspect_test.go b/cmd/nerdctl/image_inspect_test.go index ef35921ef03..f55fd575593 100644 --- a/cmd/nerdctl/image_inspect_test.go +++ b/cmd/nerdctl/image_inspect_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/image_list.go b/cmd/nerdctl/image_list.go index e63f14fc6fd..a7dc5be6f23 100644 --- a/cmd/nerdctl/image_list.go +++ b/cmd/nerdctl/image_list.go @@ -19,10 +19,10 @@ package main import ( "fmt" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" - "github.com/containerd/nerdctl/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_list_test.go b/cmd/nerdctl/image_list_test.go index 6a057b4430a..4043cf26633 100644 --- a/cmd/nerdctl/image_list_test.go +++ b/cmd/nerdctl/image_list_test.go @@ -22,8 +22,8 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/tabutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/tabutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/image_load.go b/cmd/nerdctl/image_load.go index 5d3f31063ce..39c027d42fa 100644 --- a/cmd/nerdctl/image_load.go +++ b/cmd/nerdctl/image_load.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_load_linux_test.go b/cmd/nerdctl/image_load_linux_test.go index 0f620363a19..bb48046844d 100644 --- a/cmd/nerdctl/image_load_linux_test.go +++ b/cmd/nerdctl/image_load_linux_test.go @@ -24,7 +24,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/image_prune.go b/cmd/nerdctl/image_prune.go index f444c9bb8c2..0f42f9e9828 100644 --- a/cmd/nerdctl/image_prune.go +++ b/cmd/nerdctl/image_prune.go @@ -20,9 +20,9 @@ import ( "fmt" "strings" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_prune_test.go b/cmd/nerdctl/image_prune_test.go index a185d6f33c2..63ba0f5bdea 100644 --- a/cmd/nerdctl/image_prune_test.go +++ b/cmd/nerdctl/image_prune_test.go @@ -21,7 +21,7 @@ import ( "os" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/image_pull.go b/cmd/nerdctl/image_pull.go index 11b2444870f..8c478fb68d9 100644 --- a/cmd/nerdctl/image_pull.go +++ b/cmd/nerdctl/image_pull.go @@ -17,10 +17,10 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" - "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image_pull_linux_test.go index 5c09157cdcc..82c83871f3a 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image_pull_linux_test.go @@ -24,8 +24,8 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/testregistry" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/image_push.go b/cmd/nerdctl/image_push.go index 3dac0d986c1..132318b82ad 100644 --- a/cmd/nerdctl/image_push.go +++ b/cmd/nerdctl/image_push.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_push_linux_test.go b/cmd/nerdctl/image_push_linux_test.go index 9a6bdbd5622..0a65980e19c 100644 --- a/cmd/nerdctl/image_push_linux_test.go +++ b/cmd/nerdctl/image_push_linux_test.go @@ -22,8 +22,8 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/testregistry" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/image_remove.go b/cmd/nerdctl/image_remove.go index b060ec27a9e..26dfdefe4c2 100644 --- a/cmd/nerdctl/image_remove.go +++ b/cmd/nerdctl/image_remove.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_remove_linux_test.go b/cmd/nerdctl/image_remove_linux_test.go index 7594798f62d..0ad754cc596 100644 --- a/cmd/nerdctl/image_remove_linux_test.go +++ b/cmd/nerdctl/image_remove_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRemoveImage(t *testing.T) { diff --git a/cmd/nerdctl/image_save.go b/cmd/nerdctl/image_save.go index 3d9e9ca91cd..a72b7b245b2 100644 --- a/cmd/nerdctl/image_save.go +++ b/cmd/nerdctl/image_save.go @@ -20,9 +20,9 @@ import ( "fmt" "os" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/mattn/go-isatty" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/image_save_linux_test.go b/cmd/nerdctl/image_save_linux_test.go index c2970a9f04c..be9504ca5d4 100644 --- a/cmd/nerdctl/image_save_linux_test.go +++ b/cmd/nerdctl/image_save_linux_test.go @@ -26,7 +26,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/image_save_test.go b/cmd/nerdctl/image_save_test.go index cd4106b8bf7..2bfdeeeb2c1 100644 --- a/cmd/nerdctl/image_save_test.go +++ b/cmd/nerdctl/image_save_test.go @@ -21,7 +21,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestSaveById(t *testing.T) { diff --git a/cmd/nerdctl/image_tag.go b/cmd/nerdctl/image_tag.go index 4361eeffe3b..b6eede91c90 100644 --- a/cmd/nerdctl/image_tag.go +++ b/cmd/nerdctl/image_tag.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/inspect.go b/cmd/nerdctl/inspect.go index 30204ca7c5c..2cea1d97cc7 100644 --- a/cmd/nerdctl/inspect.go +++ b/cmd/nerdctl/inspect.go @@ -20,12 +20,12 @@ import ( "context" "fmt" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/cmd/image" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/idutil/imagewalker" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/internal_oci_hook.go b/cmd/nerdctl/internal_oci_hook.go index e75b32b66a7..bb76c19bb31 100644 --- a/cmd/nerdctl/internal_oci_hook.go +++ b/cmd/nerdctl/internal_oci_hook.go @@ -20,8 +20,8 @@ import ( "errors" "os" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/ocihook" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/ocihook" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/ipfs_build_linux_test.go b/cmd/nerdctl/ipfs_build_linux_test.go index e7af2400786..55a629aa13c 100644 --- a/cmd/nerdctl/ipfs_build_linux_test.go +++ b/cmd/nerdctl/ipfs_build_linux_test.go @@ -23,7 +23,7 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" diff --git a/cmd/nerdctl/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs_compose_linux_test.go index 087fbed2e8a..30ff09b5a9a 100644 --- a/cmd/nerdctl/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs_compose_linux_test.go @@ -23,8 +23,8 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/ipfs_linux_test.go b/cmd/nerdctl/ipfs_linux_test.go index 523d5eb981f..1c5582347ea 100644 --- a/cmd/nerdctl/ipfs_linux_test.go +++ b/cmd/nerdctl/ipfs_linux_test.go @@ -22,9 +22,9 @@ import ( "regexp" "testing" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/ipfs_registry_linux_test.go b/cmd/nerdctl/ipfs_registry_linux_test.go index cec59e59756..70d7794fdc5 100644 --- a/cmd/nerdctl/ipfs_registry_linux_test.go +++ b/cmd/nerdctl/ipfs_registry_linux_test.go @@ -21,7 +21,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestIPFSRegistry(t *testing.T) { diff --git a/cmd/nerdctl/ipfs_registry_serve.go b/cmd/nerdctl/ipfs_registry_serve.go index 81708d2c56e..67a120919bf 100644 --- a/cmd/nerdctl/ipfs_registry_serve.go +++ b/cmd/nerdctl/ipfs_registry_serve.go @@ -17,8 +17,8 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/ipfs" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/ipfs" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/login.go b/cmd/nerdctl/login.go index e64dfee1920..4cff2458bb8 100644 --- a/cmd/nerdctl/login.go +++ b/cmd/nerdctl/login.go @@ -22,8 +22,8 @@ import ( "strings" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/login" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/login" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/login_linux_test.go b/cmd/nerdctl/login_linux_test.go index 12fbc8d4377..ce145e530ee 100644 --- a/cmd/nerdctl/login_linux_test.go +++ b/cmd/nerdctl/login_linux_test.go @@ -23,8 +23,8 @@ import ( "strconv" "testing" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/testregistry" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) func TestLogin(t *testing.T) { diff --git a/cmd/nerdctl/logout.go b/cmd/nerdctl/logout.go index 09b4ee43179..a08c2bdd0a8 100644 --- a/cmd/nerdctl/logout.go +++ b/cmd/nerdctl/logout.go @@ -19,7 +19,7 @@ package main import ( "fmt" - "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" + "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" dockercliconfig "github.com/docker/cli/cli/config" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index c97da084cac..42e5eb7d925 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -26,12 +26,12 @@ import ( "time" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/config" - ncdefaults "github.com/containerd/nerdctl/pkg/defaults" - "github.com/containerd/nerdctl/pkg/errutil" - "github.com/containerd/nerdctl/pkg/logging" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/version" + "github.com/containerd/nerdctl/v2/pkg/config" + ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/errutil" + "github.com/containerd/nerdctl/v2/pkg/logging" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/version" "github.com/fatih/color" "github.com/pelletier/go-toml/v2" diff --git a/cmd/nerdctl/main_linux.go b/cmd/nerdctl/main_linux.go index d4c81209421..5f1f5ae9355 100644 --- a/cmd/nerdctl/main_linux.go +++ b/cmd/nerdctl/main_linux.go @@ -17,9 +17,9 @@ package main import ( - ncdefaults "github.com/containerd/nerdctl/pkg/defaults" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/strutil" + ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/main_linux_test.go b/cmd/nerdctl/main_linux_test.go index a61fa50ee2b..a0e82861a84 100644 --- a/cmd/nerdctl/main_linux_test.go +++ b/cmd/nerdctl/main_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) // TestIssue108 tests https://github.com/containerd/nerdctl/issues/108 diff --git a/cmd/nerdctl/main_test.go b/cmd/nerdctl/main_test.go index 03a09360147..184b2d399be 100644 --- a/cmd/nerdctl/main_test.go +++ b/cmd/nerdctl/main_test.go @@ -22,7 +22,7 @@ import ( "testing" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/main_unix.go b/cmd/nerdctl/main_unix.go index d85a980ccd4..93ac2f9134e 100644 --- a/cmd/nerdctl/main_unix.go +++ b/cmd/nerdctl/main_unix.go @@ -20,9 +20,9 @@ package main import ( "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/multi_platform_linux_test.go b/cmd/nerdctl/multi_platform_linux_test.go index 017d2827c8b..cc76cae4f08 100644 --- a/cmd/nerdctl/multi_platform_linux_test.go +++ b/cmd/nerdctl/multi_platform_linux_test.go @@ -23,9 +23,9 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/nettestutil" - "github.com/containerd/nerdctl/pkg/testutil/testregistry" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/namespace.go b/cmd/nerdctl/namespace.go index 58a3ca0a0d1..b60e89ccd37 100644 --- a/cmd/nerdctl/namespace.go +++ b/cmd/nerdctl/namespace.go @@ -25,8 +25,8 @@ import ( "github.com/containerd/containerd/namespaces" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/mountutil/volumestore" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/namespace_create.go b/cmd/nerdctl/namespace_create.go index 2d8d6617137..ae4b9e08b68 100644 --- a/cmd/nerdctl/namespace_create.go +++ b/cmd/nerdctl/namespace_create.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/namespace" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/namespace_inspect.go b/cmd/nerdctl/namespace_inspect.go index b308c95b93f..669d2002a60 100644 --- a/cmd/nerdctl/namespace_inspect.go +++ b/cmd/nerdctl/namespace_inspect.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/namespace" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/namespace_remove.go b/cmd/nerdctl/namespace_remove.go index 7f23031b581..c8b6c1c8c1c 100644 --- a/cmd/nerdctl/namespace_remove.go +++ b/cmd/nerdctl/namespace_remove.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/namespace" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/namespace_update.go b/cmd/nerdctl/namespace_update.go index fb58ae6edcc..aeabcf3aef7 100644 --- a/cmd/nerdctl/namespace_update.go +++ b/cmd/nerdctl/namespace_update.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/namespace" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index b5c4f1e81e3..d00cf8fe5c2 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -20,10 +20,10 @@ import ( "fmt" "github.com/containerd/containerd/identifiers" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/network" - "github.com/containerd/nerdctl/pkg/netutil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/network" + "github.com/containerd/nerdctl/v2/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/network_create_linux_test.go b/cmd/nerdctl/network_create_linux_test.go index 58b8fcecaed..d27bf24dd4a 100644 --- a/cmd/nerdctl/network_create_linux_test.go +++ b/cmd/nerdctl/network_create_linux_test.go @@ -22,7 +22,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/network_inspect.go b/cmd/nerdctl/network_inspect.go index cea18685fcd..f1cf21d1c9e 100644 --- a/cmd/nerdctl/network_inspect.go +++ b/cmd/nerdctl/network_inspect.go @@ -17,8 +17,8 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/network" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/network" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/network_inspect_test.go b/cmd/nerdctl/network_inspect_test.go index 76b93ec7097..5a43cab1ceb 100644 --- a/cmd/nerdctl/network_inspect_test.go +++ b/cmd/nerdctl/network_inspect_test.go @@ -20,8 +20,8 @@ import ( "runtime" "testing" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/network_list.go b/cmd/nerdctl/network_list.go index 73d2dac2807..0e98257f492 100644 --- a/cmd/nerdctl/network_list.go +++ b/cmd/nerdctl/network_list.go @@ -17,8 +17,8 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/network" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/network" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/network_list_linux_test.go b/cmd/nerdctl/network_list_linux_test.go index 5bbb5e2f9b8..adf5cd71efa 100644 --- a/cmd/nerdctl/network_list_linux_test.go +++ b/cmd/nerdctl/network_list_linux_test.go @@ -22,7 +22,7 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestNetworkLsFilter(t *testing.T) { diff --git a/cmd/nerdctl/network_prune.go b/cmd/nerdctl/network_prune.go index f67996a2733..89e24ad2cf4 100644 --- a/cmd/nerdctl/network_prune.go +++ b/cmd/nerdctl/network_prune.go @@ -20,9 +20,9 @@ import ( "fmt" "strings" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/network" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/network" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/network_prune_linux_test.go b/cmd/nerdctl/network_prune_linux_test.go index d872d540b26..68ad06efaa2 100644 --- a/cmd/nerdctl/network_prune_linux_test.go +++ b/cmd/nerdctl/network_prune_linux_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestNetworkPrune(t *testing.T) { diff --git a/cmd/nerdctl/network_remove.go b/cmd/nerdctl/network_remove.go index 4d26b579461..3b8dae7fb1d 100644 --- a/cmd/nerdctl/network_remove.go +++ b/cmd/nerdctl/network_remove.go @@ -17,10 +17,10 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/network" - "github.com/containerd/nerdctl/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/network" + "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/network_remove_linux_test.go b/cmd/nerdctl/network_remove_linux_test.go index 9003f2a4bcf..80ccc504069 100644 --- a/cmd/nerdctl/network_remove_linux_test.go +++ b/cmd/nerdctl/network_remove_linux_test.go @@ -19,8 +19,8 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/vishvananda/netlink" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/system_events.go b/cmd/nerdctl/system_events.go index 9455cd1ca59..db41ab17dba 100644 --- a/cmd/nerdctl/system_events.go +++ b/cmd/nerdctl/system_events.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/system" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/system" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/system_info.go b/cmd/nerdctl/system_info.go index 1a8c94304a9..b7a69568df6 100644 --- a/cmd/nerdctl/system_info.go +++ b/cmd/nerdctl/system_info.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/system" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/system" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/system_info_test.go b/cmd/nerdctl/system_info_test.go index 7606b0ed601..dfe2665bf3d 100644 --- a/cmd/nerdctl/system_info_test.go +++ b/cmd/nerdctl/system_info_test.go @@ -22,9 +22,9 @@ import ( "os" "testing" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func testInfoJSON(stdout string) error { diff --git a/cmd/nerdctl/system_prune.go b/cmd/nerdctl/system_prune.go index 944b2fdcf45..bfe1b8257d3 100644 --- a/cmd/nerdctl/system_prune.go +++ b/cmd/nerdctl/system_prune.go @@ -21,9 +21,9 @@ import ( "strings" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/system" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/system" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/system_prune_linux_test.go b/cmd/nerdctl/system_prune_linux_test.go index 24c7b9d481e..32fbf04c4c0 100644 --- a/cmd/nerdctl/system_prune_linux_test.go +++ b/cmd/nerdctl/system_prune_linux_test.go @@ -26,8 +26,8 @@ import ( "testing" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/buildkitutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestSystemPrune(t *testing.T) { diff --git a/cmd/nerdctl/version.go b/cmd/nerdctl/version.go index 88eec8c775b..6d09a364321 100644 --- a/cmd/nerdctl/version.go +++ b/cmd/nerdctl/version.go @@ -24,11 +24,11 @@ import ( "text/template" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume_create.go index 4a90d082a77..972d5fc0359 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume_create.go @@ -17,8 +17,8 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/volume" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/volume_create_test.go b/cmd/nerdctl/volume_create_test.go index 742810b0223..f8f5997b501 100644 --- a/cmd/nerdctl/volume_create_test.go +++ b/cmd/nerdctl/volume_create_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/volume_inspect.go b/cmd/nerdctl/volume_inspect.go index 64ef29a35d2..0eee9c41231 100644 --- a/cmd/nerdctl/volume_inspect.go +++ b/cmd/nerdctl/volume_inspect.go @@ -17,8 +17,8 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/volume" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/volume_inspect_test.go b/cmd/nerdctl/volume_inspect_test.go index 6dc948b31cd..24fff144a77 100644 --- a/cmd/nerdctl/volume_inspect_test.go +++ b/cmd/nerdctl/volume_inspect_test.go @@ -22,7 +22,7 @@ import ( "path/filepath" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/cmd/nerdctl/volume_list.go b/cmd/nerdctl/volume_list.go index 163c5da4427..5f01f6c5146 100644 --- a/cmd/nerdctl/volume_list.go +++ b/cmd/nerdctl/volume_list.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/volume" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/volume_list_test.go b/cmd/nerdctl/volume_list_test.go index 9a62dd102d4..9b88e13eac9 100644 --- a/cmd/nerdctl/volume_list_test.go +++ b/cmd/nerdctl/volume_list_test.go @@ -22,8 +22,8 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/tabutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/tabutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestVolumeLs(t *testing.T) { diff --git a/cmd/nerdctl/volume_prune.go b/cmd/nerdctl/volume_prune.go index d015462134b..a6fa42392e9 100644 --- a/cmd/nerdctl/volume_prune.go +++ b/cmd/nerdctl/volume_prune.go @@ -20,9 +20,9 @@ import ( "fmt" "strings" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/volume" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/volume_prune_linux_test.go b/cmd/nerdctl/volume_prune_linux_test.go index be7a7fc093b..a744de0f5fe 100644 --- a/cmd/nerdctl/volume_prune_linux_test.go +++ b/cmd/nerdctl/volume_prune_linux_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestVolumePrune(t *testing.T) { diff --git a/cmd/nerdctl/volume_remove.go b/cmd/nerdctl/volume_remove.go index 71245937b47..0d237c10b6f 100644 --- a/cmd/nerdctl/volume_remove.go +++ b/cmd/nerdctl/volume_remove.go @@ -17,9 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/volume" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/volume_remove_linux_test.go b/cmd/nerdctl/volume_remove_linux_test.go index b244a5101e2..35a478e530e 100644 --- a/cmd/nerdctl/volume_remove_linux_test.go +++ b/cmd/nerdctl/volume_remove_linux_test.go @@ -20,7 +20,7 @@ import ( "fmt" "testing" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestVolumeRemove(t *testing.T) { diff --git a/go.mod b/go.mod index bd206d11d81..672726c0b66 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/containerd/nerdctl +module github.com/containerd/nerdctl/v2 go 1.20 diff --git a/hack/verify-pkg-isolation.sh b/hack/verify-pkg-isolation.sh index e6b2150608a..3f1edd22e30 100755 --- a/hack/verify-pkg-isolation.sh +++ b/hack/verify-pkg-isolation.sh @@ -17,7 +17,7 @@ echo "Verifying that ./pkg/... is decoupled from the CLI packages" set -eux -o pipefail -if go list -f '{{join .Deps "\n"}}' ./pkg/... | grep -E '^(github.com/spf13/cobra|github.com/spf13/pflag|github.com/containerd/nerdctl/cmd)'; then +if go list -f '{{join .Deps "\n"}}' ./pkg/... | grep -E '^(github.com/spf13/cobra|github.com/spf13/pflag|github.com/containerd/nerdctl/v2/cmd)'; then echo >&2 "ERROR: ./pkg/... is not decoupled from the CLI packages" exit 1 fi diff --git a/pkg/api/types/global.go b/pkg/api/types/global.go index bffb23eee26..132fb17e137 100644 --- a/pkg/api/types/global.go +++ b/pkg/api/types/global.go @@ -16,6 +16,6 @@ package types -import "github.com/containerd/nerdctl/pkg/config" +import "github.com/containerd/nerdctl/v2/pkg/config" type GlobalCommandOptions config.Config diff --git a/pkg/api/types/image_types.go b/pkg/api/types/image_types.go index aebee69ea03..16a6602b06e 100644 --- a/pkg/api/types/image_types.go +++ b/pkg/api/types/image_types.go @@ -19,7 +19,7 @@ package types import ( "io" - "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil" ) // ImageListOptions specifies options for `nerdctl image list`. diff --git a/pkg/api/types/network_types.go b/pkg/api/types/network_types.go index a3f15e7d69e..c8fa1cc5645 100644 --- a/pkg/api/types/network_types.go +++ b/pkg/api/types/network_types.go @@ -19,7 +19,7 @@ package types import ( "io" - "github.com/containerd/nerdctl/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/netutil" ) // NetworkCreateOptions specifies options for `nerdctl network create`. diff --git a/pkg/buildkitutil/buildkitutil.go b/pkg/buildkitutil/buildkitutil.go index b89170d91ba..2f72f8c1ff5 100644 --- a/pkg/buildkitutil/buildkitutil.go +++ b/pkg/buildkitutil/buildkitutil.go @@ -36,7 +36,7 @@ import ( "runtime" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) const ( diff --git a/pkg/bypass4netnsutil/bypass4netnsutil.go b/pkg/bypass4netnsutil/bypass4netnsutil.go index 4e2dfa826e3..133102ae98f 100644 --- a/pkg/bypass4netnsutil/bypass4netnsutil.go +++ b/pkg/bypass4netnsutil/bypass4netnsutil.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/opencontainers/runtime-spec/specs-go" b4nnoci "github.com/rootless-containers/bypass4netns/pkg/oci" ) diff --git a/pkg/clientutil/client.go b/pkg/clientutil/client.go index 5f3aa4e82eb..c6a799a55ec 100644 --- a/pkg/clientutil/client.go +++ b/pkg/clientutil/client.go @@ -28,8 +28,8 @@ import ( "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/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/systemutil" "github.com/opencontainers/go-digest" ) diff --git a/pkg/cmd/apparmor/inspect_linux.go b/pkg/cmd/apparmor/inspect_linux.go index 5fa2a17286d..e24dc1f0a27 100644 --- a/pkg/cmd/apparmor/inspect_linux.go +++ b/pkg/cmd/apparmor/inspect_linux.go @@ -20,8 +20,8 @@ import ( "fmt" "github.com/containerd/containerd/contrib/apparmor" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/defaults" ) func Inspect(options types.ApparmorInspectOptions) error { diff --git a/pkg/cmd/apparmor/list_linux.go b/pkg/cmd/apparmor/list_linux.go index ca4b8c7e632..b5825545159 100644 --- a/pkg/cmd/apparmor/list_linux.go +++ b/pkg/cmd/apparmor/list_linux.go @@ -23,9 +23,9 @@ import ( "text/tabwriter" "text/template" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/apparmorutil" - "github.com/containerd/nerdctl/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" + "github.com/containerd/nerdctl/v2/pkg/formatter" ) func List(options types.ApparmorListOptions) error { diff --git a/pkg/cmd/apparmor/load_linux.go b/pkg/cmd/apparmor/load_linux.go index ed45eaf7da5..aace881f288 100644 --- a/pkg/cmd/apparmor/load_linux.go +++ b/pkg/cmd/apparmor/load_linux.go @@ -19,7 +19,7 @@ package apparmor import ( "github.com/containerd/containerd/contrib/apparmor" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/defaults" ) func Load() error { diff --git a/pkg/cmd/apparmor/unload_linux.go b/pkg/cmd/apparmor/unload_linux.go index b5e349ae4dd..87458d87341 100644 --- a/pkg/cmd/apparmor/unload_linux.go +++ b/pkg/cmd/apparmor/unload_linux.go @@ -18,7 +18,7 @@ package apparmor import ( "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/apparmorutil" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" ) func Unload(target string) error { diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index fa2feeaa085..401bb5f504a 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -35,11 +35,11 @@ import ( "github.com/containerd/containerd/platforms" dockerreference "github.com/containerd/containerd/reference/docker" "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/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) func Build(ctx context.Context, client *containerd.Client, options types.BuilderBuildOptions) error { diff --git a/pkg/cmd/builder/prune.go b/pkg/cmd/builder/prune.go index 0bd970df320..121b9230962 100644 --- a/pkg/cmd/builder/prune.go +++ b/pkg/cmd/builder/prune.go @@ -24,8 +24,8 @@ import ( "os/exec" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" ) // Prune will prune all build cache. diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 65be64b8965..b7ab4543561 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -26,16 +26,16 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/platforms" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/volume" - "github.com/containerd/nerdctl/pkg/composer" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/ipfs" - "github.com/containerd/nerdctl/pkg/netutil" - "github.com/containerd/nerdctl/pkg/referenceutil" - "github.com/containerd/nerdctl/pkg/signutil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" + "github.com/containerd/nerdctl/v2/pkg/composer" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/ipfs" + "github.com/containerd/nerdctl/v2/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/signutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/cmd/container/attach.go b/pkg/cmd/container/attach.go index a4c3944e60a..c7fda751628 100644 --- a/pkg/cmd/container/attach.go +++ b/pkg/cmd/container/attach.go @@ -25,11 +25,11 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/consoleutil" - "github.com/containerd/nerdctl/pkg/errutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/signalutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/consoleutil" + "github.com/containerd/nerdctl/v2/pkg/errutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/signalutil" ) // Attach attaches stdin, stdout, and stderr to a running container. diff --git a/pkg/cmd/container/commit.go b/pkg/cmd/container/commit.go index b355d1c02a8..4a6a98bc110 100644 --- a/pkg/cmd/container/commit.go +++ b/pkg/cmd/container/commit.go @@ -24,10 +24,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/imgutil/commit" - "github.com/containerd/nerdctl/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/imgutil/commit" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) // Commit will commit a container’s file changes or settings into a new image. diff --git a/pkg/cmd/container/cp_linux.go b/pkg/cmd/container/cp_linux.go index a392aacc8e9..79466203894 100644 --- a/pkg/cmd/container/cp_linux.go +++ b/pkg/cmd/container/cp_linux.go @@ -21,9 +21,9 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) // Cp copies files/folders between a running container and the local filesystem. diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 43f5e6828d4..dc5b3491bf7 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -36,21 +36,21 @@ import ( "github.com/containerd/containerd/oci" gocni "github.com/containerd/go-cni" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/image" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/flagutil" - "github.com/containerd/nerdctl/pkg/idgen" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/logging" - "github.com/containerd/nerdctl/pkg/mountutil" - "github.com/containerd/nerdctl/pkg/namestore" - "github.com/containerd/nerdctl/pkg/platformutil" - "github.com/containerd/nerdctl/pkg/referenceutil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/flagutil" + "github.com/containerd/nerdctl/v2/pkg/idgen" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/logging" + "github.com/containerd/nerdctl/v2/pkg/mountutil" + "github.com/containerd/nerdctl/v2/pkg/namestore" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" dockercliopts "github.com/docker/cli/opts" dockeropts "github.com/docker/docker/opts" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/pkg/cmd/container/exec.go b/pkg/cmd/container/exec.go index a50f4106e84..8beefcf1091 100644 --- a/pkg/cmd/container/exec.go +++ b/pkg/cmd/container/exec.go @@ -26,13 +26,13 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/consoleutil" - "github.com/containerd/nerdctl/pkg/flagutil" - "github.com/containerd/nerdctl/pkg/idgen" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/signalutil" - "github.com/containerd/nerdctl/pkg/taskutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/consoleutil" + "github.com/containerd/nerdctl/v2/pkg/flagutil" + "github.com/containerd/nerdctl/v2/pkg/idgen" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/signalutil" + "github.com/containerd/nerdctl/v2/pkg/taskutil" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/cmd/container/inspect.go b/pkg/cmd/container/inspect.go index 458fd0e60a4..4cdad9faf27 100644 --- a/pkg/cmd/container/inspect.go +++ b/pkg/cmd/container/inspect.go @@ -23,11 +23,11 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/containerinspector" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerinspector" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" ) // Inspect prints detailed information for each container in `containers`. diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index 6c0f7031752..ad2104b283c 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -27,9 +27,9 @@ import ( "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/moby/sys/signal" ) diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index 97f6033f9f8..b4b0a5f4ee4 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -29,11 +29,11 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/pkg/progress" "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/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/labels/k8slabels" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/labels/k8slabels" ) // List prints containers according to `options`. diff --git a/pkg/cmd/container/list_util.go b/pkg/cmd/container/list_util.go index 6067405fb87..4647faa213a 100644 --- a/pkg/cmd/container/list_util.go +++ b/pkg/cmd/container/list_util.go @@ -26,7 +26,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/containerutil" ) func foldContainerFilters(ctx context.Context, containers []containerd.Container, filters []string) (*containerFilterContext, error) { diff --git a/pkg/cmd/container/logs.go b/pkg/cmd/container/logs.go index 239074c36cd..1cc79c02bf2 100644 --- a/pkg/cmd/container/logs.go +++ b/pkg/cmd/container/logs.go @@ -26,13 +26,13 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/api/types/cri" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/labels/k8slabels" - "github.com/containerd/nerdctl/pkg/logging" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types/cri" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/labels/k8slabels" + "github.com/containerd/nerdctl/v2/pkg/logging" ) func Logs(ctx context.Context, client *containerd.Client, container string, options types.ContainerLogsOptions) error { diff --git a/pkg/cmd/container/pause.go b/pkg/cmd/container/pause.go index 8a18a35ba41..11bcbd02613 100644 --- a/pkg/cmd/container/pause.go +++ b/pkg/cmd/container/pause.go @@ -21,9 +21,9 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) // Pause pauses all containers specified by `reqs`. diff --git a/pkg/cmd/container/prune.go b/pkg/cmd/container/prune.go index b0f8f1221ca..cc36e77a126 100644 --- a/pkg/cmd/container/prune.go +++ b/pkg/cmd/container/prune.go @@ -24,7 +24,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) // Prune remove all stopped containers diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 11e4a91c230..842f62d7e54 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -30,14 +30,14 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/namespaces" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/cmd/volume" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/namestore" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/namestore" ) var _ error = ErrContainerStatus{} diff --git a/pkg/cmd/container/rename.go b/pkg/cmd/container/rename.go index 31b357e25e9..959bf68152e 100644 --- a/pkg/cmd/container/rename.go +++ b/pkg/cmd/container/rename.go @@ -22,12 +22,12 @@ import ( "runtime" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/namestore" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/namestore" ) // Rename change container name to a new name diff --git a/pkg/cmd/container/restart.go b/pkg/cmd/container/restart.go index 5547074d128..a24a5f641d3 100644 --- a/pkg/cmd/container/restart.go +++ b/pkg/cmd/container/restart.go @@ -21,9 +21,9 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) // Restart will restart one or more containers. diff --git a/pkg/cmd/container/run_cgroup_freebsd.go b/pkg/cmd/container/run_cgroup_freebsd.go index 7ae22379ef9..fcf07cb7bb2 100644 --- a/pkg/cmd/container/run_cgroup_freebsd.go +++ b/pkg/cmd/container/run_cgroup_freebsd.go @@ -18,7 +18,7 @@ package container import ( "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) func generateCgroupOpts(id string, options types.ContainerCreateOptions) ([]oci.SpecOpts, error) { diff --git a/pkg/cmd/container/run_cgroup_linux.go b/pkg/cmd/container/run_cgroup_linux.go index 87b57035ec9..d7e6b4e4bc2 100644 --- a/pkg/cmd/container/run_cgroup_linux.go +++ b/pkg/cmd/container/run_cgroup_linux.go @@ -26,9 +26,9 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/cmd/container/run_cgroup_windows.go b/pkg/cmd/container/run_cgroup_windows.go index 7ae22379ef9..fcf07cb7bb2 100644 --- a/pkg/cmd/container/run_cgroup_windows.go +++ b/pkg/cmd/container/run_cgroup_windows.go @@ -18,7 +18,7 @@ package container import ( "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) func generateCgroupOpts(id string, options types.ContainerCreateOptions) ([]oci.SpecOpts, error) { diff --git a/pkg/cmd/container/run_freebsd.go b/pkg/cmd/container/run_freebsd.go index 5aabb440848..87a07a12753 100644 --- a/pkg/cmd/container/run_freebsd.go +++ b/pkg/cmd/container/run_freebsd.go @@ -22,7 +22,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) func WithoutRunMount() func(ctx context.Context, client oci.Client, c *containers.Container, s *oci.Spec) error { diff --git a/pkg/cmd/container/run_gpus.go b/pkg/cmd/container/run_gpus.go index fdd14455d85..9c3891c053d 100644 --- a/pkg/cmd/container/run_gpus.go +++ b/pkg/cmd/container/run_gpus.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd/contrib/nvidia" "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) // GPUReq is a request for GPUs. diff --git a/pkg/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index cf22e642715..06ef8416294 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -26,12 +26,12 @@ import ( "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" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/bypass4netnsutil" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/docker/go-units" "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..3a53c8c6f70 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -36,15 +36,15 @@ import ( "github.com/containerd/containerd/pkg/userns" "github.com/containerd/continuity/fs" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/volume" - "github.com/containerd/nerdctl/pkg/idgen" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/mountutil" - "github.com/containerd/nerdctl/pkg/mountutil/volumestore" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" + "github.com/containerd/nerdctl/v2/pkg/idgen" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/mountutil" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" + "github.com/containerd/nerdctl/v2/pkg/strutil" securejoin "github.com/cyphar/filepath-securejoin" "github.com/opencontainers/image-spec/identity" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/pkg/cmd/container/run_restart.go b/pkg/cmd/container/run_restart.go index 81c190133c6..b300dc0698d 100644 --- a/pkg/cmd/container/run_restart.go +++ b/pkg/cmd/container/run_restart.go @@ -23,7 +23,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/runtime/restart" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) func checkRestartCapabilities(ctx context.Context, client *containerd.Client, restartFlag string) (bool, error) { diff --git a/pkg/cmd/container/run_security_linux.go b/pkg/cmd/container/run_security_linux.go index 2e1b0d19e74..5b74cce49f9 100644 --- a/pkg/cmd/container/run_security_linux.go +++ b/pkg/cmd/container/run_security_linux.go @@ -26,10 +26,10 @@ import ( "github.com/containerd/containerd/oci" "github.com/containerd/containerd/pkg/cap" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/apparmorutil" - "github.com/containerd/nerdctl/pkg/defaults" - "github.com/containerd/nerdctl/pkg/maputil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" + "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/maputil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) var privilegedOpts = []oci.SpecOpts{ diff --git a/pkg/cmd/container/run_ulimit.go b/pkg/cmd/container/run_ulimit.go index 52fec1f8ba6..5b825a7ec16 100644 --- a/pkg/cmd/container/run_ulimit.go +++ b/pkg/cmd/container/run_ulimit.go @@ -22,7 +22,7 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/cmd/container/run_windows.go b/pkg/cmd/container/run_windows.go index 6d6e5a32184..4e2f5fe07b5 100644 --- a/pkg/cmd/container/run_windows.go +++ b/pkg/cmd/container/run_windows.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/cmd/container/start.go b/pkg/cmd/container/start.go index 7267972b614..926c521f6df 100644 --- a/pkg/cmd/container/start.go +++ b/pkg/cmd/container/start.go @@ -21,9 +21,9 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) // Start starts a list of `containers`. If attach is true, it only starts a single container. diff --git a/pkg/cmd/container/stats.go b/pkg/cmd/container/stats.go index 64811db4c72..537e6a54193 100644 --- a/pkg/cmd/container/stats.go +++ b/pkg/cmd/container/stats.go @@ -32,16 +32,16 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/events" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/containerinspector" - "github.com/containerd/nerdctl/pkg/eventutil" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/statsutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/containerinspector" + "github.com/containerd/nerdctl/v2/pkg/eventutil" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/statsutil" "github.com/containerd/typeurl/v2" ) diff --git a/pkg/cmd/container/stats_freebsd.go b/pkg/cmd/container/stats_freebsd.go index e2dbea58ea6..ef2c98fdfad 100644 --- a/pkg/cmd/container/stats_freebsd.go +++ b/pkg/cmd/container/stats_freebsd.go @@ -17,8 +17,8 @@ package container import ( - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/pkg/statsutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/statsutil" ) func setContainerStatsAndRenderStatsEntry(previousStats *statsutil.ContainerStats, firstSet bool, anydata interface{}, pid int, interfaces []native.NetInterface) (statsutil.StatsEntry, error) { diff --git a/pkg/cmd/container/stats_linux.go b/pkg/cmd/container/stats_linux.go index 49d9eb488db..762dec200ac 100644 --- a/pkg/cmd/container/stats_linux.go +++ b/pkg/cmd/container/stats_linux.go @@ -25,8 +25,8 @@ import ( v1 "github.com/containerd/cgroups/v3/cgroup1/stats" v2 "github.com/containerd/cgroups/v3/cgroup2/stats" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/pkg/statsutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/statsutil" "github.com/vishvananda/netlink" "github.com/vishvananda/netns" ) diff --git a/pkg/cmd/container/stats_windows.go b/pkg/cmd/container/stats_windows.go index e2dbea58ea6..ef2c98fdfad 100644 --- a/pkg/cmd/container/stats_windows.go +++ b/pkg/cmd/container/stats_windows.go @@ -17,8 +17,8 @@ package container import ( - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/pkg/statsutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/statsutil" ) func setContainerStatsAndRenderStatsEntry(previousStats *statsutil.ContainerStats, firstSet bool, anydata interface{}, pid int, interfaces []native.NetInterface) (statsutil.StatsEntry, error) { diff --git a/pkg/cmd/container/stop.go b/pkg/cmd/container/stop.go index 25b78a9d769..6398abe9e65 100644 --- a/pkg/cmd/container/stop.go +++ b/pkg/cmd/container/stop.go @@ -22,9 +22,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) // Stop stops a list of containers specified by `reqs`. diff --git a/pkg/cmd/container/top.go b/pkg/cmd/container/top.go index f1a3f238b6f..2f4cae35c4c 100644 --- a/pkg/cmd/container/top.go +++ b/pkg/cmd/container/top.go @@ -33,8 +33,8 @@ import ( "strings" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) // ContainerTopOKBody is from https://github.com/moby/moby/blob/v20.10.6/api/types/container/container_top.go diff --git a/pkg/cmd/container/unpause.go b/pkg/cmd/container/unpause.go index f8044ba5992..f0e6325e81f 100644 --- a/pkg/cmd/container/unpause.go +++ b/pkg/cmd/container/unpause.go @@ -21,9 +21,9 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) // Unpause unpauses all containers specified by `reqs`. diff --git a/pkg/cmd/container/wait.go b/pkg/cmd/container/wait.go index 5540e7b3c11..f726f81cd3a 100644 --- a/pkg/cmd/container/wait.go +++ b/pkg/cmd/container/wait.go @@ -23,8 +23,8 @@ import ( "io" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) // Wait blocks until all the containers specified by reqs have stopped, then print their exit codes. diff --git a/pkg/cmd/image/convert.go b/pkg/cmd/image/convert.go index 64007060033..0cb9c560f8c 100644 --- a/pkg/cmd/image/convert.go +++ b/pkg/cmd/image/convert.go @@ -32,11 +32,11 @@ import ( "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/images/converter/uncompress" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - converterutil "github.com/containerd/nerdctl/pkg/imgutil/converter" - "github.com/containerd/nerdctl/pkg/platformutil" - "github.com/containerd/nerdctl/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + converterutil "github.com/containerd/nerdctl/v2/pkg/imgutil/converter" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" nydusconvert "github.com/containerd/nydus-snapshotter/pkg/converter" "github.com/containerd/stargz-snapshotter/estargz" estargzconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz" diff --git a/pkg/cmd/image/crypt.go b/pkg/cmd/image/crypt.go index 9aa08318e1c..be134fcf972 100644 --- a/pkg/cmd/image/crypt.go +++ b/pkg/cmd/image/crypt.go @@ -26,9 +26,9 @@ import ( "github.com/containerd/containerd/images/converter" "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/imgcrypt/images/encryption/parsehelpers" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/platformutil" - "github.com/containerd/nerdctl/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/cmd/image/inspect.go b/pkg/cmd/image/inspect.go index fcaa46d2f38..f37e9e0e217 100644 --- a/pkg/cmd/image/inspect.go +++ b/pkg/cmd/image/inspect.go @@ -23,11 +23,11 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/idutil/imagewalker" - "github.com/containerd/nerdctl/pkg/imageinspector" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" + "github.com/containerd/nerdctl/v2/pkg/imageinspector" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" ) // Inspect prints detailed information of each image in `images`. diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 9a4f927e2f0..be256b3ddb5 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -35,9 +35,9 @@ import ( "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/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/imgutil" 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..7922c2448ad 100644 --- a/pkg/cmd/image/load.go +++ b/pkg/cmd/image/load.go @@ -28,9 +28,9 @@ import ( "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/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/platformutil" ) type readCounter struct { diff --git a/pkg/cmd/image/prune.go b/pkg/cmd/image/prune.go index abcee6bd86a..5691f331023 100644 --- a/pkg/cmd/image/prune.go +++ b/pkg/cmd/image/prune.go @@ -24,8 +24,8 @@ import ( "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/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/opencontainers/go-digest" ) diff --git a/pkg/cmd/image/pull.go b/pkg/cmd/image/pull.go index 68e14e03735..0a87df16d5a 100644 --- a/pkg/cmd/image/pull.go +++ b/pkg/cmd/image/pull.go @@ -23,13 +23,13 @@ import ( "path/filepath" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/ipfs" - "github.com/containerd/nerdctl/pkg/platformutil" - "github.com/containerd/nerdctl/pkg/referenceutil" - "github.com/containerd/nerdctl/pkg/signutil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/ipfs" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/signutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" v1 "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index 64c3b6cc7c8..0970a6972fe 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -33,15 +33,15 @@ import ( "github.com/containerd/containerd/remotes/docker" dockerconfig "github.com/containerd/containerd/remotes/docker/config" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/errutil" - "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" - "github.com/containerd/nerdctl/pkg/imgutil/push" - "github.com/containerd/nerdctl/pkg/ipfs" - "github.com/containerd/nerdctl/pkg/platformutil" - "github.com/containerd/nerdctl/pkg/referenceutil" - "github.com/containerd/nerdctl/pkg/signutil" - "github.com/containerd/nerdctl/pkg/snapshotterutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/errutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" + "github.com/containerd/nerdctl/v2/pkg/imgutil/push" + "github.com/containerd/nerdctl/v2/pkg/ipfs" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/signutil" + "github.com/containerd/nerdctl/v2/pkg/snapshotterutil" "github.com/containerd/stargz-snapshotter/estargz" "github.com/containerd/stargz-snapshotter/estargz/zstdchunked" estargzconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz" diff --git a/pkg/cmd/image/remove.go b/pkg/cmd/image/remove.go index 0e0c20d8a60..19d5cd8ea7c 100644 --- a/pkg/cmd/image/remove.go +++ b/pkg/cmd/image/remove.go @@ -26,9 +26,9 @@ import ( "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/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" ) // Remove removes a list of `images`. diff --git a/pkg/cmd/image/save.go b/pkg/cmd/image/save.go index cf4dbf3069e..db910323a89 100644 --- a/pkg/cmd/image/save.go +++ b/pkg/cmd/image/save.go @@ -22,10 +22,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images/archive" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/idutil/imagewalker" - "github.com/containerd/nerdctl/pkg/platformutil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) // Save exports `images` to a `io.Writer` (e.g., a file writer, or os.Stdout) specified by `options.Stdout`. diff --git a/pkg/cmd/image/tag.go b/pkg/cmd/image/tag.go index 8349fc6c769..4543f2a070d 100644 --- a/pkg/cmd/image/tag.go +++ b/pkg/cmd/image/tag.go @@ -22,9 +22,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/idutil/imagewalker" - "github.com/containerd/nerdctl/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) func Tag(ctx context.Context, client *containerd.Client, options types.ImageTagOptions) error { diff --git a/pkg/cmd/ipfs/registry_serve.go b/pkg/cmd/ipfs/registry_serve.go index ede278f115e..9ee048a9a94 100644 --- a/pkg/cmd/ipfs/registry_serve.go +++ b/pkg/cmd/ipfs/registry_serve.go @@ -22,8 +22,8 @@ import ( "path/filepath" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/ipfs" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/ipfs" ) func RegistryServe(options types.IPFSRegistryServeOptions) error { diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 385a9609f44..64573c7e0e5 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -30,9 +30,9 @@ import ( "github.com/containerd/containerd/remotes/docker" "github.com/containerd/containerd/remotes/docker/config" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/errutil" - "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/errutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" dockercliconfig "github.com/docker/cli/cli/config" dockercliconfigtypes "github.com/docker/cli/cli/config/types" "github.com/docker/docker/api/types/registry" diff --git a/pkg/cmd/namespace/create.go b/pkg/cmd/namespace/create.go index f23765dcbab..6f79e999797 100644 --- a/pkg/cmd/namespace/create.go +++ b/pkg/cmd/namespace/create.go @@ -20,7 +20,7 @@ import ( "context" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) func Create(ctx context.Context, client *containerd.Client, namespace string, options types.NamespaceCreateOptions) error { diff --git a/pkg/cmd/namespace/inspect.go b/pkg/cmd/namespace/inspect.go index 99341ca03d2..3f602ef6187 100644 --- a/pkg/cmd/namespace/inspect.go +++ b/pkg/cmd/namespace/inspect.go @@ -21,9 +21,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/namespaces" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) func Inspect(ctx context.Context, client *containerd.Client, inspectedNamespaces []string, options types.NamespaceInspectOptions) error { diff --git a/pkg/cmd/namespace/remove.go b/pkg/cmd/namespace/remove.go index 25a8720cf84..a4de8514e87 100644 --- a/pkg/cmd/namespace/remove.go +++ b/pkg/cmd/namespace/remove.go @@ -23,7 +23,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) func Remove(ctx context.Context, client *containerd.Client, deletedNamespaces []string, options types.NamespaceRemoveOptions) error { diff --git a/pkg/cmd/namespace/update.go b/pkg/cmd/namespace/update.go index a8b4eb31aef..3952f98a6cc 100644 --- a/pkg/cmd/namespace/update.go +++ b/pkg/cmd/namespace/update.go @@ -20,7 +20,7 @@ import ( "context" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) func Update(ctx context.Context, client *containerd.Client, namespace string, options types.NamespaceUpdateOptions) error { diff --git a/pkg/cmd/network/create.go b/pkg/cmd/network/create.go index 8a032433478..f1dd42a1b6b 100644 --- a/pkg/cmd/network/create.go +++ b/pkg/cmd/network/create.go @@ -21,8 +21,8 @@ import ( "io" "github.com/containerd/containerd/errdefs" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/netutil" ) func Create(options types.NetworkCreateOptions, stdout io.Writer) error { diff --git a/pkg/cmd/network/inspect.go b/pkg/cmd/network/inspect.go index 39c5ffc1aed..9ef9581b4a4 100644 --- a/pkg/cmd/network/inspect.go +++ b/pkg/cmd/network/inspect.go @@ -22,12 +22,12 @@ import ( "fmt" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/idutil/netwalker" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/idutil/netwalker" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/netutil" ) func Inspect(ctx context.Context, options types.NetworkInspectOptions) error { diff --git a/pkg/cmd/network/list.go b/pkg/cmd/network/list.go index a045900ff35..ab7c2696ee2 100644 --- a/pkg/cmd/network/list.go +++ b/pkg/cmd/network/list.go @@ -25,9 +25,9 @@ import ( "text/tabwriter" "text/template" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/netutil" ) type networkPrintable struct { diff --git a/pkg/cmd/network/prune.go b/pkg/cmd/network/prune.go index 645e6d2362a..4595e6fe2b4 100644 --- a/pkg/cmd/network/prune.go +++ b/pkg/cmd/network/prune.go @@ -22,9 +22,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/netutil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) func Prune(ctx context.Context, client *containerd.Client, options types.NetworkPruneOptions) error { diff --git a/pkg/cmd/network/remove.go b/pkg/cmd/network/remove.go index 76da1eeabca..a2fc73c0e17 100644 --- a/pkg/cmd/network/remove.go +++ b/pkg/cmd/network/remove.go @@ -21,9 +21,9 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/idutil/netwalker" - "github.com/containerd/nerdctl/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/idutil/netwalker" + "github.com/containerd/nerdctl/v2/pkg/netutil" ) func Remove(ctx context.Context, client *containerd.Client, options types.NetworkRemoveOptions) error { diff --git a/pkg/cmd/system/events.go b/pkg/cmd/system/events.go index b18955611e1..cb313eca2a7 100644 --- a/pkg/cmd/system/events.go +++ b/pkg/cmd/system/events.go @@ -29,8 +29,8 @@ import ( _ "github.com/containerd/containerd/api/events" // Register grpc event types "github.com/containerd/containerd/events" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/typeurl/v2" ) diff --git a/pkg/cmd/system/info.go b/pkg/cmd/system/info.go index 77aa78cb2b6..5e87cf24fc4 100644 --- a/pkg/cmd/system/info.go +++ b/pkg/cmd/system/info.go @@ -26,17 +26,17 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" "golang.org/x/text/cases" "golang.org/x/text/language" "github.com/containerd/containerd/api/services/introspection/v1" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/docker/go-units" ) diff --git a/pkg/cmd/system/prune.go b/pkg/cmd/system/prune.go index 94c941a48aa..efc1d934261 100644 --- a/pkg/cmd/system/prune.go +++ b/pkg/cmd/system/prune.go @@ -21,12 +21,12 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/cmd/builder" - "github.com/containerd/nerdctl/pkg/cmd/container" - "github.com/containerd/nerdctl/pkg/cmd/image" - "github.com/containerd/nerdctl/pkg/cmd/network" - "github.com/containerd/nerdctl/pkg/cmd/volume" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/builder" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/cmd/network" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" ) // Prune will remove all unused containers, networks, diff --git a/pkg/cmd/volume/create.go b/pkg/cmd/volume/create.go index 77290f9d666..c00fe00efa3 100644 --- a/pkg/cmd/volume/create.go +++ b/pkg/cmd/volume/create.go @@ -20,10 +20,10 @@ import ( "fmt" "github.com/containerd/containerd/identifiers" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/docker/docker/pkg/stringid" ) diff --git a/pkg/cmd/volume/inspect.go b/pkg/cmd/volume/inspect.go index 78221c6bd56..4c9442ed286 100644 --- a/pkg/cmd/volume/inspect.go +++ b/pkg/cmd/volume/inspect.go @@ -17,8 +17,8 @@ package volume import ( - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/formatter" ) func Inspect(volumes []string, options types.VolumeInspectOptions) error { diff --git a/pkg/cmd/volume/list.go b/pkg/cmd/volume/list.go index b10ad9d3cca..a0e275a10c0 100644 --- a/pkg/cmd/volume/list.go +++ b/pkg/cmd/volume/list.go @@ -27,9 +27,9 @@ import ( "github.com/containerd/containerd/pkg/progress" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) type volumePrintable struct { diff --git a/pkg/cmd/volume/prune.go b/pkg/cmd/volume/prune.go index cc7faa85b5b..d8161be8bfa 100644 --- a/pkg/cmd/volume/prune.go +++ b/pkg/cmd/volume/prune.go @@ -21,8 +21,8 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/labels" ) func Prune(ctx context.Context, client *containerd.Client, options types.VolumePruneOptions) error { diff --git a/pkg/cmd/volume/rm.go b/pkg/cmd/volume/rm.go index 98a5a44c4bb..e25a3ff19a8 100644 --- a/pkg/cmd/volume/rm.go +++ b/pkg/cmd/volume/rm.go @@ -22,10 +22,10 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/mountutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/mountutil" ) func Remove(ctx context.Context, client *containerd.Client, volumes []string, options types.VolumeRemoveOptions) error { diff --git a/pkg/cmd/volume/volume.go b/pkg/cmd/volume/volume.go index 6efb1a7b46b..1a6fc9f16f1 100644 --- a/pkg/cmd/volume/volume.go +++ b/pkg/cmd/volume/volume.go @@ -17,8 +17,8 @@ package volume import ( - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/mountutil/volumestore" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) // Store returns a volume store diff --git a/pkg/composer/build.go b/pkg/composer/build.go index 1fe7b72837c..8f34835bc3b 100644 --- a/pkg/composer/build.go +++ b/pkg/composer/build.go @@ -23,7 +23,7 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" ) type BuildOptions struct { diff --git a/pkg/composer/composer.go b/pkg/composer/composer.go index 2c5bd4d2e8c..2ebadc4407e 100644 --- a/pkg/composer/composer.go +++ b/pkg/composer/composer.go @@ -28,8 +28,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/identifiers" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/reflectutil" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) // Options groups the command line options recommended for a Compose implementation (ProjectOptions) and extra options for nerdctl diff --git a/pkg/composer/container.go b/pkg/composer/container.go index 33b4b699775..3a0169e74dc 100644 --- a/pkg/composer/container.go +++ b/pkg/composer/container.go @@ -22,7 +22,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/labels" ) func (c *Composer) Containers(ctx context.Context, services ...string) ([]containerd.Container, error) { diff --git a/pkg/composer/copy.go b/pkg/composer/copy.go index 76caeead512..0442b5775ae 100644 --- a/pkg/composer/copy.go +++ b/pkg/composer/copy.go @@ -24,7 +24,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/docker/docker/pkg/system" ) diff --git a/pkg/composer/create.go b/pkg/composer/create.go index 7a62f24fa1e..97112f27744 100644 --- a/pkg/composer/create.go +++ b/pkg/composer/create.go @@ -25,8 +25,8 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/labels" "golang.org/x/sync/errgroup" ) diff --git a/pkg/composer/down.go b/pkg/composer/down.go index 2b40e5d9073..3ea0221d209 100644 --- a/pkg/composer/down.go +++ b/pkg/composer/down.go @@ -21,7 +21,7 @@ import ( "fmt" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) type DownOptions struct { diff --git a/pkg/composer/exec.go b/pkg/composer/exec.go index 95ffee05620..1d8ab64f069 100644 --- a/pkg/composer/exec.go +++ b/pkg/composer/exec.go @@ -26,8 +26,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/labels" ) // ExecOptions stores options passed from users as flags and args. diff --git a/pkg/composer/logs.go b/pkg/composer/logs.go index c6109bdb2fb..21cb4fb5623 100644 --- a/pkg/composer/logs.go +++ b/pkg/composer/logs.go @@ -26,9 +26,9 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/pipetagger" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/composer/pipetagger" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/labels" ) type LogsOptions struct { diff --git a/pkg/composer/orphans.go b/pkg/composer/orphans.go index 2466d4ca174..2df49253132 100644 --- a/pkg/composer/orphans.go +++ b/pkg/composer/orphans.go @@ -21,8 +21,8 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/labels" ) func (c *Composer) getOrphanContainers(ctx context.Context, parsedServices []*serviceparser.Service) ([]containerd.Container, error) { diff --git a/pkg/composer/pause.go b/pkg/composer/pause.go index 51a05503b62..4817a5710d6 100644 --- a/pkg/composer/pause.go +++ b/pkg/composer/pause.go @@ -23,8 +23,8 @@ import ( "sync" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/containerutil" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/labels" "golang.org/x/sync/errgroup" ) diff --git a/pkg/composer/port.go b/pkg/composer/port.go index 12676eb981f..750ee8ae970 100644 --- a/pkg/composer/port.go +++ b/pkg/composer/port.go @@ -21,7 +21,7 @@ import ( "fmt" "io" - "github.com/containerd/nerdctl/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/containerutil" ) // PortOptions has args for getting the public port of a given private port/protocol diff --git a/pkg/composer/pull.go b/pkg/composer/pull.go index 62e5c683178..1036df783ba 100644 --- a/pkg/composer/pull.go +++ b/pkg/composer/pull.go @@ -23,7 +23,7 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" ) type PullOptions struct { diff --git a/pkg/composer/push.go b/pkg/composer/push.go index eabec25db97..ae8f580a6bb 100644 --- a/pkg/composer/push.go +++ b/pkg/composer/push.go @@ -23,7 +23,7 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" ) type PushOptions struct { diff --git a/pkg/composer/restart.go b/pkg/composer/restart.go index c473cf71eff..a2d430b3603 100644 --- a/pkg/composer/restart.go +++ b/pkg/composer/restart.go @@ -24,7 +24,7 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/labels" ) // RestartOptions stores all option input from `nerdctl compose restart` diff --git a/pkg/composer/rm.go b/pkg/composer/rm.go index 2ad1b798fb8..86cae7c9000 100644 --- a/pkg/composer/rm.go +++ b/pkg/composer/rm.go @@ -23,10 +23,10 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) // RemoveOptions stores all options when removing compose containers: diff --git a/pkg/composer/run.go b/pkg/composer/run.go index 5c065d7f5ef..58c8fc13727 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -25,8 +25,8 @@ import ( "github.com/compose-spec/compose-go/loader" "github.com/compose-spec/compose-go/types" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/idgen" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/idgen" "golang.org/x/sync/errgroup" ) diff --git a/pkg/composer/serviceparser/build.go b/pkg/composer/serviceparser/build.go index 6859af2e95e..ed0046a95ed 100644 --- a/pkg/composer/serviceparser/build.go +++ b/pkg/composer/serviceparser/build.go @@ -26,7 +26,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/reflectutil" + "github.com/containerd/nerdctl/v2/pkg/reflectutil" securejoin "github.com/cyphar/filepath-securejoin" ) diff --git a/pkg/composer/serviceparser/build_test.go b/pkg/composer/serviceparser/build_test.go index d0411054a94..55d2ecc2e87 100644 --- a/pkg/composer/serviceparser/build_test.go +++ b/pkg/composer/serviceparser/build_test.go @@ -19,8 +19,8 @@ package serviceparser import ( "testing" - "github.com/containerd/nerdctl/pkg/composer/projectloader" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/composer/projectloader" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index b914437b250..60dd5ee8d86 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -32,7 +32,7 @@ import ( "github.com/containerd/containerd/contrib/nvidia" "github.com/containerd/containerd/identifiers" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/reflectutil" + "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) // ComposeExtensionKey defines fields used to implement extension features. diff --git a/pkg/composer/serviceparser/serviceparser_test.go b/pkg/composer/serviceparser/serviceparser_test.go index 72d96b1ab09..ca363e7c49b 100644 --- a/pkg/composer/serviceparser/serviceparser_test.go +++ b/pkg/composer/serviceparser/serviceparser_test.go @@ -24,9 +24,9 @@ import ( "testing" "github.com/compose-spec/compose-go/types" - "github.com/containerd/nerdctl/pkg/composer/projectloader" - "github.com/containerd/nerdctl/pkg/strutil" - "github.com/containerd/nerdctl/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/composer/projectloader" + "github.com/containerd/nerdctl/v2/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/pkg/composer/stop.go b/pkg/composer/stop.go index 6df54863815..6baa0f9edb2 100644 --- a/pkg/composer/stop.go +++ b/pkg/composer/stop.go @@ -23,9 +23,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) // StopOptions stores all option input from `nerdctl compose stop` diff --git a/pkg/composer/up.go b/pkg/composer/up.go index 3e65ba89a71..eb2239476cd 100644 --- a/pkg/composer/up.go +++ b/pkg/composer/up.go @@ -23,8 +23,8 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/reflectutil" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) type UpOptions struct { diff --git a/pkg/composer/up_network.go b/pkg/composer/up_network.go index 32d35bb7d77..65ffdd7dd1d 100644 --- a/pkg/composer/up_network.go +++ b/pkg/composer/up_network.go @@ -21,8 +21,8 @@ import ( "fmt" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/reflectutil" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) func (c *Composer) upNetwork(ctx context.Context, shortName string) error { diff --git a/pkg/composer/up_service.go b/pkg/composer/up_service.go index 32f1e3b52a2..ce4a5d798b3 100644 --- a/pkg/composer/up_service.go +++ b/pkg/composer/up_service.go @@ -26,8 +26,8 @@ import ( "sync" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/composer/serviceparser" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/labels" "golang.org/x/sync/errgroup" ) diff --git a/pkg/composer/up_volume.go b/pkg/composer/up_volume.go index b1578b89a03..11f0417b5dc 100644 --- a/pkg/composer/up_volume.go +++ b/pkg/composer/up_volume.go @@ -21,8 +21,8 @@ import ( "fmt" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/reflectutil" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) func (c *Composer) upVolume(ctx context.Context, shortName string) error { diff --git a/pkg/config/config.go b/pkg/config/config.go index e393933779d..6c3273f9ea5 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -20,7 +20,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/defaults" "github.com/containerd/containerd/namespaces" - ncdefaults "github.com/containerd/nerdctl/pkg/defaults" + ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" ) // Config corresponds to nerdctl.toml . diff --git a/pkg/containerinspector/containerinspector.go b/pkg/containerinspector/containerinspector.go index 4ff3624c4c1..c60f90baca3 100644 --- a/pkg/containerinspector/containerinspector.go +++ b/pkg/containerinspector/containerinspector.go @@ -22,7 +22,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/typeurl/v2" ) diff --git a/pkg/containerinspector/containerinspector_freebsd.go b/pkg/containerinspector/containerinspector_freebsd.go index c9c53558955..e5a2dbc42fb 100644 --- a/pkg/containerinspector/containerinspector_freebsd.go +++ b/pkg/containerinspector/containerinspector_freebsd.go @@ -19,7 +19,7 @@ package containerinspector import ( "context" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) func InspectNetNS(ctx context.Context, pid int) (*native.NetNS, error) { diff --git a/pkg/containerinspector/containerinspector_linux.go b/pkg/containerinspector/containerinspector_linux.go index b409166d85e..2bf39fd5d56 100644 --- a/pkg/containerinspector/containerinspector_linux.go +++ b/pkg/containerinspector/containerinspector_linux.go @@ -22,7 +22,7 @@ import ( "net" "strings" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containernetworking/plugins/pkg/ns" ) diff --git a/pkg/containerinspector/containerinspector_windows.go b/pkg/containerinspector/containerinspector_windows.go index c9c53558955..e5a2dbc42fb 100644 --- a/pkg/containerinspector/containerinspector_windows.go +++ b/pkg/containerinspector/containerinspector_windows.go @@ -19,7 +19,7 @@ package containerinspector import ( "context" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) func InspectNetNS(ctx context.Context, pid int) (*native.NetNS, error) { diff --git a/pkg/containerutil/config.go b/pkg/containerutil/config.go index dfe4ec47e93..44bf50286dc 100644 --- a/pkg/containerutil/config.go +++ b/pkg/containerutil/config.go @@ -26,8 +26,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/netutil/nettype" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 67a49f2dd88..6dc57f2f08a 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -30,15 +30,15 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" - "github.com/containerd/nerdctl/pkg/idutil/containerwalker" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/mountutil" - "github.com/containerd/nerdctl/pkg/netutil" - "github.com/containerd/nerdctl/pkg/netutil/nettype" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/mountutil" + "github.com/containerd/nerdctl/v2/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/containerutil/container_network_manager_linux.go b/pkg/containerutil/container_network_manager_linux.go index 4702b2ce81b..e4d058f856f 100644 --- a/pkg/containerutil/container_network_manager_linux.go +++ b/pkg/containerutil/container_network_manager_linux.go @@ -25,13 +25,13 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/oci" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/clientutil" - "github.com/containerd/nerdctl/pkg/dnsutil" - "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" - "github.com/containerd/nerdctl/pkg/netutil" - "github.com/containerd/nerdctl/pkg/resolvconf" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/dnsutil" + "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" + "github.com/containerd/nerdctl/v2/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/resolvconf" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) type cniNetworkManagerPlatform struct { diff --git a/pkg/containerutil/container_network_manager_other.go b/pkg/containerutil/container_network_manager_other.go index af6c337e8b8..914a3553c1a 100644 --- a/pkg/containerutil/container_network_manager_other.go +++ b/pkg/containerutil/container_network_manager_other.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) type cniNetworkManagerPlatform struct { diff --git a/pkg/containerutil/container_network_manager_windows.go b/pkg/containerutil/container_network_manager_windows.go index 774c737ac82..ba7304c30f5 100644 --- a/pkg/containerutil/container_network_manager_windows.go +++ b/pkg/containerutil/container_network_manager_windows.go @@ -25,9 +25,9 @@ import ( "github.com/containerd/containerd/pkg/netns" gocni "github.com/containerd/go-cni" - "github.com/containerd/nerdctl/pkg/api/types" - "github.com/containerd/nerdctl/pkg/netutil" - "github.com/containerd/nerdctl/pkg/ocihook" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/ocihook" ) type cniNetworkManagerPlatform struct { diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 23d03545177..ad05e8fab5d 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -35,15 +35,15 @@ import ( "github.com/containerd/containerd/oci" "github.com/containerd/containerd/runtime/restart" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/consoleutil" - "github.com/containerd/nerdctl/pkg/errutil" - "github.com/containerd/nerdctl/pkg/formatter" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/nsutil" - "github.com/containerd/nerdctl/pkg/portutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/signalutil" - "github.com/containerd/nerdctl/pkg/taskutil" + "github.com/containerd/nerdctl/v2/pkg/consoleutil" + "github.com/containerd/nerdctl/v2/pkg/errutil" + "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/nsutil" + "github.com/containerd/nerdctl/v2/pkg/portutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/signalutil" + "github.com/containerd/nerdctl/v2/pkg/taskutil" "github.com/moby/sys/signal" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/containerutil/cp_linux.go b/pkg/containerutil/cp_linux.go index 21fb413701b..7e6ed4928b7 100644 --- a/pkg/containerutil/cp_linux.go +++ b/pkg/containerutil/cp_linux.go @@ -32,8 +32,8 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/mount" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/tarutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/tarutil" securejoin "github.com/cyphar/filepath-securejoin" ) diff --git a/pkg/defaults/cgroup_linux.go b/pkg/defaults/cgroup_linux.go index caaae236e61..2a3963c52ee 100644 --- a/pkg/defaults/cgroup_linux.go +++ b/pkg/defaults/cgroup_linux.go @@ -20,7 +20,7 @@ import ( "os" "github.com/containerd/cgroups/v3" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) func IsSystemdAvailable() bool { diff --git a/pkg/defaults/defaults_linux.go b/pkg/defaults/defaults_linux.go index 63f35ab93e5..76c5ffa60a5 100644 --- a/pkg/defaults/defaults_linux.go +++ b/pkg/defaults/defaults_linux.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd/plugin" gocni "github.com/containerd/go-cni" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) const ( diff --git a/pkg/dnsutil/dnsutil.go b/pkg/dnsutil/dnsutil.go index acbfc68c7c4..433a19b324b 100644 --- a/pkg/dnsutil/dnsutil.go +++ b/pkg/dnsutil/dnsutil.go @@ -19,7 +19,7 @@ package dnsutil import ( "context" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) func GetSlirp4netnsDNS() ([]string, error) { diff --git a/pkg/dnsutil/hostsstore/hostsstore.go b/pkg/dnsutil/hostsstore/hostsstore.go index 40a7726e66d..1edb5256331 100644 --- a/pkg/dnsutil/hostsstore/hostsstore.go +++ b/pkg/dnsutil/hostsstore/hostsstore.go @@ -25,7 +25,7 @@ import ( "path/filepath" "github.com/containerd/containerd/errdefs" - "github.com/containerd/nerdctl/pkg/lockutil" + "github.com/containerd/nerdctl/v2/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..2ce10385ca1 100644 --- a/pkg/dnsutil/hostsstore/updater.go +++ b/pkg/dnsutil/hostsstore/updater.go @@ -26,7 +26,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/netutil" ) // newUpdater creates an updater for hostsD (/var/lib/nerdctl//etchosts) diff --git a/pkg/flagutil/flagutil.go b/pkg/flagutil/flagutil.go index 064b8a8ab1a..663a5746161 100644 --- a/pkg/flagutil/flagutil.go +++ b/pkg/flagutil/flagutil.go @@ -23,7 +23,7 @@ import ( "os" "strings" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) // ReplaceOrAppendEnvValues returns the defaults with the overrides either diff --git a/pkg/formatter/formatter.go b/pkg/formatter/formatter.go index f8374ff94e8..e8258bde35a 100644 --- a/pkg/formatter/formatter.go +++ b/pkg/formatter/formatter.go @@ -33,7 +33,7 @@ import ( "github.com/containerd/containerd/oci" "github.com/containerd/containerd/runtime/restart" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/portutil" + "github.com/containerd/nerdctl/v2/pkg/portutil" "github.com/docker/go-units" ) diff --git a/pkg/idutil/containerwalker/containerwalker.go b/pkg/idutil/containerwalker/containerwalker.go index d90896e894b..94c497e9f10 100644 --- a/pkg/idutil/containerwalker/containerwalker.go +++ b/pkg/idutil/containerwalker/containerwalker.go @@ -23,7 +23,7 @@ import ( "strings" "github.com/containerd/containerd" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/labels" ) type Found struct { diff --git a/pkg/idutil/imagewalker/imagewalker.go b/pkg/idutil/imagewalker/imagewalker.go index a67f9e58051..68f8c9fe269 100644 --- a/pkg/idutil/imagewalker/imagewalker.go +++ b/pkg/idutil/imagewalker/imagewalker.go @@ -24,7 +24,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" - "github.com/containerd/nerdctl/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/opencontainers/go-digest" ) diff --git a/pkg/idutil/netwalker/netwalker.go b/pkg/idutil/netwalker/netwalker.go index cd92d4eaa89..40debd9bfd2 100644 --- a/pkg/idutil/netwalker/netwalker.go +++ b/pkg/idutil/netwalker/netwalker.go @@ -22,7 +22,7 @@ import ( "regexp" "strings" - "github.com/containerd/nerdctl/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/netutil" ) type Found struct { diff --git a/pkg/imageinspector/imageinspector.go b/pkg/imageinspector/imageinspector.go index 3fff0bd5abe..239720e154f 100644 --- a/pkg/imageinspector/imageinspector.go +++ b/pkg/imageinspector/imageinspector.go @@ -22,8 +22,8 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" "github.com/containerd/log" - imgutil "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" + imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) // Inspect inspects the image, for the platform specified in image.platform. diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index 81bd0d6a425..38c866929c5 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -38,8 +38,8 @@ import ( "github.com/containerd/containerd/rootfs" "github.com/containerd/containerd/snapshots" "github.com/containerd/log" - imgutil "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/labels" + imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/labels" "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..aee052bc07f 100644 --- a/pkg/imgutil/converter/zstd.go +++ b/pkg/imgutil/converter/zstd.go @@ -27,7 +27,7 @@ import ( "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/images/converter/uncompress" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/klauspost/compress/zstd" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index 898b6f1c1e2..ad31d0617e4 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -27,7 +27,7 @@ import ( "github.com/containerd/containerd/images" dockerreference "github.com/containerd/containerd/reference/docker" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) // Filter types supported to filter images. diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 9dd63502cff..356836eae29 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -33,10 +33,10 @@ import ( "github.com/containerd/imgcrypt" "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/errutil" - "github.com/containerd/nerdctl/pkg/idutil/imagewalker" - "github.com/containerd/nerdctl/pkg/imgutil/dockerconfigresolver" - "github.com/containerd/nerdctl/pkg/imgutil/pull" + "github.com/containerd/nerdctl/v2/pkg/errutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" + "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" + "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" "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/pull/pull.go b/pkg/imgutil/pull/pull.go index bbe18bf792a..dae303eaa1c 100644 --- a/pkg/imgutil/pull/pull.go +++ b/pkg/imgutil/pull/pull.go @@ -25,8 +25,8 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/remotes" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/imgutil/jobs" - "github.com/containerd/nerdctl/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil/jobs" + "github.com/containerd/nerdctl/v2/pkg/platformutil" 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..36b1774d741 100644 --- a/pkg/imgutil/push/push.go +++ b/pkg/imgutil/push/push.go @@ -32,7 +32,7 @@ import ( "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/nerdctl/v2/pkg/imgutil/jobs" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "golang.org/x/sync/errgroup" diff --git a/pkg/imgutil/snapshotter.go b/pkg/imgutil/snapshotter.go index 694ea518e19..46ff8b5f3ac 100644 --- a/pkg/imgutil/snapshotter.go +++ b/pkg/imgutil/snapshotter.go @@ -24,7 +24,7 @@ import ( "github.com/containerd/containerd/images" ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/imgutil/pull" + "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" "github.com/containerd/stargz-snapshotter/fs/source" ) diff --git a/pkg/imgutil/snapshotter_test.go b/pkg/imgutil/snapshotter_test.go index f50c863c296..f09da014012 100644 --- a/pkg/imgutil/snapshotter_test.go +++ b/pkg/imgutil/snapshotter_test.go @@ -23,7 +23,7 @@ import ( "github.com/containerd/containerd" ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" - "github.com/containerd/nerdctl/pkg/imgutil/pull" + "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "gotest.tools/v3/assert" diff --git a/pkg/infoutil/infoutil.go b/pkg/infoutil/infoutil.go index e5eb2efddab..3b4c57e6968 100644 --- a/pkg/infoutil/infoutil.go +++ b/pkg/infoutil/infoutil.go @@ -30,11 +30,11 @@ import ( ptypes "github.com/containerd/containerd/protobuf/types" "github.com/containerd/containerd/services/introspection" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/buildkitutil" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/pkg/logging" - "github.com/containerd/nerdctl/pkg/version" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/logging" + "github.com/containerd/nerdctl/v2/pkg/version" ) func NativeDaemonInfo(ctx context.Context, client *containerd.Client) (*native.DaemonInfo, error) { diff --git a/pkg/infoutil/infoutil_freebsd.go b/pkg/infoutil/infoutil_freebsd.go index ca8d67c6eaa..4cf753ad9e4 100644 --- a/pkg/infoutil/infoutil_freebsd.go +++ b/pkg/infoutil/infoutil_freebsd.go @@ -17,7 +17,7 @@ package infoutil import ( - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/docker/docker/pkg/sysinfo" ) diff --git a/pkg/infoutil/infoutil_linux.go b/pkg/infoutil/infoutil_linux.go index 2ed28e22aa9..8dbe95274b5 100644 --- a/pkg/infoutil/infoutil_linux.go +++ b/pkg/infoutil/infoutil_linux.go @@ -21,10 +21,10 @@ import ( "strings" "github.com/containerd/cgroups/v3" - "github.com/containerd/nerdctl/pkg/apparmorutil" - "github.com/containerd/nerdctl/pkg/defaults" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" + "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/docker/docker/pkg/meminfo" "github.com/docker/docker/pkg/sysinfo" ) diff --git a/pkg/infoutil/infoutil_test.go b/pkg/infoutil/infoutil_test.go index 632e9dd03c6..ebf6d367cf3 100644 --- a/pkg/infoutil/infoutil_test.go +++ b/pkg/infoutil/infoutil_test.go @@ -19,7 +19,7 @@ package infoutil import ( "testing" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "gotest.tools/v3/assert" ) diff --git a/pkg/infoutil/infoutil_windows.go b/pkg/infoutil/infoutil_windows.go index 3131731eb3a..7612bd2015a 100644 --- a/pkg/infoutil/infoutil_windows.go +++ b/pkg/infoutil/infoutil_windows.go @@ -17,7 +17,7 @@ package infoutil import ( - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/docker/docker/pkg/sysinfo" ) diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index 2312274f9af..a344a2e9ec3 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -39,9 +39,9 @@ import ( "github.com/containerd/containerd/runtime/restart" gocni "github.com/containerd/go-cni" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/docker/go-connections/nat" "github.com/opencontainers/runtime-spec/specs-go" "github.com/tidwall/gjson" diff --git a/pkg/ipfs/image.go b/pkg/ipfs/image.go index 0519eefbf15..ffe2db4eb34 100644 --- a/pkg/ipfs/image.go +++ b/pkg/ipfs/image.go @@ -27,10 +27,10 @@ import ( "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/remotes" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/idutil/imagewalker" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/platformutil" - "github.com/containerd/nerdctl/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/stargz-snapshotter/ipfs" ipfsclient "github.com/containerd/stargz-snapshotter/ipfs/client" "github.com/docker/docker/errdefs" diff --git a/pkg/logging/cri_logger.go b/pkg/logging/cri_logger.go index 9865a99d6c1..c3c3b35efc3 100644 --- a/pkg/logging/cri_logger.go +++ b/pkg/logging/cri_logger.go @@ -34,7 +34,7 @@ import ( "time" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/logging/tail" + "github.com/containerd/nerdctl/v2/pkg/logging/tail" ) // LogStreamType is the type of the stream in CRI container log. diff --git a/pkg/logging/fluentd_logger.go b/pkg/logging/fluentd_logger.go index 9abf9157962..5cc12e76c73 100644 --- a/pkg/logging/fluentd_logger.go +++ b/pkg/logging/fluentd_logger.go @@ -28,7 +28,7 @@ import ( "github.com/containerd/containerd/runtime/v2/logging" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/fluent/fluent-logger-golang/fluent" ) diff --git a/pkg/logging/journald_logger.go b/pkg/logging/journald_logger.go index d5617eb8e97..02d49b0c411 100644 --- a/pkg/logging/journald_logger.go +++ b/pkg/logging/journald_logger.go @@ -30,7 +30,7 @@ import ( "github.com/containerd/containerd/runtime/v2/logging" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/coreos/go-systemd/v22/journal" "github.com/docker/cli/templates" timetypes "github.com/docker/docker/api/types/time" diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index 88c8555d3e0..f30511897d2 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -28,8 +28,8 @@ import ( "github.com/containerd/containerd/runtime/v2/logging" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/logging/jsonfile" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/logging/jsonfile" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/docker/go-units" "github.com/fahedouch/go-logrotate" ) diff --git a/pkg/logging/log_viewer.go b/pkg/logging/log_viewer.go index b96670ac160..891086bc47c 100644 --- a/pkg/logging/log_viewer.go +++ b/pkg/logging/log_viewer.go @@ -24,7 +24,7 @@ import ( "path/filepath" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/labels/k8slabels" + "github.com/containerd/nerdctl/v2/pkg/labels/k8slabels" ) // Type alias for functions which write out logs to the provided stdout/stderr Writers. diff --git a/pkg/logging/syslog_logger.go b/pkg/logging/syslog_logger.go index c5108e821b1..398d3a8ea67 100644 --- a/pkg/logging/syslog_logger.go +++ b/pkg/logging/syslog_logger.go @@ -32,7 +32,7 @@ import ( syslog "github.com/yuchanns/srslog" "github.com/containerd/containerd/runtime/v2/logging" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) const ( diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index bb938d073a8..f8e184033b0 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -29,9 +29,9 @@ import ( "github.com/containerd/containerd/oci" "github.com/containerd/containerd/pkg/userns" "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/containerd/nerdctl/v2/pkg/idgen" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/mountutil/mountutil_freebsd.go b/pkg/mountutil/mountutil_freebsd.go index 637bdfebc2b..dd9433af559 100644 --- a/pkg/mountutil/mountutil_freebsd.go +++ b/pkg/mountutil/mountutil_freebsd.go @@ -23,7 +23,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/mountutil/volumestore" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) const ( diff --git a/pkg/mountutil/mountutil_linux.go b/pkg/mountutil/mountutil_linux.go index ef46bdd6de1..d42112a2073 100644 --- a/pkg/mountutil/mountutil_linux.go +++ b/pkg/mountutil/mountutil_linux.go @@ -29,7 +29,7 @@ import ( "github.com/containerd/containerd/mount" "github.com/containerd/containerd/oci" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/mountutil/volumestore" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" "github.com/docker/go-units" mobymount "github.com/moby/sys/mount" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/pkg/mountutil/mountutil_linux_test.go b/pkg/mountutil/mountutil_linux_test.go index c707837ea29..956dcd40447 100644 --- a/pkg/mountutil/mountutil_linux_test.go +++ b/pkg/mountutil/mountutil_linux_test.go @@ -23,8 +23,8 @@ import ( "github.com/containerd/containerd/mount" "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - mocks "github.com/containerd/nerdctl/pkg/mountutil/mountutilmock" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + mocks "github.com/containerd/nerdctl/v2/pkg/mountutil/mountutilmock" "github.com/opencontainers/runtime-spec/specs-go" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" diff --git a/pkg/mountutil/mountutil_other.go b/pkg/mountutil/mountutil_other.go index 184926a1354..eed4431382a 100644 --- a/pkg/mountutil/mountutil_other.go +++ b/pkg/mountutil/mountutil_other.go @@ -23,7 +23,7 @@ import ( "path/filepath" "strings" - "github.com/containerd/nerdctl/pkg/mountutil/volumestore" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) func splitVolumeSpec(s string) ([]string, error) { diff --git a/pkg/mountutil/mountutil_windows.go b/pkg/mountutil/mountutil_windows.go index 35faafb72ee..eee76ba40b6 100644 --- a/pkg/mountutil/mountutil_windows.go +++ b/pkg/mountutil/mountutil_windows.go @@ -34,7 +34,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/mountutil/volumestore" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) const ( diff --git a/pkg/mountutil/mountutil_windows_test.go b/pkg/mountutil/mountutil_windows_test.go index ed69dfdf96b..81322f9b8c6 100644 --- a/pkg/mountutil/mountutil_windows_test.go +++ b/pkg/mountutil/mountutil_windows_test.go @@ -21,8 +21,8 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - mocks "github.com/containerd/nerdctl/pkg/mountutil/mountutilmock" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + mocks "github.com/containerd/nerdctl/v2/pkg/mountutil/mountutilmock" "github.com/opencontainers/runtime-spec/specs-go" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" diff --git a/pkg/mountutil/mountutilmock/volumestore.mock.go b/pkg/mountutil/mountutilmock/volumestore.mock.go index 427d6138b55..b5c933cd125 100644 --- a/pkg/mountutil/mountutilmock/volumestore.mock.go +++ b/pkg/mountutil/mountutilmock/volumestore.mock.go @@ -19,7 +19,7 @@ package mountutilmock import ( "reflect" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "go.uber.org/mock/gomock" ) diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index f645a167e71..48fbbfa5397 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -24,9 +24,9 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/pkg/lockutil" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/lockutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) // Path returns a string like `/var/lib/nerdctl/1935db59/volumes/default`. diff --git a/pkg/namestore/namestore.go b/pkg/namestore/namestore.go index 1ab9b4b3b18..73e073b911a 100644 --- a/pkg/namestore/namestore.go +++ b/pkg/namestore/namestore.go @@ -23,7 +23,7 @@ import ( "strings" "github.com/containerd/containerd/identifiers" - "github.com/containerd/nerdctl/pkg/lockutil" + "github.com/containerd/nerdctl/v2/pkg/lockutil" ) func New(dataStore, ns string) (NameStore, error) { diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index f6e0079cd9f..1a29d7dc67d 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -34,11 +34,11 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/namespaces" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/lockutil" - "github.com/containerd/nerdctl/pkg/netutil/nettype" - subnetutil "github.com/containerd/nerdctl/pkg/netutil/subnet" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/lockutil" + "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" + subnetutil "github.com/containerd/nerdctl/v2/pkg/netutil/subnet" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containernetworking/cni/libcni" ) diff --git a/pkg/netutil/netutil_linux_test.go b/pkg/netutil/netutil_linux_test.go index d3c090072a4..1f64dbbd5af 100644 --- a/pkg/netutil/netutil_linux_test.go +++ b/pkg/netutil/netutil_linux_test.go @@ -21,7 +21,7 @@ package netutil import ( "testing" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) // Tests whether nerdctl properly creates the default network when required. diff --git a/pkg/netutil/netutil_test.go b/pkg/netutil/netutil_test.go index c102f281999..c3f692c397f 100644 --- a/pkg/netutil/netutil_test.go +++ b/pkg/netutil/netutil_test.go @@ -26,9 +26,9 @@ import ( "testing" "text/template" - ncdefaults "github.com/containerd/nerdctl/pkg/defaults" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/testutil" + ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index d149a1e9ebd..d935f0972ec 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -30,9 +30,9 @@ import ( "github.com/Masterminds/semver/v3" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/defaults" - "github.com/containerd/nerdctl/pkg/strutil" - "github.com/containerd/nerdctl/pkg/systemutil" + "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/systemutil" "github.com/mitchellh/mapstructure" "github.com/vishvananda/netlink" ) diff --git a/pkg/nsutil/nsutil_test.go b/pkg/nsutil/nsutil_test.go index 4c3645faf6e..7b6f19a8933 100644 --- a/pkg/nsutil/nsutil_test.go +++ b/pkg/nsutil/nsutil_test.go @@ -19,7 +19,7 @@ package nsutil_test import ( "testing" - "github.com/containerd/nerdctl/pkg/nsutil" + "github.com/containerd/nerdctl/v2/pkg/nsutil" "gotest.tools/v3/assert" ) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 222993c709c..1cd9b86e4ce 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -29,13 +29,13 @@ import ( gocni "github.com/containerd/go-cni" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/bypass4netnsutil" - "github.com/containerd/nerdctl/pkg/dnsutil/hostsstore" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/namestore" - "github.com/containerd/nerdctl/pkg/netutil" - "github.com/containerd/nerdctl/pkg/netutil/nettype" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/bypass4netnsutil" + "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/namestore" + "github.com/containerd/nerdctl/v2/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" types100 "github.com/containernetworking/cni/pkg/types/100" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/pkg/ocihook/ocihook_linux.go b/pkg/ocihook/ocihook_linux.go index fd9d7878c85..43cd714046d 100644 --- a/pkg/ocihook/ocihook_linux.go +++ b/pkg/ocihook/ocihook_linux.go @@ -19,8 +19,8 @@ package ocihook import ( "github.com/containerd/containerd/contrib/apparmor" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/apparmorutil" - "github.com/containerd/nerdctl/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" + "github.com/containerd/nerdctl/v2/pkg/defaults" ) func loadAppArmor() { diff --git a/pkg/ocihook/rootless_linux.go b/pkg/ocihook/rootless_linux.go index 2b1f4db7730..582ad76f0d3 100644 --- a/pkg/ocihook/rootless_linux.go +++ b/pkg/ocihook/rootless_linux.go @@ -20,7 +20,7 @@ import ( "context" gocni "github.com/containerd/go-cni" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" rlkclient "github.com/rootless-containers/rootlesskit/pkg/api/client" ) diff --git a/pkg/platformutil/platformutil.go b/pkg/platformutil/platformutil.go index 13e90dcdc15..fc5cc6f6296 100644 --- a/pkg/platformutil/platformutil.go +++ b/pkg/platformutil/platformutil.go @@ -20,7 +20,7 @@ import ( "fmt" "github.com/containerd/containerd/platforms" - "github.com/containerd/nerdctl/pkg/strutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/portutil/port_allocate_linux.go b/pkg/portutil/port_allocate_linux.go index 75ae344a58d..bd396a52555 100644 --- a/pkg/portutil/port_allocate_linux.go +++ b/pkg/portutil/port_allocate_linux.go @@ -19,8 +19,8 @@ package portutil import ( "fmt" - "github.com/containerd/nerdctl/pkg/portutil/iptable" - "github.com/containerd/nerdctl/pkg/portutil/procnet" + "github.com/containerd/nerdctl/v2/pkg/portutil/iptable" + "github.com/containerd/nerdctl/v2/pkg/portutil/procnet" ) const ( diff --git a/pkg/portutil/portutil.go b/pkg/portutil/portutil.go index c8c132717e0..f0ffe9b96de 100644 --- a/pkg/portutil/portutil.go +++ b/pkg/portutil/portutil.go @@ -24,8 +24,8 @@ import ( gocni "github.com/containerd/go-cni" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/docker/go-connections/nat" ) diff --git a/pkg/portutil/portutil_test.go b/pkg/portutil/portutil_test.go index 8b15c07596c..87f0f5dc892 100644 --- a/pkg/portutil/portutil_test.go +++ b/pkg/portutil/portutil_test.go @@ -23,8 +23,8 @@ import ( "testing" gocni "github.com/containerd/go-cni" - "github.com/containerd/nerdctl/pkg/labels" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) func TestTestParseFlagPWithPlatformSpec(t *testing.T) { diff --git a/pkg/signutil/cosignutil.go b/pkg/signutil/cosignutil.go index 2932353e0c8..8a3a3b26417 100644 --- a/pkg/signutil/cosignutil.go +++ b/pkg/signutil/cosignutil.go @@ -25,7 +25,7 @@ import ( "strings" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil" ) // SignCosign signs an image(`rawRef`) using a cosign private key (`keyRef`) diff --git a/pkg/signutil/notationutil.go b/pkg/signutil/notationutil.go index b15c80aaf5f..297756ae470 100644 --- a/pkg/signutil/notationutil.go +++ b/pkg/signutil/notationutil.go @@ -24,7 +24,7 @@ import ( "strings" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil" ) // SignNotation signs an image(`rawRef`) using a notation key name (`keyNameRef`) diff --git a/pkg/signutil/signutil.go b/pkg/signutil/signutil.go index d599458048c..6ddef610b6c 100644 --- a/pkg/signutil/signutil.go +++ b/pkg/signutil/signutil.go @@ -21,7 +21,7 @@ import ( "fmt" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) // Sign signs an image using a signer and options provided in options. diff --git a/pkg/snapshotterutil/sociutil.go b/pkg/snapshotterutil/sociutil.go index 5a4043ac9e6..9770a571316 100644 --- a/pkg/snapshotterutil/sociutil.go +++ b/pkg/snapshotterutil/sociutil.go @@ -24,7 +24,7 @@ import ( "strings" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) // CreateSoci creates a SOCI index(`rawRef`) diff --git a/pkg/taskutil/taskutil.go b/pkg/taskutil/taskutil.go index 022da8c7df2..101452f8b0e 100644 --- a/pkg/taskutil/taskutil.go +++ b/pkg/taskutil/taskutil.go @@ -31,9 +31,9 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" "github.com/containerd/log" - "github.com/containerd/nerdctl/pkg/cioutil" - "github.com/containerd/nerdctl/pkg/consoleutil" - "github.com/containerd/nerdctl/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/cioutil" + "github.com/containerd/nerdctl/v2/pkg/consoleutil" + "github.com/containerd/nerdctl/v2/pkg/infoutil" "golang.org/x/term" ) diff --git a/pkg/testutil/testregistry/testregistry_linux.go b/pkg/testutil/testregistry/testregistry_linux.go index 9eb77985e9e..4b15df56e68 100644 --- a/pkg/testutil/testregistry/testregistry_linux.go +++ b/pkg/testutil/testregistry/testregistry_linux.go @@ -23,9 +23,9 @@ import ( "path/filepath" "strconv" - "github.com/containerd/nerdctl/pkg/testutil" - "github.com/containerd/nerdctl/pkg/testutil/nettestutil" - "github.com/containerd/nerdctl/pkg/testutil/testca" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testca" "golang.org/x/crypto/bcrypt" "gotest.tools/v3/assert" diff --git a/pkg/testutil/testsyslog/testsyslog.go b/pkg/testutil/testsyslog/testsyslog.go index 8d7b9aa6ef8..a5eeb0cbf37 100644 --- a/pkg/testutil/testsyslog/testsyslog.go +++ b/pkg/testutil/testsyslog/testsyslog.go @@ -26,8 +26,8 @@ import ( "runtime" "time" - "github.com/containerd/nerdctl/pkg/rootlessutil" - "github.com/containerd/nerdctl/pkg/testutil/testca" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testca" ) func StartServer(n, la string, done chan<- string, certs ...*testca.Cert) (addr string, sock io.Closer) { diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 340ff7bf059..35d3bdef447 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -31,13 +31,13 @@ import ( "github.com/Masterminds/semver/v3" "github.com/containerd/containerd/defaults" - "github.com/containerd/nerdctl/pkg/buildkitutil" - "github.com/containerd/nerdctl/pkg/imgutil" - "github.com/containerd/nerdctl/pkg/infoutil" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/pkg/platformutil" - "github.com/containerd/nerdctl/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/opencontainers/go-digest" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" diff --git a/pkg/testutil/testutil_windows.go b/pkg/testutil/testutil_windows.go index 5d4de6d24e5..76740064de5 100644 --- a/pkg/testutil/testutil_windows.go +++ b/pkg/testutil/testutil_windows.go @@ -23,7 +23,7 @@ import ( "sync" "github.com/Microsoft/hcsshim" - "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "golang.org/x/sys/windows/svc/mgr" ) From d307fda98d482d0d4e93bd5ec5b767f540962eba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 22:57:53 +0000 Subject: [PATCH 0297/1066] build(deps): bump github.com/containerd/containerd from 1.7.11 to 1.7.12 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.11 to 1.7.12. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.11...v1.7.12) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 5 +++-- go.sum | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index bd206d11d81..8db0a4a84f3 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.0.2 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.3 - github.com/containerd/containerd v1.7.11 + github.com/containerd/containerd v1.7.12 github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 @@ -64,6 +64,8 @@ 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 @@ -111,7 +113,6 @@ require ( github.com/multiformats/go-multibase v0.1.1 // indirect github.com/multiformats/go-multihash v0.2.1 // indirect github.com/multiformats/go-varint v0.0.6 // indirect - github.com/opencontainers/runc v1.1.7 // indirect github.com/opencontainers/selinux v1.11.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/philhofer/fwd v1.1.1 // indirect diff --git a/go.sum b/go.sum index d8a46bdcc38..37024465176 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ 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.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw= -github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE= +github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= +github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= 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/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= @@ -210,6 +210,8 @@ 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/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= @@ -244,8 +246,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 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/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk= -github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= 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= From 2410e1f6ebbddfdab84ad2101b679b44486aaefb Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 15 Jan 2024 10:52:22 +0900 Subject: [PATCH 0298/1066] go.mod: github.com/rootless-containers/rootlesskit/v2 v2.0.0 Signed-off-by: Akihiro Suda --- go.mod | 6 +++--- go.sum | 11 ++++++----- pkg/bypass4netnsutil/bypass.go | 2 +- pkg/ocihook/ocihook.go | 2 +- pkg/ocihook/rootless_linux.go | 2 +- pkg/ocihook/rootless_other.go | 2 +- pkg/rootlessutil/port_linux.go | 4 ++-- pkg/rootlessutil/rootlessutil_linux.go | 2 +- pkg/rootlessutil/rootlessutil_other.go | 2 +- 9 files changed, 17 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 4073d42340c..4e8c14dca0a 100644 --- a/go.mod +++ b/go.mod @@ -46,7 +46,7 @@ require ( 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 - github.com/rootless-containers/rootlesskit v1.1.1 + github.com/rootless-containers/rootlesskit/v2 v2.0.0 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/tidwall/gjson v1.17.0 @@ -90,7 +90,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/google/uuid v1.5.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 @@ -103,7 +103,7 @@ require ( github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/locker v1.0.1 // indirect - github.com/moby/sys/mountinfo v0.6.2 // indirect + github.com/moby/sys/mountinfo v0.7.1 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/symlink v0.2.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect diff --git a/go.sum b/go.sum index 37024465176..2fbe1819aa9 100644 --- a/go.sum +++ b/go.sum @@ -159,8 +159,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= 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.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.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= @@ -202,8 +202,9 @@ github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0= -github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= +github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= @@ -267,8 +268,8 @@ github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwa github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rootless-containers/bypass4netns v0.4.0 h1:7pcI4XWnOMQkgCsPKMXxMzQKhZUjaQ8J1n+eIYiHS0Y= github.com/rootless-containers/bypass4netns v0.4.0/go.mod h1:RPNWMSRT951DMtq9Xv72IZoJPWFeJL6Wg5pF79Lkano= -github.com/rootless-containers/rootlesskit v1.1.1 h1:F5psKWoWY9/VjZ3ifVcaosjvFZJOagX85U22M0/EQZE= -github.com/rootless-containers/rootlesskit v1.1.1/go.mod h1:UD5GoA3dqKCJrnvnhVgQQnweMF2qZnf9KLw8EewcMZI= +github.com/rootless-containers/rootlesskit/v2 v2.0.0 h1:oAtnD6sgsNmdxXCm5zont5nEYTAkSqExmQOalZYiYJM= +github.com/rootless-containers/rootlesskit/v2 v2.0.0/go.mod h1:G7x0sK6onoLhFYZahpSsM/HaWEAh664SK5nCeQs4MQE= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= diff --git a/pkg/bypass4netnsutil/bypass.go b/pkg/bypass4netnsutil/bypass.go index b5497d3bba8..6dfb4db3c86 100644 --- a/pkg/bypass4netnsutil/bypass.go +++ b/pkg/bypass4netnsutil/bypass.go @@ -26,7 +26,7 @@ import ( gocni "github.com/containerd/go-cni" b4nnapi "github.com/rootless-containers/bypass4netns/pkg/api" "github.com/rootless-containers/bypass4netns/pkg/api/daemon/client" - rlkclient "github.com/rootless-containers/rootlesskit/pkg/api/client" + rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" ) func NewBypass4netnsCNIBypassManager(client client.Client, rlkClient rlkclient.Client) (*Bypass4netnsCNIBypassManager, error) { diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 1cd9b86e4ce..ebbd95150bd 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -40,7 +40,7 @@ import ( "github.com/opencontainers/runtime-spec/specs-go" b4nndclient "github.com/rootless-containers/bypass4netns/pkg/api/daemon/client" - rlkclient "github.com/rootless-containers/rootlesskit/pkg/api/client" + rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" ) const ( diff --git a/pkg/ocihook/rootless_linux.go b/pkg/ocihook/rootless_linux.go index 582ad76f0d3..9764d5f123a 100644 --- a/pkg/ocihook/rootless_linux.go +++ b/pkg/ocihook/rootless_linux.go @@ -21,7 +21,7 @@ import ( gocni "github.com/containerd/go-cni" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - rlkclient "github.com/rootless-containers/rootlesskit/pkg/api/client" + rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" ) func exposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []gocni.PortMapping) error { diff --git a/pkg/ocihook/rootless_other.go b/pkg/ocihook/rootless_other.go index c3dbe214d54..e4e092df1e2 100644 --- a/pkg/ocihook/rootless_other.go +++ b/pkg/ocihook/rootless_other.go @@ -23,7 +23,7 @@ import ( "fmt" gocni "github.com/containerd/go-cni" - rlkclient "github.com/rootless-containers/rootlesskit/pkg/api/client" + rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" ) func exposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []gocni.PortMapping) error { diff --git a/pkg/rootlessutil/port_linux.go b/pkg/rootlessutil/port_linux.go index 108ef6b4602..e8b166102eb 100644 --- a/pkg/rootlessutil/port_linux.go +++ b/pkg/rootlessutil/port_linux.go @@ -22,8 +22,8 @@ import ( "github.com/containerd/containerd/errdefs" gocni "github.com/containerd/go-cni" - "github.com/rootless-containers/rootlesskit/pkg/api/client" - "github.com/rootless-containers/rootlesskit/pkg/port" + "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" + "github.com/rootless-containers/rootlesskit/v2/pkg/port" ) func NewRootlessCNIPortManager(client client.Client) (*RootlessCNIPortManager, error) { diff --git a/pkg/rootlessutil/rootlessutil_linux.go b/pkg/rootlessutil/rootlessutil_linux.go index 795df9cf750..7eee647f297 100644 --- a/pkg/rootlessutil/rootlessutil_linux.go +++ b/pkg/rootlessutil/rootlessutil_linux.go @@ -22,7 +22,7 @@ import ( "path/filepath" "strconv" - "github.com/rootless-containers/rootlesskit/pkg/api/client" + "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" ) func IsRootless() bool { diff --git a/pkg/rootlessutil/rootlessutil_other.go b/pkg/rootlessutil/rootlessutil_other.go index 9fa5d12f737..12a368c1581 100644 --- a/pkg/rootlessutil/rootlessutil_other.go +++ b/pkg/rootlessutil/rootlessutil_other.go @@ -25,7 +25,7 @@ package rootlessutil import ( "fmt" - "github.com/rootless-containers/rootlesskit/pkg/api/client" + "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" ) // Always returns false on non-Linux platforms. From 77234f5a12adf4af748539e0db11003a35c76b8a Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 16 Jan 2024 10:44:36 +0000 Subject: [PATCH 0299/1066] update gpu image to 12.3 Signed-off-by: Kay Yan --- docs/gpu.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/gpu.md b/docs/gpu.md index 4106facda16..009170c1a37 100644 --- a/docs/gpu.md +++ b/docs/gpu.md @@ -20,7 +20,7 @@ You can specify number of GPUs to use via `--gpus` option. The following example exposes all available GPUs. ``` -nerdctl run -it --rm --gpus all nvidia/cuda:9.0-base nvidia-smi +nerdctl run -it --rm --gpus all nvidia/cuda:12.3.1-base-ubuntu20.04 nvidia-smi ``` You can also pass detailed configuration to `--gpus` option as a list of key-value pairs. The following options are provided. @@ -32,7 +32,7 @@ You can also pass detailed configuration to `--gpus` option as a list of key-val The following example exposes a specific GPU to the container. ``` -nerdctl run -it --rm --gpus '"capabilities=utility,compute",device=GPU-3a23c669-1f69-c64e-cf85-44e9b07e7a2a' nvidia/cuda:9.0-base nvidia-smi +nerdctl run -it --rm --gpus '"capabilities=utility,compute",device=GPU-3a23c669-1f69-c64e-cf85-44e9b07e7a2a' nvidia/cuda:12.3.1-base-ubuntu20.04 nvidia-smi ``` ## Fields for `nerdctl compose` @@ -53,7 +53,7 @@ The following exposes all available GPUs to the container. version: "3.8" services: demo: - image: nvidia/cuda:9.0-base + image: nvidia/cuda:12.3.1-base-ubuntu20.04 command: nvidia-smi deploy: resources: From 7f88313c6a406beb7c934725252a29465301c61a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:41:24 +0000 Subject: [PATCH 0300/1066] build(deps): bump actions/cache from 3 to 4 Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2e6ac21683b..b2597c271ee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -290,7 +290,7 @@ jobs: steps: - uses: actions/checkout@v4.1.1 - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: /root/.vagrant.d key: vagrant-${{ matrix.box }} From 3a7948b3051c02ce792e28e81612a87e562b0d9d Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 19 Jan 2024 12:23:43 +0900 Subject: [PATCH 0301/1066] CI: use standard GHA runners "Larger" runners are no longer required for nested virt with Linux Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b2597c271ee..3800d51d45e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -283,9 +283,7 @@ jobs: test-integration-freebsd: name: FreeBSD - # "Larger" runner is needed for nested virtualization - # https://github.com/organizations/containerd/settings/actions/runners - runs-on: ubuntu-latest-4-cores + runs-on: ubuntu-22.04 timeout-minutes: 20 steps: From 3149671ed718b966e177c838033d93a16c1e3dda Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 22:06:06 +0000 Subject: [PATCH 0302/1066] build(deps): bump github.com/opencontainers/image-spec Bumps [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec) from 1.1.0-rc5 to 1.1.0-rc.6. - [Release notes](https://github.com/opencontainers/image-spec/releases) - [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md) - [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0-rc5...v1.1.0-rc6) --- updated-dependencies: - dependency-name: github.com/opencontainers/image-spec dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: Akihiro Suda --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4e8c14dca0a..848f069cba3 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,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-rc6 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 diff --git a/go.sum b/go.sum index 2fbe1819aa9..9db81532875 100644 --- a/go.sum +++ b/go.sum @@ -245,8 +245,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= 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-rc6 h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU= +github.com/opencontainers/image-spec v1.1.0-rc6/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= From 2863b6c7e4c16b9aa63cf283b8d8371be1a90a8c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 19 Jan 2024 15:27:12 +0900 Subject: [PATCH 0303/1066] CI: use standard GHA runner for Windows too Follow-up to PR 2762 Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3800d51d45e..7894ee76da1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -248,8 +248,7 @@ jobs: run: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon -test.ipv6 test-integration-windows: - # A "larger" runner is used for enabling Hyper-V containers - runs-on: windows-2022-8-cores + runs-on: windows-2022 timeout-minutes: 30 defaults: run: From 0ac36b66839e9fea1c691a61dd5709876fb8b4ab Mon Sep 17 00:00:00 2001 From: Manu Gupta Date: Sun, 21 Jan 2024 14:47:12 -0800 Subject: [PATCH 0304/1066] Retag images when tag is already present in nerdctl build https://github.com/containerd/nerdctl/issues/2678 Signed-off-by: Manu Gupta --- cmd/nerdctl/builder_build_test.go | 36 ++++++++++++++++--------------- pkg/cmd/builder/build.go | 6 ++++++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index 0091a7b6f2f..96cb281a9c2 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -334,23 +334,25 @@ func TestBuildMultipleTags(t *testing.T) { defer base.Cmd("builder", "prune").Run() img := testutil.Identifier(t) imgWithNoTag, imgWithCustomTag := fmt.Sprintf("%s%d", img, 2), fmt.Sprintf("%s%d:hello", img, 3) - defer base.Cmd("rmi", img).Run() - defer base.Cmd("rmi", imgWithNoTag).Run() - defer base.Cmd("rmi", imgWithCustomTag).Run() - - dockerfile := fmt.Sprintf(`FROM %s -CMD ["echo", "nerdctl-build-test-string"] - `, testutil.CommonImage) - - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) - - base.Cmd("build", "-t", img, buildCtx).AssertOK() - base.Cmd("build", buildCtx, "-t", img, "-t", imgWithNoTag, "-t", imgWithCustomTag).AssertOK() - base.Cmd("run", "--rm", img).AssertOutExactly("nerdctl-build-test-string\n") - base.Cmd("run", "--rm", imgWithNoTag).AssertOutExactly("nerdctl-build-test-string\n") - base.Cmd("run", "--rm", imgWithCustomTag).AssertOutExactly("nerdctl-build-test-string\n") + defer base.Cmd("rmi", img).AssertOK() + defer base.Cmd("rmi", imgWithNoTag).AssertOK() + defer base.Cmd("rmi", imgWithCustomTag).AssertOK() + + buildOutputs := []string{"nerdctl-build-test-string", "nerdctl-build-test-string-rebuild"} + for _, output := range buildOutputs { + dockerfile := fmt.Sprintf(`FROM %s + CMD ["echo", "%s"] + `, testutil.CommonImage, output) + buildCtx, err := createBuildContext(dockerfile) + assert.NilError(t, err) + defer os.RemoveAll(buildCtx) + + base.Cmd("build", "-t", img, buildCtx).AssertOK() + base.Cmd("build", buildCtx, "-t", img, "-t", imgWithNoTag, "-t", imgWithCustomTag).AssertOK() + base.Cmd("run", "--rm", img).AssertOutExactly(output + "\n") + base.Cmd("run", "--rm", imgWithNoTag).AssertOutExactly(output + "\n") + base.Cmd("run", "--rm", imgWithCustomTag).AssertOutExactly(output + "\n") + } } func TestBuildWithContainerfile(t *testing.T) { diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 401bb5f504a..4f0eba7ace3 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -108,6 +108,12 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder if _, err := imageService.Create(ctx, image); err != nil { // if already exists; skip. if errors.Is(err, errdefs.ErrAlreadyExists) { + if err = imageService.Delete(ctx, targetRef); err != nil { + return err + } + if _, err = imageService.Create(ctx, image); err != nil { + return err + } continue } return fmt.Errorf("unable to tag image: %s", err) From 8df3f8a95d283d81199c4dd81b05c3d98e68bf29 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 23 Jan 2024 18:09:00 +0900 Subject: [PATCH 0305/1066] containerd/containerd/platforms -> containerd/platforms The `github.com/containerd/containerd/platorms` package was split to a separate repo: https://github.com/containerd/platforms Signed-off-by: Akihiro Suda --- cmd/nerdctl/container_diff.go | 2 +- go.mod | 1 + go.sum | 2 ++ pkg/clientutil/client.go | 2 +- pkg/cmd/builder/build.go | 2 +- pkg/cmd/compose/compose.go | 2 +- pkg/cmd/image/list.go | 2 +- pkg/cmd/image/load.go | 2 +- pkg/cmd/image/prune.go | 2 +- pkg/cmd/image/remove.go | 2 +- pkg/imgutil/commit/commit.go | 2 +- pkg/imgutil/imgutil.go | 2 +- pkg/imgutil/push/push.go | 2 +- pkg/platformutil/binfmt.go | 2 +- pkg/platformutil/layers.go | 2 +- pkg/platformutil/platformutil.go | 2 +- 16 files changed, 17 insertions(+), 14 deletions(-) diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index d5eb238fbf1..7731327d3e2 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/v2/pkg/api/types" @@ -35,6 +34,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/platforms" "github.com/opencontainers/image-spec/identity" "github.com/spf13/cobra" ) diff --git a/go.mod b/go.mod index 848f069cba3..ed56e87bcfa 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/containerd/imgcrypt v1.1.9 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.13.4 + github.com/containerd/platforms v0.1.1 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 github.com/containerd/stargz-snapshotter/ipfs v0.15.1 diff --git a/go.sum b/go.sum index 9db81532875..516d43e38d0 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,8 @@ 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.1.1 h1:gp0xXBoY+1CjH54gJDon0kBjIbK2C4XSX1BGwP5ptG0= +github.com/containerd/platforms v0.1.1/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= 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= diff --git a/pkg/clientutil/client.go b/pkg/clientutil/client.go index c6a799a55ec..03a6105247b 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/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/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 4f0eba7ace3..85c6e227247 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -32,7 +32,6 @@ import ( "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/log" "github.com/containerd/nerdctl/v2/pkg/api/types" @@ -40,6 +39,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/strutil" + "github.com/containerd/platforms" ) 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 b7ab4543561..6517412088f 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -25,7 +25,6 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/platforms" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -36,6 +35,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/nerdctl/v2/pkg/signutil" "github.com/containerd/nerdctl/v2/pkg/strutil" + "github.com/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index be256b3ddb5..4bd8843442c 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/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 7922c2448ad..1008900c88d 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/platforms" ) type readCounter struct { diff --git a/pkg/cmd/image/prune.go b/pkg/cmd/image/prune.go index 5691f331023..f290925f689 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/platforms" "github.com/opencontainers/go-digest" ) diff --git a/pkg/cmd/image/remove.go b/pkg/cmd/image/remove.go index 19d5cd8ea7c..824cd404cd6 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" + "github.com/containerd/platforms" ) // Remove removes a list of `images`. diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index 38c866929c5..45cd03241f4 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -34,12 +34,12 @@ import ( "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/log" imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/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/imgutil.go b/pkg/imgutil/imgutil.go index 356836eae29..1608d642033 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -26,7 +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" @@ -37,6 +36,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" + "github.com/containerd/platforms" "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/push/push.go b/pkg/imgutil/push/push.go index 36b1774d741..7307a66b3b3 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/v2/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/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 fc5cc6f6296..e47bee7e550 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/v2/pkg/strutil" + "github.com/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) From 1050dd65630768f328c0ce0bdff5c4eecf53ff6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Jan 2024 22:24:41 +0000 Subject: [PATCH 0306/1066] build(deps): bump github.com/klauspost/compress from 1.17.4 to 1.17.5 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.4 to 1.17.5. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.4...v1.17.5) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ed56e87bcfa..0cf077eb563 100644 --- a/go.mod +++ b/go.mod @@ -96,7 +96,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.4 + github.com/klauspost/compress v1.17.5 github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect diff --git a/go.sum b/go.sum index 516d43e38d0..2e237ae6f84 100644 --- a/go.sum +++ b/go.sum @@ -178,8 +178,8 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPquI5E= +github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= From bd6a915c101a0e9c5917513273c7aac1f1d8d0ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Jan 2024 22:24:51 +0000 Subject: [PATCH 0307/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.4 to 0.13.5. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.4...v0.13.5) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ed56e87bcfa..ab64e40bfdb 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.9 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.4 + github.com/containerd/nydus-snapshotter v0.13.5 github.com/containerd/platforms v0.1.1 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 diff --git a/go.sum b/go.sum index 516d43e38d0..bd53942b72e 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,8 @@ github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= 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/nydus-snapshotter v0.13.5 h1:C48wi0JlWsHj2/7xlGHUg7Xi+wcLC65V37uXETlHCJQ= +github.com/containerd/nydus-snapshotter v0.13.5/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= github.com/containerd/platforms v0.1.1 h1:gp0xXBoY+1CjH54gJDon0kBjIbK2C4XSX1BGwP5ptG0= github.com/containerd/platforms v0.1.1/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= github.com/containerd/stargz-snapshotter v0.15.1 h1:fpsP4kf/Z4n2EYnU0WT8ZCE3eiKDwikDhL6VwxIlgeA= From 76199746311e3ad93c078acef9dd3dba46413eba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 22:53:42 +0000 Subject: [PATCH 0308/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.5 to 0.13.6. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.5...v0.13.6) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ad8f18a30db..d2e374c7bae 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.9 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.5 + github.com/containerd/nydus-snapshotter v0.13.6 github.com/containerd/platforms v0.1.1 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 diff --git a/go.sum b/go.sum index a817f772693..e7aeb7b0690 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,8 @@ github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= 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.5 h1:C48wi0JlWsHj2/7xlGHUg7Xi+wcLC65V37uXETlHCJQ= -github.com/containerd/nydus-snapshotter v0.13.5/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= +github.com/containerd/nydus-snapshotter v0.13.6 h1:T4tDGA3oEEHiTBP8FnHqnbMX5IZtxkQKeCP1V6+1QMY= +github.com/containerd/nydus-snapshotter v0.13.6/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= github.com/containerd/platforms v0.1.1 h1:gp0xXBoY+1CjH54gJDon0kBjIbK2C4XSX1BGwP5ptG0= github.com/containerd/platforms v0.1.1/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= github.com/containerd/stargz-snapshotter v0.15.1 h1:fpsP4kf/Z4n2EYnU0WT8ZCE3eiKDwikDhL6VwxIlgeA= From 5e38fa101acc22b19ca0e4baf7e7a6ed896a6c70 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 31 Jan 2024 11:46:36 +0900 Subject: [PATCH 0309/1066] containerd-rootless-setuptool.sh: avoid creating buildkitd.toml Signed-off-by: Akihiro Suda --- .../rootless/containerd-rootless-setuptool.sh | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/extras/rootless/containerd-rootless-setuptool.sh b/extras/rootless/containerd-rootless-setuptool.sh index 03e6252aa6f..6796b924c75 100755 --- a/extras/rootless/containerd-rootless-setuptool.sh +++ b/extras/rootless/containerd-rootless-setuptool.sh @@ -265,6 +265,7 @@ cmd_entrypoint_install_buildkit() { ERROR "Install containerd first (\`$ARG0 install\`)" exit 1 fi + BUILDKITD_FLAG="--oci-worker=true --oci-worker-rootless=true --containerd-worker=false" cat <<-EOT | install_systemd_unit "${SYSTEMD_BUILDKIT_UNIT}" [Unit] Description=BuildKit (Rootless) @@ -272,7 +273,7 @@ cmd_entrypoint_install_buildkit() { [Service] Environment=PATH=$BIN:/sbin:/usr/sbin:$PATH - ExecStart="$REALPATH0" nsenter buildkitd + ExecStart="$REALPATH0" nsenter -- buildkitd ${BUILDKITD_FLAG} ExecReload=/bin/kill -s HUP \$MAINPID RestartSec=2 Restart=always @@ -291,23 +292,12 @@ cmd_entrypoint_install_buildkit_containerd() { ERROR "buildkitd (https://github.com/moby/buildkit) needs to be present under \$PATH" exit 1 fi - if [ ! -f "${XDG_CONFIG_HOME}/buildkit/buildkitd.toml" ]; then - mkdir -p "${XDG_CONFIG_HOME}/buildkit" - cat <<-EOF >"${XDG_CONFIG_HOME}/buildkit/buildkitd.toml" - [worker.oci] - enabled = false - - [worker.containerd] - enabled = true - rootless = true - EOF - fi if ! systemctl --user --no-pager status "${SYSTEMD_CONTAINERD_UNIT}" >/dev/null 2>&1; then ERROR "Install containerd first (\`$ARG0 install\`)" exit 1 fi UNIT_NAME=${SYSTEMD_BUILDKIT_UNIT} - BUILDKITD_FLAG= + BUILDKITD_FLAG="--oci-worker=false --containerd-worker=true --containerd-worker-rootless=true" if [ -n "${CONTAINERD_NAMESPACE:-}" ]; then UNIT_NAME="${CONTAINERD_NAMESPACE}-${SYSTEMD_BUILDKIT_UNIT}" BUILDKITD_FLAG="${BUILDKITD_FLAG} --addr=unix://${XDG_RUNTIME_DIR}/buildkit-${CONTAINERD_NAMESPACE}/buildkitd.sock --root=${XDG_DATA_HOME}/buildkit-${CONTAINERD_NAMESPACE} --containerd-worker-namespace=${CONTAINERD_NAMESPACE}" @@ -521,7 +511,10 @@ cmd_entrypoint_uninstall_buildkit() { init uninstall_systemd_unit "${SYSTEMD_BUILDKIT_UNIT}" INFO "This uninstallation tool does NOT remove data." - INFO "To remove data, run: \`$BIN/rootlesskit rm -rf ${XDG_DATA_HOME}/buildkit" + INFO "To remove data, run: \`$BIN/rootlesskit rm -rf ${XDG_DATA_HOME}/buildkit\`" + if [ -e "${XDG_CONFIG_HOME}/buildkit/buildkitd.toml" ]; then + INFO "You may also want to remove the daemon config: \`rm -f ${XDG_CONFIG_HOME}/buildkit/buildkitd.toml\`" + fi } # CLI subcommand: "uninstall-buildkit-containerd" From 58cc30c711be6f3efc5d3e980ed8407d5df29d6f Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 31 Jan 2024 12:01:16 +0900 Subject: [PATCH 0310/1066] update BuildKit (0.13.0-beta2) Signed-off-by: Akihiro Suda --- Dockerfile | 5 +++-- Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.4 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta2 | 2 ++ 3 files changed, 5 insertions(+), 4 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.4 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta2 diff --git a/Dockerfile b/Dockerfile index bff4e86274b..f65fee1c395 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.11 ARG CNI_PLUGINS_VERSION=v1.4.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.12.4 +ARG BUILDKIT_VERSION=v0.13.0-beta2 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption @@ -151,7 +151,8 @@ RUN fname="buildkit-${BUILDKIT_VERSION}.${TARGETOS:-linux}-${TARGETARCH:-amd64}. curl -o "${fname}" -fSL "https://github.com/moby/buildkit/releases/download/${BUILDKIT_VERSION}/${fname}" && \ grep "${fname}" "/SHA256SUMS.d/buildkit-${BUILDKIT_VERSION}" | sha256sum -c && \ tar xzf "${fname}" -C /out && \ - rm -f "${fname}" /out/bin/buildkit-qemu-* /out/bin/buildkit-runc && \ + rm -f "${fname}" /out/bin/buildkit-qemu-* /out/bin/buildkit-cni-* /out/bin/buildkit-runc && \ + for f in /out/libexec/cni/*; do ln -s ../libexec/cni/$(basename $f) /out/bin/buildkit-cni-$(basename $f); done && \ echo "- BuildKit: ${BUILDKIT_VERSION}" >> /out/share/doc/nerdctl-full/README.md # NOTE: github.com/moby/buildkit/examples/systemd is not included in BuildKit v0.8.x, will be included in v0.9.x RUN cd /out/lib/systemd/system && \ diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.4 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.4 deleted file mode 100644 index ff290731061..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.12.4 +++ /dev/null @@ -1,2 +0,0 @@ -75ffe406e4284b77af35447d829767cfa935eb7dd2ea2e3407223d6885bd8ebd buildkit-v0.12.4.linux-amd64.tar.gz -9166eeaff11721122b9398d6385c7b73d6e4df86797e537c16ac6b6d05eab899 buildkit-v0.12.4.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta2 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta2 new file mode 100644 index 00000000000..735470189a9 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta2 @@ -0,0 +1,2 @@ +c089e8c4d5765479547c04070676c3803956b98b20b0aa07de671f8ceb4521eb buildkit-v0.13.0-beta2.linux-amd64.tar.gz +a1228cd8d5fbb0d1e150f6ab7690dad9448fc63d99ec84b919d169b4f449a9ee buildkit-v0.13.0-beta2.linux-arm64.tar.gz From 328497a8079dca35a22ebf8f007045ebe6a99791 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 31 Jan 2024 12:03:16 +0900 Subject: [PATCH 0311/1066] update RootlessKit (2.0.0) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 11 ++++++++++- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.0 | 6 ++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7894ee76da1..b69cd64646d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -158,31 +158,40 @@ jobs: include: - ubuntu: 20.04 containerd: v1.6.26 + rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 20.04 containerd: v1.7.11 + rootlesskit: v2.0.0 target: test-integration-rootless - ubuntu: 22.04 containerd: v1.7.11 + rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 containerd: main + rootlesskit: v2.0.0 target: test-integration-rootless - ubuntu: 20.04 containerd: v1.6.26 + rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 containerd: v1.7.11 + rootlesskit: v2.0.0 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: v1.7.11 + rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main + rootlesskit: v2.0.0 target: test-integration-rootless-port-slirp4netns env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" + ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" TEST_TARGET: "${{ matrix.target }}" steps: - uses: actions/checkout@v4.1.1 @@ -191,7 +200,7 @@ jobs: - name: "Register QEMU (tonistiigi/binfmt)" run: docker run --privileged --rm tonistiigi/binfmt --install all - name: "Prepare (network driver=slirp4netns, port driver=builtin)" - run: DOCKER_BUILDKIT=1 docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . + run: DOCKER_BUILDKIT=1 docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} --build-arg ROOTLESSKIT_VERSION=${ROOTLESSKIT_VERSION} . - name: "Test (network driver=slirp4netns, port driver=builtin)" run: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=1 ${TEST_TARGET} diff --git a/Dockerfile b/Dockerfile index f65fee1c395..05e8b6d1d96 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption ARG IMGCRYPT_VERSION=v1.1.9 # Extra deps: Rootless -ARG ROOTLESSKIT_VERSION=v1.1.1 +ARG ROOTLESSKIT_VERSION=v2.0.0 ARG SLIRP4NETNS_VERSION=v1.2.2 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.3.0 diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.0 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.0 new file mode 100644 index 00000000000..933f7fc1276 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.0 @@ -0,0 +1,6 @@ +c24c13b0a7d74ea2ce9c44ca13810844149c93b5d193a08bf21166d08706621c rootlesskit-aarch64.tar.gz +da79e531f38688aad050c93e0c4d2b1f33e888e9dc6301f9866eabfec93bc75f rootlesskit-armv7l.tar.gz +181e9ff0c9ee0286b7b5384893b5dc6498098eee7014de253f053e3b50fdcbdb rootlesskit-ppc64le.tar.gz +709527301c6c4046cbe0ef5043a866ca7cfd105d91dee4a49ef3c85c8e57de5a rootlesskit-riscv64.tar.gz +28a8d3eb8eb6fc49cba4819a3a74be6319e7060707e37ca02425107ed65c034e rootlesskit-s390x.tar.gz +8205e3f96ca9eb576a0b182455fb5ad1067bf019a7fe50a1816f6c04b581723f rootlesskit-x86_64.tar.gz From 4892364cba785385b93202a3304462ffe62bb595 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 31 Jan 2024 12:11:21 +0900 Subject: [PATCH 0312/1066] [Carry 2535] rootless: support detach-netns mode When RootlessKit v2.0 (rootless-containers/rootlesskit PR 379) is installed, `containerd-rootless.sh` launches it with `--detach-netns` so as to run the daemon in the host network namespace. This will enable: - Accelerated (and deflaked) `nerdctl pull`, `nerdctl push`, `nerdctl build`, etc - Proper support for `nerdctl pull 127.0.0.1:.../...` - Proper support for `nerdctl run --net=host` Replaces Fahed Dorgaa's PR 2535 Co-authored-by: fahed dorgaa Signed-off-by: Akihiro Suda --- README.md | 2 +- .../container_run_network_linux_test.go | 5 +++ cmd/nerdctl/ipfs_linux_test.go | 23 +++++++---- docs/rootless.md | 30 ++++++++++++++ .../rootless/containerd-rootless-setuptool.sh | 15 ++++++- extras/rootless/containerd-rootless.sh | 31 +++++++++++++- pkg/cmd/container/create.go | 24 +++++++++++ .../container_network_manager.go | 41 +++++++++++++++++++ pkg/defaults/defaults_linux.go | 1 + pkg/netutil/netutil_unix.go | 15 ++++--- pkg/netutil/subnet/subnet.go | 10 ++++- pkg/rootlessutil/parent_linux.go | 15 ++++++- pkg/rootlessutil/rootlessutil_linux.go | 39 ++++++++++++++++++ pkg/rootlessutil/rootlessutil_other.go | 8 ++++ pkg/testutil/nettestutil/nettestutil.go | 1 + 15 files changed, 240 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 98e7a3d9b33..1d4e6863779 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ In addition to containerd, the following components should be installed: - [BuildKit](https://github.com/moby/buildkit) (OPTIONAL): for using `nerdctl build`. BuildKit daemon (`buildkitd`) needs to be running. See also [the document about setting up BuildKit](./docs/build.md). - v0.11.0 or later is highly recommended. Some features, such as pruning caches with `nerdctl system prune`, do not work with older versions. - [RootlessKit](https://github.com/rootless-containers/rootlesskit) and [slirp4netns](https://github.com/rootless-containers/slirp4netns) (OPTIONAL): for [Rootless mode](./docs/rootless.md) - - RootlessKit needs to be v0.10.0 or later. v0.14.1 or later is recommended. + - RootlessKit needs to be v0.10.0 or later. v2.0.0 or later is recommended. - slirp4netns needs to be v0.4.0 or later. v1.1.7 or later is recommended. These dependencies are included in `nerdctl-full---.tar.gz`, but not included in `nerdctl---.tar.gz`. diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index 79139736203..58349cba619 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -494,6 +494,11 @@ func TestRunContainerWithMACAddress(t *testing.T) { } func TestHostsFileMounts(t *testing.T) { + if rootlessutil.IsRootless() { + if detachedNetNS, _ := rootlessutil.DetachedNetNS(); detachedNetNS != "" { + t.Skip("/etc/hosts is not writable") + } + } base := testutil.NewBase(t) base.Cmd("run", "--rm", testutil.CommonImage, diff --git a/cmd/nerdctl/ipfs_linux_test.go b/cmd/nerdctl/ipfs_linux_test.go index 1c5582347ea..981894f9978 100644 --- a/cmd/nerdctl/ipfs_linux_test.go +++ b/cmd/nerdctl/ipfs_linux_test.go @@ -73,14 +73,21 @@ func TestIPFSAddress(t *testing.T) { func runIPFSDaemonContainer(t *testing.T, base *testutil.Base) (ipfsAddress string, done func()) { name := "test-ipfs-address" - base.Cmd("run", "-d", "--name", name, "--entrypoint=/bin/sh", testutil.KuboImage, "-c", "ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/5001 && ipfs daemon --offline").AssertOK() - iplines := base.Cmd("inspect", name, "-f", "'{{json .NetworkSettings.IPAddress}}'").OutLines() - t.Logf("IPAddress=%v", iplines) - assert.Equal(t, len(iplines), 2) - matches := iplineRegexp.FindStringSubmatch(iplines[0]) - t.Logf("ip address matches=%v", matches) - assert.Equal(t, len(matches), 2) - ipfsaddr := fmt.Sprintf("/ip4/%s/tcp/5001", matches[1]) + var ipfsaddr string + if detachedNetNS, _ := rootlessutil.DetachedNetNS(); detachedNetNS != "" { + // detached-netns mode can't use .NetworkSettings.IPAddress, because the daemon and CNI has different network namespaces + base.Cmd("run", "-d", "-p", "127.0.0.1:5999:5999", "--name", name, "--entrypoint=/bin/sh", testutil.KuboImage, "-c", "ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/5999 && ipfs daemon --offline").AssertOK() + ipfsaddr = "/ip4/127.0.0.1/tcp/5999" + } else { + base.Cmd("run", "-d", "--name", name, "--entrypoint=/bin/sh", testutil.KuboImage, "-c", "ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/5001 && ipfs daemon --offline").AssertOK() + iplines := base.Cmd("inspect", name, "-f", "'{{json .NetworkSettings.IPAddress}}'").OutLines() + t.Logf("IPAddress=%v", iplines) + assert.Equal(t, len(iplines), 2) + matches := iplineRegexp.FindStringSubmatch(iplines[0]) + t.Logf("ip address matches=%v", matches) + assert.Equal(t, len(matches), 2) + ipfsaddr = fmt.Sprintf("/ip4/%s/tcp/5001", matches[1]) + } return ipfsaddr, func() { base.Cmd("kill", "test-ipfs-address").AssertOK() base.Cmd("rm", "test-ipfs-address").AssertOK() diff --git a/docs/rootless.md b/docs/rootless.md index 4c9cfa5d4b1..6c9d048fe02 100644 --- a/docs/rootless.md +++ b/docs/rootless.md @@ -130,6 +130,36 @@ $ nerdctl run -it --rm -p 8080:80 --label nerdctl/bypass4netns=true alpine More detail is available at [https://github.com/rootless-containers/bypass4netns/blob/master/README.md](https://github.com/rootless-containers/bypass4netns/blob/master/README.md) +## Configuring RootlessKit + +Rootless containerd recognizes the following environment variables to configure the behavior of [RootlessKit](https://github.com/rootless-containers/rootlesskit): + +* `CONTAINERD_ROOTLESS_ROOTLESSKIT_STATE_DIR=DIR`: the rootlesskit state dir. Defaults to `$XDG_RUNTIME_DIR/containerd-rootless`. +* `CONTAINERD_ROOTLESS_ROOTLESSKIT_NET=(slirp4netns|vpnkit|lxc-user-nic)`: the rootlesskit network driver. Defaults to "slirp4netns" if slirp4netns (>= v0.4.0) is installed. Otherwise defaults to "vpnkit". +* `CONTAINERD_ROOTLESS_ROOTLESSKIT_MTU=NUM`: the MTU value for the rootlesskit network driver. Defaults to 65520 for slirp4netns, 1500 for other drivers. +* `CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=(builtin|slirp4netns)`: the rootlesskit port driver. Defaults to "builtin". +* `CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SANDBOX=(auto|true|false)`: whether to protect slirp4netns with a dedicated mount namespace. Defaults to "auto". +* `CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SECCOMP=(auto|true|false)`: whether to protect slirp4netns with seccomp. Defaults to "auto". +* `CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS=(auto|true|false)`: whether to launch rootlesskit with the "detach-netns" mode. + Defaults to "auto", which is resolved to "true" if RootlessKit >= 2.0 is installed. + The "detached-netns" mode accelerates `nerdctl (pull|push|build)` and enables `nerdctl run --net=host`, + however, there is a relatively minor drawback with BuildKit prior to v0.13: + the host loopback IP address (127.0.0.1) and abstract sockets are exposed to Dockerfile's "RUN" instructions during `nerdctl build` (not `nerdctl run`). + The drawback is fixed in BuildKit v0.13. Upgrading from a prior version of BuildKit needs removing the old systemd unit: + `containerd-rootless-setuptool.sh uninstall-buildkit && rm -f ~/.config/buildkit/buildkitd.toml` + +To set these variables, create `~/.config/systemd/user/containerd.service.d/override.conf` as follows: +```ini +[Service] +Environment=CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS="false" +``` + +And then run the following commands: +```bash +systemctl --user daemon-reload +systemctl --user restart containerd +``` + ## Troubleshooting ### Hint to Fedora users diff --git a/extras/rootless/containerd-rootless-setuptool.sh b/extras/rootless/containerd-rootless-setuptool.sh index 6796b924c75..1ecc63e4351 100755 --- a/extras/rootless/containerd-rootless-setuptool.sh +++ b/extras/rootless/containerd-rootless-setuptool.sh @@ -152,8 +152,13 @@ propagate_env_from() { cmd_entrypoint_nsenter() { # No need to call init() pid=$(cat "$XDG_RUNTIME_DIR/containerd-rootless/child_pid") + n="" + # If RootlessKit is running with `--detach-netns` mode, we do NOT enter the detached netns here + if [ ! -e "$XDG_RUNTIME_DIR/containerd-rootless/netns" ]; then + n="-n" + fi propagate_env_from "$pid" ROOTLESSKIT_STATE_DIR ROOTLESSKIT_PARENT_EUID ROOTLESSKIT_PARENT_EGID - exec nsenter --no-fork --wd="$(pwd)" --preserve-credentials -m -n -U -t "$pid" -- "$@" + exec nsenter --no-fork --wd="$(pwd)" --preserve-credentials -m $n -U -t "$pid" -- "$@" } show_systemd_error() { @@ -266,6 +271,10 @@ cmd_entrypoint_install_buildkit() { exit 1 fi BUILDKITD_FLAG="--oci-worker=true --oci-worker-rootless=true --containerd-worker=false" + if buildkitd --help | grep -q bridge; then + # Available since BuildKit v0.13 + BUILDKITD_FLAG="${BUILDKITD_FLAG} --oci-worker-net=bridge" + fi cat <<-EOT | install_systemd_unit "${SYSTEMD_BUILDKIT_UNIT}" [Unit] Description=BuildKit (Rootless) @@ -307,6 +316,10 @@ cmd_entrypoint_install_buildkit_containerd() { if [ -n "${CONTAINERD_SNAPSHOTTER:-}" ]; then BUILDKITD_FLAG="${BUILDKITD_FLAG} --containerd-worker-snapshotter=${CONTAINERD_SNAPSHOTTER}" fi + if buildkitd --help | grep -q bridge; then + # Available since BuildKit v0.13 + BUILDKITD_FLAG="${BUILDKITD_FLAG} --containerd-worker-net=bridge" + fi cat <<-EOT | install_systemd_unit "${UNIT_NAME}" [Unit] Description=BuildKit (Rootless) diff --git a/extras/rootless/containerd-rootless.sh b/extras/rootless/containerd-rootless.sh index d394eeabe56..4338af510d7 100755 --- a/extras/rootless/containerd-rootless.sh +++ b/extras/rootless/containerd-rootless.sh @@ -28,7 +28,7 @@ # External dependencies: # * newuidmap and newgidmap needs to be installed. # * /etc/subuid and /etc/subgid needs to be configured for the current user. -# * RootlessKit (>= v0.10.0) needs to be installed. RootlessKit >= v0.14.1 is recommended. +# * RootlessKit (>= v0.10.0) needs to be installed. RootlessKit >= v2.0.0 is recommended. # * Either one of slirp4netns (>= v0.4.0), VPNKit, lxc-user-nic needs to be installed. slirp4netns >= v1.1.7 is recommended. # # Recognized environment variables: @@ -38,6 +38,15 @@ # * CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=(builtin|slirp4netns): the rootlesskit port driver. Defaults to "builtin". # * CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SANDBOX=(auto|true|false): whether to protect slirp4netns with a dedicated mount namespace. Defaults to "auto". # * CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SECCOMP=(auto|true|false): whether to protect slirp4netns with seccomp. Defaults to "auto". +# * CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS=(auto|true|false): whether to launch rootlesskit with the "detach-netns" mode. +# Defaults to "auto", which is resolved to "true" if RootlessKit >= 2.0 is installed. +# The "detached-netns" mode accelerates `nerdctl (pull|push|build)` and enables `nerdctl run --net=host`, +# however, there is a relatively minor drawback with BuildKit prior to v0.13: +# the host loopback IP address (127.0.0.1) and abstract sockets are exposed to Dockerfile's "RUN" instructions during `nerdctl build` (not `nerdctl run`). +# The drawback is fixed in BuildKit v0.13. Upgrading from a prior version of BuildKit needs removing the old systemd unit: +# `containerd-rootless-setuptool.sh uninstall-buildkit && rm -f ~/.config/buildkit/buildkitd.toml` + +# See also: https://github.com/containerd/nerdctl/blob/main/docs/rootless.md#configuring-rootlesskit set -e if ! [ -w $XDG_RUNTIME_DIR ]; then @@ -69,6 +78,7 @@ if [ -z $_CONTAINERD_ROOTLESS_CHILD ]; then : "${CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER:=builtin}" : "${CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SANDBOX:=auto}" : "${CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SECCOMP:=auto}" + : "${CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS:=auto}" net=$CONTAINERD_ROOTLESS_ROOTLESSKIT_NET mtu=$CONTAINERD_ROOTLESS_ROOTLESSKIT_MTU if [ -z $net ]; then @@ -107,6 +117,25 @@ if [ -z $_CONTAINERD_ROOTLESS_CHILD ]; then export _CONTAINERD_ROOTLESS_SELINUX fi fi + + case "$CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS" in + auto) + if rootlesskit --help | grep -qw -- "--detach-netns"; then + CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS=--detach-netns $CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS + fi + ;; + 1 | true) + CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS=--detach-netns $CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS + ;; + 0 | false) + # NOP + ;; + *) + echo "Unknown CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS value: $CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS" + exit 1 + ;; + esac + # Re-exec the script via RootlessKit, so as to create unprivileged {user,mount,network} namespaces. # # --copy-up allows removing/creating files in the directories by creating tmpfs and symlinks diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index dc5b3491bf7..fbd51ff302f 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -50,6 +50,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/namestore" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/referenceutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" dockercliopts "github.com/docker/cli/opts" dockeropts "github.com/docker/docker/opts" @@ -418,6 +419,29 @@ func GenerateLogURI(dataStore string) (*url.URL, error) { } func withNerdctlOCIHook(cmd string, args []string) (oci.SpecOpts, error) { + if rootlessutil.IsRootless() { + detachedNetNS, err := rootlessutil.DetachedNetNS() + if err != nil { + return nil, fmt.Errorf("failed to check whether RootlessKit is running with --detach-netns: %w", err) + } + if detachedNetNS != "" { + // Rewrite {cmd, args} if RootlessKit is running with --detach-netns, so that the hook can gain + // CAP_NET_ADMIN in the namespaces. + // - Old: + // - cmd: "/usr/local/bin/nerdctl" + // - args: {"--data-root=/foo", "internal", "oci-hook"} + // - New: + // - cmd: "/usr/bin/nsenter" + // - args: {"-n/run/user/1000/containerd-rootless/netns", "-F", "--", "/usr/local/bin/nerdctl", "--data-root=/foo", "internal", "oci-hook"} + oldCmd, oldArgs := cmd, args + cmd, err = exec.LookPath("nsenter") + if err != nil { + return nil, err + } + args = append([]string{"-n" + detachedNetNS, "-F", "--", oldCmd}, oldArgs...) + } + } + args = append([]string{cmd}, append(args, "internal", "oci-hook")...) return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error { if s.Hooks == nil { diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 6dc57f2f08a..ae24bc15f54 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -38,6 +38,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/mountutil" "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/opencontainers/runtime-spec/specs-go" ) @@ -461,9 +462,49 @@ func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containe } } + if rootlessutil.IsRootless() { + detachedNetNS, err := rootlessutil.DetachedNetNS() + if err != nil { + return nil, nil, fmt.Errorf("failed to check whether RootlessKit is running with --detach-netns: %w", err) + } + if detachedNetNS != "" { + // For rootless + host netns, we can't mount sysfs. + // We can't (non-recursively) bind mount /sys, either. + // + // TODO: consider to just rbind /sys from the host with rro, + // when rro is available (kernel >= 5.12, runc >= 1.1). + // + // Relevant: https://github.com/moby/buildkit/blob/v0.12.4/util/rootless/specconv/specconv_linux.go#L15-L34 + specs = append(specs, withRemoveSysfs) + } + } + return specs, cOpts, nil } +func withRemoveSysfs(_ context.Context, _ oci.Client, c *containers.Container, s *oci.Spec) error { + var hasSysfs bool + for _, mount := range s.Mounts { + if mount.Type == "sysfs" { + hasSysfs = true + break + } + } + if !hasSysfs { + // NOP, as the user has specified a custom /sys mount + return nil + } + var mounts []specs.Mount // nolint: prealloc + for _, mount := range s.Mounts { + if strings.HasPrefix(mount.Destination, "/sys") { + continue + } + mounts = append(mounts, mount) + } + s.Mounts = mounts + return nil +} + // types.NetworkOptionsManager implementation for CNI networking settings. // This is a more specialized and OS-dependendant networking model so this // struct provides different implementations on different platforms. diff --git a/pkg/defaults/defaults_linux.go b/pkg/defaults/defaults_linux.go index 76c5ffa60a5..13dbf9c9dd4 100644 --- a/pkg/defaults/defaults_linux.go +++ b/pkg/defaults/defaults_linux.go @@ -138,6 +138,7 @@ func HostsDirs() []string { // HostGatewayIP returns the non-loop-back host ip if available and returns empty string if running into error. func HostGatewayIP() string { + // no need to use [rootlessutil.WithDetachedNetNSIfAny] here addrs, err := net.InterfaceAddrs() if err != nil { return "" diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index d935f0972ec..7b9dff23b5a 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -31,6 +31,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/systemutil" "github.com/mitchellh/mapstructure" @@ -322,11 +323,13 @@ func guessFirewallPluginVersion(stderr string) (*semver.Version, error) { } func removeBridgeNetworkInterface(netIf string) error { - link, err := netlink.LinkByName(netIf) - if err == nil { - if err := netlink.LinkDel(link); err != nil { - return fmt.Errorf("failed to remove network interface %s: %v", netIf, err) + return rootlessutil.WithDetachedNetNSIfAny(func() error { + link, err := netlink.LinkByName(netIf) + if err == nil { + if err := netlink.LinkDel(link); err != nil { + return fmt.Errorf("failed to remove network interface %s: %v", netIf, err) + } } - } - return nil + return nil + }) } diff --git a/pkg/netutil/subnet/subnet.go b/pkg/netutil/subnet/subnet.go index 188ab88e9f3..02c3a8b2bd4 100644 --- a/pkg/netutil/subnet/subnet.go +++ b/pkg/netutil/subnet/subnet.go @@ -19,11 +19,17 @@ package subnet import ( "fmt" "net" + + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) func GetLiveNetworkSubnets() ([]*net.IPNet, error) { - addrs, err := net.InterfaceAddrs() - if err != nil { + var addrs []net.Addr + if err := rootlessutil.WithDetachedNetNSIfAny(func() error { + var err2 error + addrs, err2 = net.InterfaceAddrs() + return err2 + }); err != nil { return nil, err } nets := make([]*net.IPNet, 0, len(addrs)) diff --git a/pkg/rootlessutil/parent_linux.go b/pkg/rootlessutil/parent_linux.go index 42064671984..8066f24c7e2 100644 --- a/pkg/rootlessutil/parent_linux.go +++ b/pkg/rootlessutil/parent_linux.go @@ -77,6 +77,16 @@ func ParentMain(hostGatewayIP string) error { return err } + detachedNetNSPath, err := detachedNetNS(stateDir) + if err != nil { + return err + } + detachNetNSMode := detachedNetNSPath != "" + log.L.Debugf("RootlessKit detach-netns mode: %v", detachNetNSMode) + if err != nil { + return err + } + wd, err := os.Getwd() if err != nil { return err @@ -92,10 +102,13 @@ func ParentMain(hostGatewayIP string) error { "-r/", // root dir (busybox nsenter wants this to be explicitly specified), "-w" + wd, // work dir "--preserve-credentials", - "-m", "-n", "-U", + "-m", "-U", "-t", strconv.Itoa(childPid), "-F", // no fork } + if !detachNetNSMode { + args = append(args, "-n") + } args = append(args, os.Args...) log.L.Debugf("rootless parent main: executing %q with %v", arg0, args) diff --git a/pkg/rootlessutil/rootlessutil_linux.go b/pkg/rootlessutil/rootlessutil_linux.go index 7eee647f297..bb5349f255f 100644 --- a/pkg/rootlessutil/rootlessutil_linux.go +++ b/pkg/rootlessutil/rootlessutil_linux.go @@ -17,11 +17,13 @@ package rootlessutil import ( + "errors" "fmt" "os" "path/filepath" "strconv" + "github.com/containernetworking/plugins/pkg/ns" "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" ) @@ -80,3 +82,40 @@ func RootlessContainredSockAddress() (string, error) { } return filepath.Join(fmt.Sprintf("/proc/%d/root/run/containerd/containerd.sock", childPid)), nil } + +// DetachedNetNS returns non-empty netns path if RootlessKit is running with --detach-netns mode. +// Otherwise returns "" without an error. +func DetachedNetNS() (string, error) { + if !IsRootless() { + return "", nil + } + stateDir, err := RootlessKitStateDir() + if err != nil { + return "", err + } + return detachedNetNS(stateDir) +} + +func detachedNetNS(stateDir string) (string, error) { + p := filepath.Join(stateDir, "netns") + if _, err := os.Stat(p); err != nil { + if errors.Is(err, os.ErrNotExist) { + return "", nil + } + return "", err + } + return p, nil +} + +// WithDetachedNetNSIfAny executes fn in [DetachedNetNS] if RootlessKit is running with --detach-netns mode. +// Otherwise it just executes fn in the current netns. +func WithDetachedNetNSIfAny(fn func() error) error { + netns, err := DetachedNetNS() + if err != nil { + return err + } + if netns == "" { + return fn() + } + return ns.WithNetNSPath(netns, func(_ ns.NetNS) error { return fn() }) +} diff --git a/pkg/rootlessutil/rootlessutil_other.go b/pkg/rootlessutil/rootlessutil_other.go index 12a368c1581..4ebd5c1d832 100644 --- a/pkg/rootlessutil/rootlessutil_other.go +++ b/pkg/rootlessutil/rootlessutil_other.go @@ -66,3 +66,11 @@ func ParentMain(hostGatewayIP string) error { func RootlessContainredSockAddress() (string, error) { return "", fmt.Errorf("cannot inspect RootlessKit state on non-Linux hosts") } + +func DetachedNetNS() (string, error) { + return "", nil +} + +func WithDetachedNetNSIfAny(fn func() error) error { + return fn() +} diff --git a/pkg/testutil/nettestutil/nettestutil.go b/pkg/testutil/nettestutil/nettestutil.go index 960d7738bca..be9d14fb8f3 100644 --- a/pkg/testutil/nettestutil/nettestutil.go +++ b/pkg/testutil/nettestutil/nettestutil.go @@ -54,6 +54,7 @@ func HTTPGet(urlStr string, attempts int, insecure bool) (*http.Response, error) } func NonLoopbackIPv4() (net.IP, error) { + // no need to use [rootlessutil.WithDetachedNetNSIfAny] here addrs, err := net.InterfaceAddrs() if err != nil { return nil, err From 3ab02f69554537a997dbf2c2e8515bdd3c7899b3 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 31 Jan 2024 16:13:58 +0900 Subject: [PATCH 0313/1066] update containerd (1.7.13) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 24 ++++++++++++------------ Dockerfile | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b69cd64646d..683c3e7cbc0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,11 +77,11 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.26 + containerd: v1.6.28 - ubuntu: 20.04 - containerd: v1.7.11 + containerd: v1.7.13 - ubuntu: 22.04 - containerd: v1.7.11 + containerd: v1.7.13 - ubuntu: 22.04 containerd: main env: @@ -113,7 +113,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 22.04 - containerd: v1.7.11 + containerd: v1.7.13 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -157,15 +157,15 @@ jobs: # ubuntu-22.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.26 + containerd: v1.6.28 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.11 + containerd: v1.7.13 rootlesskit: v2.0.0 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.11 + containerd: v1.7.13 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 @@ -173,15 +173,15 @@ jobs: rootlesskit: v2.0.0 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.6.26 + containerd: v1.6.28 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.11 + containerd: v1.7.13 rootlesskit: v2.0.0 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.11 + containerd: v1.7.13 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 @@ -275,7 +275,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: repository: containerd/containerd - ref: v1.7.11 + ref: v1.7.13 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -283,7 +283,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.11 + ctrdVersion: 1.7.13 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index 05e8b6d1d96..591bca37f06 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.11 +ARG CONTAINERD_VERSION=v1.7.13 ARG RUNC_VERSION=v1.1.11 ARG CNI_PLUGINS_VERSION=v1.4.0 From 02dc9b44cf7d20b0ec1191072948e3bb0d8d0e92 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 31 Jan 2024 16:14:32 +0900 Subject: [PATCH 0314/1066] update runc (1.1.12) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 591bca37f06..cc3a995beff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v1.7.13 -ARG RUNC_VERSION=v1.1.11 +ARG RUNC_VERSION=v1.1.12 ARG CNI_PLUGINS_VERSION=v1.4.0 # Extra deps: Build From ad02e192db74d06c44cc3b3c9c8e049f401abc02 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 31 Jan 2024 16:15:34 +0900 Subject: [PATCH 0315/1066] update bypass4netns (0.4.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cc3a995beff..bd414c8046f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,7 +32,7 @@ ARG IMGCRYPT_VERSION=v1.1.9 ARG ROOTLESSKIT_VERSION=v2.0.0 ARG SLIRP4NETNS_VERSION=v1.2.2 # Extra deps: bypass4netns -ARG BYPASS4NETNS_VERSION=v0.3.0 +ARG BYPASS4NETNS_VERSION=v0.4.0 # Extra deps: FUSE-OverlayFS ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 From dc7bbed8667d49d559021117af5f1d20a61d7fef Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 31 Jan 2024 16:16:54 +0900 Subject: [PATCH 0316/1066] update Kubo (0.26.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index bd414c8046f..5a82c52b60c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ ARG BYPASS4NETNS_VERSION=v0.4.0 ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 # Extra deps: IPFS -ARG KUBO_VERSION=v0.24.0 +ARG KUBO_VERSION=v0.26.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug From a3e8cb466890a9bfe88a2a3e1407e692c77f1958 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Jan 2024 22:19:20 +0000 Subject: [PATCH 0317/1066] build(deps): bump github.com/containerd/containerd from 1.7.12 to 1.7.13 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.12 to 1.7.13. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.12...v1.7.13) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d2e374c7bae..bd67811b31c 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.0.2 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.3 - github.com/containerd/containerd v1.7.12 + github.com/containerd/containerd v1.7.13 github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 diff --git a/go.sum b/go.sum index e7aeb7b0690..4d622fc4582 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ 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.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.12 h1:+KQsnv4VnzyxWcfO9mlxxELaoztsDEjOuCMPAuPqgU0= -github.com/containerd/containerd v1.7.12/go.mod h1:/5OMpE1p0ylxtEUGY8kuCYkDRzJm9NO1TFMWjUpdevk= +github.com/containerd/containerd v1.7.13 h1:wPYKIeGMN8vaggSKuV1X0wZulpMz4CrgEsZdaCyB6Is= +github.com/containerd/containerd v1.7.13/go.mod h1:zT3up6yTRfEUa6+GsITYIJNgSVL9NQ4x4h1RPzk0Wu4= 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/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= From 371686906f13c5eed24be9bf6158451f77bdd6b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Jan 2024 22:28:20 +0000 Subject: [PATCH 0318/1066] build(deps): bump docker/metadata-action from 5.5.0 to 5.5.1 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.5.0 to 5.5.1. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/v5.5.0...v5.5.1) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 049911e5df0..cff2cbdc9cb 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -52,7 +52,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v5.5.0 + uses: docker/metadata-action@v5.5.1 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} From 5df53e5f72955d191a4f91a827a49a6fb027bdbf Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 1 Feb 2024 08:43:41 +0900 Subject: [PATCH 0319/1066] update BuildKit (0.13.0-beta3) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta2 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta3 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta2 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta3 diff --git a/Dockerfile b/Dockerfile index 5a82c52b60c..956995d25f8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.12 ARG CNI_PLUGINS_VERSION=v1.4.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.13.0-beta2 +ARG BUILDKIT_VERSION=v0.13.0-beta3 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta2 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta2 deleted file mode 100644 index 735470189a9..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta2 +++ /dev/null @@ -1,2 +0,0 @@ -c089e8c4d5765479547c04070676c3803956b98b20b0aa07de671f8ceb4521eb buildkit-v0.13.0-beta2.linux-amd64.tar.gz -a1228cd8d5fbb0d1e150f6ab7690dad9448fc63d99ec84b919d169b4f449a9ee buildkit-v0.13.0-beta2.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta3 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta3 new file mode 100644 index 00000000000..98ab016effd --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta3 @@ -0,0 +1,2 @@ +c0137ed55fd7f87ec4a04e940415ee449e3c70ae716194d5d1660b3e93e72e14 buildkit-v0.13.0-beta3.linux-amd64.tar.gz +9a877ecb952820fbd05885732d4cfb6df8d2de0a8041d8f957be72c6bff0c8c6 buildkit-v0.13.0-beta3.linux-arm64.tar.gz From 3b45cc18ec12a3def6f6f4d7f1c28d721541d6a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Feb 2024 22:10:10 +0000 Subject: [PATCH 0320/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.6 to 0.13.7. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.6...v0.13.7) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bd67811b31c..c64965409b2 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.9 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.6 + github.com/containerd/nydus-snapshotter v0.13.7 github.com/containerd/platforms v0.1.1 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 diff --git a/go.sum b/go.sum index 4d622fc4582..c9e98c38f65 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,8 @@ github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= 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.6 h1:T4tDGA3oEEHiTBP8FnHqnbMX5IZtxkQKeCP1V6+1QMY= -github.com/containerd/nydus-snapshotter v0.13.6/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= +github.com/containerd/nydus-snapshotter v0.13.7 h1:x7DHvGnzJOu1ZPwPYkeOPk5MjZZYbdddygEjaSDoFTk= +github.com/containerd/nydus-snapshotter v0.13.7/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= github.com/containerd/platforms v0.1.1 h1:gp0xXBoY+1CjH54gJDon0kBjIbK2C4XSX1BGwP5ptG0= github.com/containerd/platforms v0.1.1/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= github.com/containerd/stargz-snapshotter v0.15.1 h1:fpsP4kf/Z4n2EYnU0WT8ZCE3eiKDwikDhL6VwxIlgeA= From b452c64bb9bf215057b036bbae79e8120f4324c6 Mon Sep 17 00:00:00 2001 From: Min Uk Lee Date: Sun, 5 Nov 2023 18:23:08 +0900 Subject: [PATCH 0321/1066] Support --ipc=container: option Signed-off-by: Min Uk Lee - support ipc namespace - support /dev/shm --- cmd/nerdctl/container_restart_linux_test.go | 27 +++ cmd/nerdctl/container_run_linux_test.go | 58 +++++ docs/command-reference.md | 2 +- pkg/cmd/container/create.go | 32 ++- pkg/cmd/container/remove.go | 9 + pkg/cmd/container/run_linux.go | 42 ++-- pkg/containerutil/config.go | 24 ++ pkg/containerutil/containerutil.go | 15 ++ pkg/ipcutil/ipcutil.go | 250 ++++++++++++++++++++ pkg/ipcutil/ipcutil_linux.go | 64 +++++ pkg/ipcutil/ipcutil_unix.go | 34 +++ pkg/ipcutil/ipcutil_windows.go | 32 +++ pkg/labels/labels.go | 4 + 13 files changed, 558 insertions(+), 35 deletions(-) create mode 100644 pkg/ipcutil/ipcutil.go create mode 100644 pkg/ipcutil/ipcutil_linux.go create mode 100644 pkg/ipcutil/ipcutil_unix.go create mode 100644 pkg/ipcutil/ipcutil_windows.go diff --git a/cmd/nerdctl/container_restart_linux_test.go b/cmd/nerdctl/container_restart_linux_test.go index 374debc1d83..cd1160a540e 100644 --- a/cmd/nerdctl/container_restart_linux_test.go +++ b/cmd/nerdctl/container_restart_linux_test.go @@ -71,6 +71,33 @@ func TestRestartPIDContainer(t *testing.T) { assert.Equal(t, baseOutput, sharedOutput) } +func TestRestartIPCContainer(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + + const shmSize = "32m" + baseContainerName := testutil.Identifier(t) + defer base.Cmd("rm", "-f", baseContainerName).Run() + base.Cmd("run", "-d", "--shm-size", shmSize, "--ipc", "shareable", "--name", baseContainerName, testutil.AlpineImage, "sleep", "infinity").AssertOK() + + sharedContainerName := fmt.Sprintf("%s-shared", baseContainerName) + defer base.Cmd("rm", "-f", sharedContainerName).Run() + base.Cmd("run", "-d", "--name", sharedContainerName, fmt.Sprintf("--ipc=container:%s", baseContainerName), testutil.AlpineImage, "sleep", "infinity").AssertOK() + + base.Cmd("stop", baseContainerName).Run() + base.Cmd("stop", sharedContainerName).Run() + + base.Cmd("restart", baseContainerName).AssertOK() + base.Cmd("restart", sharedContainerName).AssertOK() + + baseShmSizeResult := base.Cmd("exec", baseContainerName, "/bin/grep", "shm", "/proc/self/mounts").Run() + baseOutput := strings.TrimSpace(baseShmSizeResult.Stdout()) + sharedShmSizeResult := base.Cmd("exec", sharedContainerName, "/bin/grep", "shm", "/proc/self/mounts").Run() + sharedOutput := strings.TrimSpace(sharedShmSizeResult.Stdout()) + + assert.Equal(t, baseOutput, sharedOutput) +} + func TestRestartWithTime(t *testing.T) { t.Parallel() base := testutil.NewBase(t) diff --git a/cmd/nerdctl/container_run_linux_test.go b/cmd/nerdctl/container_run_linux_test.go index e5b519c709f..63943258677 100644 --- a/cmd/nerdctl/container_run_linux_test.go +++ b/cmd/nerdctl/container_run_linux_test.go @@ -70,6 +70,64 @@ func TestRunShmSize(t *testing.T) { base.Cmd("run", "--rm", "--shm-size", shmSize, testutil.AlpineImage, "/bin/grep", "shm", "/proc/self/mounts").AssertOutContains("size=32768k") } +func TestRunShmSizeIPCShareable(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + const shmSize = "32m" + + container := testutil.Identifier(t) + base.Cmd("run", "--rm", "--name", container, "--ipc", "shareable", "--shm-size", shmSize, testutil.AlpineImage, "/bin/grep", "shm", "/proc/self/mounts").AssertOutContains("size=32768k") + defer base.Cmd("rm", "-f", container) +} + +func TestRunIPCShareableRemoveMount(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + container := testutil.Identifier(t) + + base.Cmd("run", "--name", container, "--ipc", "shareable", testutil.AlpineImage, "sleep", "0").AssertOK() + base.Cmd("rm", container).AssertOK() +} + +func TestRunIPCContainerNotExists(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + + container := testutil.Identifier(t) + result := base.Cmd("run", "--name", container, "--ipc", "container:abcd1234", testutil.AlpineImage, "sleep", "infinity").Run() + defer base.Cmd("rm", "-f", container) + combined := result.Combined() + if !strings.Contains(strings.ToLower(combined), "no such container: abcd1234") { + t.Fatalf("unexpected output: %s", combined) + } +} + +func TestRunShmSizeIPCContainer(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + + const shmSize = "32m" + sharedContainerResult := base.Cmd("run", "-d", "--ipc", "shareable", "--shm-size", shmSize, testutil.AlpineImage, "sleep", "infinity").Run() + baseContainerID := strings.TrimSpace(sharedContainerResult.Stdout()) + defer base.Cmd("rm", "-f", baseContainerID).Run() + + base.Cmd("run", "--rm", fmt.Sprintf("--ipc=container:%s", baseContainerID), + testutil.AlpineImage, "/bin/grep", "shm", "/proc/self/mounts").AssertOutContains("size=32768k") +} + +func TestRunIPCContainer(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + + const shmSize = "32m" + victimContainerResult := base.Cmd("run", "-d", "--ipc", "shareable", "--shm-size", shmSize, testutil.AlpineImage, "sleep", "infinity").Run() + victimContainerID := strings.TrimSpace(victimContainerResult.Stdout()) + defer base.Cmd("rm", "-f", victimContainerID).Run() + + base.Cmd("run", "--rm", fmt.Sprintf("--ipc=container:%s", victimContainerID), + testutil.AlpineImage, "/bin/grep", "shm", "/proc/self/mounts").AssertOutContains("size=32768k") +} + func TestRunPidHost(t *testing.T) { t.Parallel() base := testutil.NewBase(t) diff --git a/docs/command-reference.md b/docs/command-reference.md index cbd79627998..5ac33d6b565 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -351,7 +351,7 @@ Logging flags: Shared memory flags: -- :whale: `--ipc`: IPC namespace to use +- :whale: `--ipc=(host|private|shareable|container:)`: IPC namespace to use and mount `/dev/shm`. Default: "private". Only implemented on Linux. - :whale: `--shm-size`: Size of `/dev/shm` GPU flags: diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index dc5b3491bf7..fb1bf982688 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -24,7 +24,6 @@ import ( "net/url" "os" "os/exec" - "path" "path/filepath" "runtime" "strconv" @@ -44,6 +43,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/logging" "github.com/containerd/nerdctl/v2/pkg/mountutil" @@ -387,23 +387,6 @@ func generateRootfsOpts(args []string, id string, ensured *imgutil.EnsuredImage, return opts, cOpts, nil } -// withBindMountHostIPC replaces /dev/shm and /dev/mqueue mount with rbind. -// Required for --ipc=host on rootless. -func withBindMountHostIPC(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { - for i, m := range s.Mounts { - switch p := path.Clean(m.Destination); p { - case "/dev/shm", "/dev/mqueue": - s.Mounts[i] = specs.Mount{ - Destination: p, - Type: "bind", - Source: p, - Options: []string{"rbind", "nosuid", "noexec", "nodev"}, - } - } - } - return nil -} - // GenerateLogURI generates a log URI for the current container store func GenerateLogURI(dataStore string) (*url.URL, error) { selfExe, err := os.Executable() @@ -516,6 +499,8 @@ type internalLabels struct { anonVolumes []string // pid namespace pidContainer string + // ipc namespace & dev/shm + ipc string // log logURI string } @@ -591,6 +576,10 @@ func withInternalLabels(internalLabels internalLabels) (containerd.NewContainerO m[labels.PIDContainer] = internalLabels.pidContainer } + if internalLabels.ipc != "" { + m[labels.IPC] = internalLabels.ipc + } + return containerd.WithAdditionalContainerLabels(m), nil } @@ -717,6 +706,13 @@ func generateGcFunc(ctx context.Context, container containerd.Container, ns, id, } } + ipc, ipcErr := ipcutil.DecodeIPCLabel(internalLabels.ipc) + if ipcErr != nil { + log.G(ctx).WithError(ipcErr).Warnf("failed to decode ipc label for container %q", id) + } + if ipcErr := ipcutil.CleanUp(ipc); ipcErr != nil { + log.G(ctx).WithError(ipcErr).Warnf("failed to clean up ipc for container %q", id) + } if rmErr := os.RemoveAll(internalLabels.stateDir); rmErr != nil { log.G(ctx).WithError(rmErr).Warnf("failed to remove container %q state dir %q", id, internalLabels.stateDir) } diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 842f62d7e54..04c022e719b 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -36,6 +36,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/namestore" ) @@ -105,6 +106,14 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions if err != nil { return err } + ipc, err := ipcutil.DecodeIPCLabel(l[labels.IPC]) + if err != nil { + return err + } + err = ipcutil.CleanUp(ipc) + if err != nil { + return err + } stateDir := l[labels.StateDir] name := l[labels.Name] dataStore, err := clientutil.DataStore(globalOptions.DataRoot, globalOptions.Address) diff --git a/pkg/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index 06ef8416294..83773477782 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -30,9 +30,9 @@ import ( "github.com/containerd/nerdctl/v2/pkg/bypass4netnsutil" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" ) @@ -83,13 +83,6 @@ func setPlatformOptions(ctx context.Context, client *containerd.Client, id, uts return nil, err } opts = append(opts, b4nnOpts...) - if len(options.ShmSize) > 0 { - shmBytes, err := units.RAMInBytes(options.ShmSize) - if err != nil { - return nil, err - } - opts = append(opts, oci.WithDevShmSize(shmBytes/1024)) - } ulimitOpts, err := generateUlimitsOpts(options.Ulimit) if err != nil { @@ -149,15 +142,13 @@ func generateNamespaceOpts( return nil, fmt.Errorf("unknown uts value. valid value(s) are 'host', got: %q", uts) } - switch options.IPC { - case "host": - opts = append(opts, oci.WithHostNamespace(specs.IPCNamespace)) - opts = append(opts, withBindMountHostIPC) - case "private", "": - // If nothing is specified, or if private, default to normal behavior - default: - return nil, fmt.Errorf("unknown ipc value. valid values are 'private' or 'host', got: %q", options.IPC) + stateDir := internalLabels.stateDir + ipcOpts, ipcLabel, err := generateIPCOpts(ctx, client, options.IPC, options.ShmSize, stateDir) + if err != nil { + return nil, err } + internalLabels.ipc = ipcLabel + opts = append(opts, ipcOpts...) pidOpts, pidLabel, err := generatePIDOpts(ctx, client, options.Pid) if err != nil { @@ -169,6 +160,25 @@ func generateNamespaceOpts( return opts, nil } +func generateIPCOpts(ctx context.Context, client *containerd.Client, ipcFlag string, shmSize string, stateDir string) ([]oci.SpecOpts, string, error) { + ipcFlag = strings.ToLower(ipcFlag) + + ipc, err := ipcutil.DetectFlags(ctx, client, stateDir, ipcFlag, shmSize) + if err != nil { + return nil, "", err + } + ipcLabel, err := ipcutil.EncodeIPCLabel(ipc) + if err != nil { + return nil, "", err + } + opts, err := ipcutil.GenerateIPCOpts(ctx, ipc, client) + if err != nil { + return nil, "", err + } + + return opts, ipcLabel, nil +} + func generatePIDOpts(ctx context.Context, client *containerd.Client, pid string) ([]oci.SpecOpts, string, error) { opts := make([]oci.SpecOpts, 0) pid = strings.ToLower(pid) diff --git a/pkg/containerutil/config.go b/pkg/containerutil/config.go index 44bf50286dc..3031921222b 100644 --- a/pkg/containerutil/config.go +++ b/pkg/containerutil/config.go @@ -26,6 +26,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/oci" + "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" "github.com/opencontainers/runtime-spec/specs-go" @@ -104,3 +105,26 @@ func ReconfigPIDContainer(ctx context.Context, c containerd.Container, client *c } return nil } + +// ReconfigIPCContainer reconfigures the container's spec options for sharing IPC namespace and volumns. +func ReconfigIPCContainer(ctx context.Context, c containerd.Container, client *containerd.Client, lab map[string]string) error { + ipc, err := ipcutil.DecodeIPCLabel(lab[labels.IPC]) + if err != nil { + return err + } + opts, err := ipcutil.GenerateIPCOpts(ctx, ipc, client) + if err != nil { + return err + } + spec, err := c.Spec(ctx) + if err != nil { + return err + } + err = c.Update(ctx, containerd.UpdateContainerOpts( + containerd.WithSpec(spec, oci.Compose(opts...)), + )) + if err != nil { + return err + } + return nil +} diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index ad05e8fab5d..85a4ddc53c9 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -38,6 +38,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/consoleutil" "github.com/containerd/nerdctl/v2/pkg/errutil" "github.com/containerd/nerdctl/v2/pkg/formatter" + "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/nsutil" "github.com/containerd/nerdctl/v2/pkg/portutil" @@ -228,6 +229,10 @@ func Start(ctx context.Context, container containerd.Container, flagA bool, clie return err } + if err := ReconfigIPCContainer(ctx, container, client, lab); err != nil { + return err + } + process, err := container.Spec(ctx) if err != nil { return err @@ -331,6 +336,16 @@ func Stop(ctx context.Context, container containerd.Container, timeout *time.Dur if err != nil { return err } + ipc, err := ipcutil.DecodeIPCLabel(l[labels.IPC]) + if err != nil { + return err + } + // defer umount + defer func() { + if err := ipcutil.CleanUp(ipc); err != nil { + log.G(ctx).Warnf("failed to clean up IPC container %s: %s", container.ID(), err) + } + }() if timeout == nil { t, ok := l[labels.StopTimeout] diff --git a/pkg/ipcutil/ipcutil.go b/pkg/ipcutil/ipcutil.go new file mode 100644 index 00000000000..9a1ac8e9015 --- /dev/null +++ b/pkg/ipcutil/ipcutil.go @@ -0,0 +1,250 @@ +/* + 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 ipcutil + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "path" + "path/filepath" + "runtime" + "strings" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/oci" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/docker/go-units" + "github.com/opencontainers/runtime-spec/specs-go" +) + +type IPCMode string + +type IPC struct { + Mode IPCMode `json:"mode,omitempty"` + // VictimContainer is only used when mode is container + VictimContainerID *string `json:"victimContainerId,omitempty"` + + // HostShmPath is only used when mode is shareable + HostShmPath *string `json:"hostShmPath,omitempty"` + + // ShmSize is only used when mode is private or shareable + // Devshm size in bytes + ShmSize string `json:"shmSize,omitempty"` +} + +const ( + Private IPCMode = "private" + Host IPCMode = "host" + Shareable IPCMode = "shareable" + Container IPCMode = "container" +) + +// DetectFlags detects IPC mode from the given ipc string and shmSize string. +// If ipc is empty, it returns IPC{Mode: Private}. +func DetectFlags(ctx context.Context, client *containerd.Client, stateDir string, ipc string, shmSize string) (IPC, error) { + var res IPC + res.ShmSize = shmSize + switch ipc { + case "", "private": + res.Mode = Private + case "host": + res.Mode = Host + case "shareable": + res.Mode = Shareable + shmPath := filepath.Join(stateDir, "shm") + res.HostShmPath = &shmPath + default: // container: + res.Mode = Container + parsed := strings.Split(ipc, ":") + if len(parsed) < 2 || parsed[0] != "container" { + return res, fmt.Errorf("invalid ipc namespace. Set --ipc=[host|container:") + } + + containerName := parsed[1] + walker := &containerwalker.ContainerWalker{ + Client: client, + OnFound: func(ctx context.Context, found containerwalker.Found) error { + if found.MatchCount > 1 { + return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + } + victimContainerID := found.Container.ID() + res.VictimContainerID = &victimContainerID + + return nil + }, + } + matchedCount, err := walker.Walk(ctx, containerName) + if err != nil { + return res, err + } + if matchedCount < 1 { + return res, fmt.Errorf("no such container: %s", containerName) + } + } + + return res, nil +} + +// EncodeIPCLabel encodes IPC spec into a label. +func EncodeIPCLabel(ipc IPC) (string, error) { + if ipc.Mode == "" { + return "", nil + } + b, err := json.Marshal(ipc) + if err != nil { + return "", err + } + return string(b), nil +} + +// DecodeIPCLabel decodes IPC spec from a label. +// For backward compatibility, if ipcLabel is empty, it returns IPC{Mode: Private}. +func DecodeIPCLabel(ipcLabel string) (IPC, error) { + if ipcLabel == "" { + return IPC{ + Mode: Private, + }, nil + } + + var ipc IPC + if err := json.Unmarshal([]byte(ipcLabel), &ipc); err != nil { + return IPC{}, err + } + return ipc, nil +} + +// GenerateIPCOpts generates IPC spec opts from the given IPC. +func GenerateIPCOpts(ctx context.Context, ipc IPC, client *containerd.Client) ([]oci.SpecOpts, error) { + opts := make([]oci.SpecOpts, 0) + + switch ipc.Mode { + case Private: + // If nothing is specified, or if private, default to normal behavior + if len(ipc.ShmSize) > 0 { + shmBytes, err := units.RAMInBytes(ipc.ShmSize) + if err != nil { + return nil, err + } + opts = append(opts, oci.WithDevShmSize(shmBytes/1024)) + } + case Host: + opts = append(opts, withBindMountHostIPC) + if runtime.GOOS != "windows" { + opts = append(opts, oci.WithHostNamespace(specs.IPCNamespace)) + } + case Shareable: + if ipc.HostShmPath == nil { + return nil, errors.New("ipc mode is shareable, but host shm path is nil") + } + err := makeShareableDevshm(*ipc.HostShmPath, ipc.ShmSize) + if err != nil { + return nil, err + } + opts = append(opts, withBindMountHostOtherSourceIPC(*ipc.HostShmPath)) + case Container: + if ipc.VictimContainerID == nil { + return nil, errors.New("ipc mode is container, but victim container id is nil") + } + targetCon, err := client.LoadContainer(ctx, *ipc.VictimContainerID) + if err != nil { + return nil, err + } + + task, err := targetCon.Task(ctx, nil) + if err != nil { + return nil, err + } + + status, err := task.Status(ctx) + if err != nil { + return nil, err + } + + if status.Status != containerd.Running { + return nil, fmt.Errorf("shared container is not running") + } + + targetConLabels, err := targetCon.Labels(ctx) + if err != nil { + return nil, err + } + + targetConIPC, err := DecodeIPCLabel(targetConLabels[labels.IPC]) + if err != nil { + return nil, err + } + + if targetConIPC.Mode == Host { + opts = append(opts, oci.WithHostNamespace(specs.IPCNamespace)) + opts = append(opts, withBindMountHostIPC) + return opts, nil + } else if targetConIPC.Mode != Shareable { + return nil, errors.New("victim container's ipc mode is not shareable") + } + + if targetConIPC.HostShmPath == nil { + return nil, errors.New("victim container's host shm path is nil") + } + + opts = append(opts, withBindMountHostOtherSourceIPC(*targetConIPC.HostShmPath)) + } + + return opts, nil +} + +// WithBindMountHostOtherSourceIPC replaces /dev/shm mount with rbind by the given path on host +func withBindMountHostOtherSourceIPC(source string) oci.SpecOpts { + return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { + for i, m := range s.Mounts { + p := path.Clean(m.Destination) + if p == "/dev/shm" { + s.Mounts[i] = specs.Mount{ + Type: "bind", + Destination: p, + Source: source, + Options: []string{"rbind", "nosuid", "noexec", "nodev"}, + } + } + } + return nil + } +} + +// WithBindMountHostIPC replaces /dev/shm and /dev/mqueue mount with rbind. +// Required for --ipc=host on rootless. +func withBindMountHostIPC(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error { + for i, m := range s.Mounts { + switch p := path.Clean(m.Destination); p { + case "/dev/shm", "/dev/mqueue": + s.Mounts[i] = specs.Mount{ + Destination: p, + Type: "bind", + Source: p, + Options: []string{"rbind", "nosuid", "noexec", "nodev"}, + } + } + } + return nil +} + +func CleanUp(ipc IPC) error { + return cleanUpPlatformSpecificIPC(ipc) +} diff --git a/pkg/ipcutil/ipcutil_linux.go b/pkg/ipcutil/ipcutil_linux.go new file mode 100644 index 00000000000..1c676abb027 --- /dev/null +++ b/pkg/ipcutil/ipcutil_linux.go @@ -0,0 +1,64 @@ +//go:build linux + +/* + 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 ipcutil + +import ( + "fmt" + "os" + + "github.com/docker/go-units" + "golang.org/x/sys/unix" +) + +// makeShareableDevshm returns devshm directory path on host when there is no error. +func makeShareableDevshm(shmPath, shmSize string) error { + shmproperty := "mode=1777" + if len(shmSize) > 0 { + shmBytes, err := units.RAMInBytes(shmSize) + if err != nil { + return err + } + shmproperty = fmt.Sprintf("%s,size=%d", shmproperty, shmBytes) + } + err := os.MkdirAll(shmPath, 0700) + if err != nil { + return err + } + err = unix.Mount("/dev/shm", shmPath, "tmpfs", uintptr(unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV), shmproperty) + if err != nil { + return err + } + + return nil +} + +// cleanUpPlatformSpecificIPC cleans up platform specific IPC. +func cleanUpPlatformSpecificIPC(ipc IPC) error { + if ipc.Mode == Shareable && ipc.HostShmPath != nil { + err := unix.Unmount(*ipc.HostShmPath, 0) + if err != nil { + return err + } + err = os.RemoveAll(*ipc.HostShmPath) + if err != nil { + return err + } + } + return nil +} diff --git a/pkg/ipcutil/ipcutil_unix.go b/pkg/ipcutil/ipcutil_unix.go new file mode 100644 index 00000000000..c5664fc2732 --- /dev/null +++ b/pkg/ipcutil/ipcutil_unix.go @@ -0,0 +1,34 @@ +//go:build freebsd + +/* + 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 ipcutil + +import "fmt" + +// makeShareableDevshm returns devshm directory path on host when there is no error. +func makeShareableDevshm(shmPath, shmSize string) error { + return fmt.Errorf("unix does not support shareable devshm") +} + +// cleanUpPlatformSpecificIPC cleans up platform specific IPC. +func cleanUpPlatformSpecificIPC(ipc IPC) error { + if ipc.Mode == Shareable { + return fmt.Errorf("unix does not support shareable devshm") + } + return nil +} diff --git a/pkg/ipcutil/ipcutil_windows.go b/pkg/ipcutil/ipcutil_windows.go new file mode 100644 index 00000000000..5e9d4aa391d --- /dev/null +++ b/pkg/ipcutil/ipcutil_windows.go @@ -0,0 +1,32 @@ +/* + 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 ipcutil + +import "fmt" + +// makeShareableDevshm returns devshm directory path on host when there is no error. +func makeShareableDevshm(shmPath, shmSize string) error { + return fmt.Errorf("windows does not support shareable devshm") +} + +// cleanUpPlatformSpecificIPC cleans up platform specific IPC. +func cleanUpPlatformSpecificIPC(ipc IPC) error { + if ipc.Mode == Shareable { + return fmt.Errorf("windows does not support shareable devshm") + } + return nil +} diff --git a/pkg/labels/labels.go b/pkg/labels/labels.go index fc0b5a574dd..40e82971fd4 100644 --- a/pkg/labels/labels.go +++ b/pkg/labels/labels.go @@ -92,6 +92,10 @@ const ( // PIDContainer is the `nerdctl run --pid` for restarting PIDContainer = Prefix + "pid-container" + // IPC is the `nerectl run --ipc` for restrating + // IPC indicates ipc victim container. + IPC = Prefix + "ipc" + // Error encapsulates a container human-readable string // that describes container error. Error = Prefix + "error" From 741d06e5674d0b3a7456df7288e795aab2c2dc2a Mon Sep 17 00:00:00 2001 From: Spencer von der Ohe Date: Sat, 3 Feb 2024 22:42:31 -0700 Subject: [PATCH 0322/1066] Add support to run systemd in containers (with --systemd flag) Signed-off-by: Spencer von der Ohe --- README.md | 1 + cmd/nerdctl/container_create.go | 4 + cmd/nerdctl/container_run.go | 1 + .../container_run_systemd_linux_test.go | 104 ++++++++++++++++++ docs/command-reference.md | 9 ++ pkg/api/types/container_types.go | 2 + pkg/cmd/container/create.go | 50 ++++++++- pkg/testutil/testutil_linux.go | 1 + 8 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 cmd/nerdctl/container_run_systemd_linux_test.go diff --git a/README.md b/README.md index 1d4e6863779..7e3ee8b8c77 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,7 @@ Minor: - Better multi-platform support, e.g., `nerdctl pull --all-platforms IMAGE` - Applying an (existing) AppArmor profile to rootless containers: `nerdctl run --security-opt apparmor=`. Use `sudo nerdctl apparmor load` to load the `nerdctl-default` profile. +- Systemd compatibility support: `nerdctl run --systemd=always` Trivial: diff --git a/cmd/nerdctl/container_create.go b/cmd/nerdctl/container_create.go index f196e02cb05..de99a782671 100644 --- a/cmd/nerdctl/container_create.go +++ b/cmd/nerdctl/container_create.go @@ -255,6 +255,10 @@ func processContainerCreateOptions(cmd *cobra.Command) (opt types.ContainerCreat if err != nil { return } + opt.Systemd, err = cmd.Flags().GetString("systemd") + if err != nil { + return + } // #endregion // #region for runtime flags diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 5d74b627680..077332d447c 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -184,6 +184,7 @@ func setCreateFlags(cmd *cobra.Command) { cmd.Flags().StringSlice("cap-drop", []string{}, "Drop Linux capabilities") cmd.RegisterFlagCompletionFunc("cap-drop", capShellComplete) cmd.Flags().Bool("privileged", false, "Give extended privileges to this container") + cmd.Flags().String("systemd", "false", "Allow running systemd in this container (default: false)") // #endregion // #region runtime flags diff --git a/cmd/nerdctl/container_run_systemd_linux_test.go b/cmd/nerdctl/container_run_systemd_linux_test.go new file mode 100644 index 00000000000..770c62a438f --- /dev/null +++ b/cmd/nerdctl/container_run_systemd_linux_test.go @@ -0,0 +1,104 @@ +/* + 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 ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestRunWithSystemdAlways(t *testing.T) { + testutil.DockerIncompatible(t) + t.Parallel() + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + defer base.Cmd("container", "rm", "-f", containerName).AssertOK() + + base.Cmd("run", "--name", containerName, "--systemd=always", "--entrypoint=/bin/bash", testutil.UbuntuImage, "-c", "mount | grep cgroup").AssertOutContains("(rw,") + + base.Cmd("inspect", "--format", "{{json .Config.Labels}}", containerName).AssertOutContains("SIGRTMIN+3") + +} + +func TestRunWithSystemdTrueEnabled(t *testing.T) { + testutil.DockerIncompatible(t) + t.Parallel() + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + defer base.Cmd("container", "rm", "-f", containerName).AssertOK() + + base.Cmd("run", "-d", "--name", containerName, "--systemd=true", "--entrypoint=/sbin/init", testutil.SystemdImage).AssertOK() + + base.Cmd("inspect", "--format", "{{json .Config.Labels}}", containerName).AssertOutContains("SIGRTMIN+3") + + base.Cmd("exec", containerName, "systemctl", "list-jobs").AssertOutContains("jobs listed.") +} + +func TestRunWithSystemdTrueDisabled(t *testing.T) { + testutil.DockerIncompatible(t) + t.Parallel() + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + defer base.Cmd("rm", "-f", containerName).AssertOK() + + base.Cmd("run", "--name", containerName, "--systemd=true", "--entrypoint=/bin/bash", testutil.SystemdImage, "-c", "systemctl list-jobs || true").AssertCombinedOutContains("System has not been booted with systemd as init system") +} + +func TestRunWithSystemdFalse(t *testing.T) { + testutil.DockerIncompatible(t) + t.Parallel() + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + defer base.Cmd("rm", "-f", containerName).AssertOK() + + base.Cmd("run", "--name", containerName, "--systemd=false", "--entrypoint=/bin/bash", testutil.UbuntuImage, "-c", "mount | grep cgroup").AssertOutContains("(ro,") + + base.Cmd("inspect", "--format", "{{json .Config.Labels}}", containerName).AssertOutContains("SIGTERM") +} + +func TestRunWithNoSystemd(t *testing.T) { + testutil.DockerIncompatible(t) + t.Parallel() + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + defer base.Cmd("rm", "-f", containerName).AssertOK() + + base.Cmd("run", "--name", containerName, "--entrypoint=/bin/bash", testutil.UbuntuImage, "-c", "mount | grep cgroup").AssertOutContains("(ro,") + + base.Cmd("inspect", "--format", "{{json .Config.Labels}}", containerName).AssertOutContains("SIGTERM") +} + +func TestRunWithSystemdPrivilegedError(t *testing.T) { + testutil.DockerIncompatible(t) + t.Parallel() + base := testutil.NewBase(t) + + base.Cmd("run", "--privileged", "--rm", "--systemd=always", "--entrypoint=/sbin/init", testutil.SystemdImage).AssertCombinedOutContains("if --privileged is used with systemd `--security-opt privileged-without-host-devices` must also be used") +} + +func TestRunWithSystemdPrivilegedSuccess(t *testing.T) { + testutil.DockerIncompatible(t) + t.Parallel() + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + defer base.Cmd("container", "rm", "-f", containerName).AssertOK() + + base.Cmd("run", "-d", "--name", containerName, "--privileged", "--security-opt", "privileged-without-host-devices", "--systemd=true", "--entrypoint=/sbin/init", testutil.SystemdImage).AssertOK() + + base.Cmd("inspect", "--format", "{{json .Config.Labels}}", containerName).AssertOutContains("SIGRTMIN+3") +} diff --git a/docs/command-reference.md b/docs/command-reference.md index cbd79627998..510fe2df8e1 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -232,6 +232,15 @@ Security flags: - :whale: `--cap-add=`: Add Linux capabilities - :whale: `--cap-drop=`: Drop Linux capabilities - :whale: `--privileged`: Give extended privileges to this container +- :nerd_face: `--systemd=(true|false|always)`: Enable systemd compatibility (default: false). + - Default: "false" + - true: Enable systemd compatibility is enabled if the entrypoint executable matches one of the following paths: + - `/sbin/init` + - `/usr/sbin/init` + - `/usr/local/sbin/init` + - always: Always enable systemd compatibility + +Corresponds to Podman CLI. Runtime flags: diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index 4c30443b990..f4c4f6f1b16 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -169,6 +169,8 @@ type ContainerCreateOptions struct { CapDrop []string // Privileged gives extended privileges to this container Privileged bool + // Systemd + Systemd string // #endregion // #region for runtime flags diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index fbd51ff302f..8b731d53a09 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -46,6 +46,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/logging" + "github.com/containerd/nerdctl/v2/pkg/maputil" "github.com/containerd/nerdctl/v2/pkg/mountutil" "github.com/containerd/nerdctl/v2/pkg/namestore" "github.com/containerd/nerdctl/v2/pkg/platformutil" @@ -173,7 +174,6 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa return nil, nil, err } cOpts = append(cOpts, restartOpts...) - cOpts = append(cOpts, withStop(options.StopSignal, options.StopTimeout, ensuredImage)) if err = netManager.VerifyNetworkOptions(ctx); err != nil { return nil, nil, fmt.Errorf("failed to verify networking settings: %s", err) @@ -340,6 +340,15 @@ func generateRootfsOpts(args []string, id string, ensured *imgutil.EnsuredImage, opts = append(opts, oci.WithRootFSPath(absRootfs), oci.WithDefaultPathEnv) } + entrypointPath := "" + if ensured != nil { + if len(ensured.ImageConfig.Entrypoint) > 0 { + entrypointPath = ensured.ImageConfig.Entrypoint[0] + } else if len(ensured.ImageConfig.Cmd) > 0 { + entrypointPath = ensured.ImageConfig.Cmd[0] + } + } + if !options.Rootfs && !options.EntrypointChanged { opts = append(opts, oci.WithImageConfigArgs(ensured.Image, args[1:])) } else { @@ -357,8 +366,47 @@ func generateRootfsOpts(args []string, id string, ensured *imgutil.EnsuredImage, // error message is from Podman return nil, nil, errors.New("no command or entrypoint provided, and no CMD or ENTRYPOINT from image") } + + entrypointPath = processArgs[0] + opts = append(opts, oci.WithProcessArgs(processArgs...)) } + + isEntryPointSystemd := (entrypointPath == "/sbin/init" || + entrypointPath == "/usr/sbin/init" || + entrypointPath == "/usr/local/sbin/init") + + stopSignal := options.StopSignal + + if options.Systemd == "always" || (options.Systemd == "true" && isEntryPointSystemd) { + if options.Privileged { + securityOptsMap := strutil.ConvertKVStringsToMap(strutil.DedupeStrSlice(options.SecurityOpt)) + privilegedWithoutHostDevices, err := maputil.MapBoolValueAsOpt(securityOptsMap, "privileged-without-host-devices") + if err != nil { + return nil, nil, err + } + + // See: https://github.com/containers/podman/issues/15878 + if !privilegedWithoutHostDevices { + return nil, nil, errors.New("if --privileged is used with systemd `--security-opt privileged-without-host-devices` must also be used") + } + } + + opts = append(opts, + oci.WithoutMounts("/sys/fs/cgroup"), + oci.WithMounts([]specs.Mount{ + {Type: "cgroup", Source: "cgroup", Destination: "/sys/fs/cgroup", Options: []string{"rw"}}, + {Type: "tmpfs", Source: "tmpfs", Destination: "/run"}, + {Type: "tmpfs", Source: "tmpfs", Destination: "/run/lock"}, + {Type: "tmpfs", Source: "tmpfs", Destination: "/tmp"}, + {Type: "tmpfs", Source: "tmpfs", Destination: "/var/lib/journal"}, + }), + ) + stopSignal = "SIGRTMIN+3" + } + + cOpts = append(cOpts, withStop(stopSignal, options.StopTimeout, ensured)) + if options.InitBinary != nil { options.InitProcessFlag = true } diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index adbc5fbc775..41266be6109 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -41,6 +41,7 @@ var ( DockerAuthImage = mirrorOf("cesanta/docker_auth:1.7") FluentdImage = mirrorOf("fluent/fluentd:v1.14-1") KuboImage = mirrorOf("ipfs/kubo:v0.16.0") + SystemdImage = "ghcr.io/containerd/stargz-snapshotter:0.15.1-kind" // Source: https://gist.github.com/cpuguy83/fcf3041e5d8fb1bb5c340915aabeebe0 NonDistBlobImage = "ghcr.io/cpuguy83/non-dist-blob:latest" From 9ae613b33979c0e928ba172fd359adc98714d469 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 1 Feb 2024 08:38:26 +0000 Subject: [PATCH 0323/1066] support build attest Signed-off-by: Kay Yan --- cmd/nerdctl/builder_build.go | 36 +++++++++++++++++++ cmd/nerdctl/builder_build_test.go | 57 +++++++++++++++++++++++++++++++ docs/command-reference.md | 3 ++ pkg/api/types/builder_types.go | 2 ++ pkg/cmd/builder/build.go | 10 ++++++ 5 files changed, 108 insertions(+) diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index a4d159791ac..4952451f0df 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "os" + "strconv" "strings" "github.com/containerd/nerdctl/v2/pkg/api/types" @@ -50,13 +51,16 @@ If Dockerfile is not present and -f is not specified, it will look for Container buildCommand.Flags().Bool("no-cache", false, "Do not use cache when building the image") buildCommand.Flags().StringP("output", "o", "", "Output destination (format: type=local,dest=path)") buildCommand.Flags().String("progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output") + buildCommand.Flags().String("provenance", "", "Shorthand for \"--attest=type=provenance\"") buildCommand.Flags().StringArray("secret", nil, "Secret file to expose to the build: id=mysecret,src=/local/secret") buildCommand.Flags().StringArray("allow", nil, "Allow extra privileged entitlement, e.g. network.host, security.insecure") buildCommand.RegisterFlagCompletionFunc("allow", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"network.host", "security.insecure"}, cobra.ShellCompDirectiveNoFileComp }) + buildCommand.Flags().StringArray("attest", nil, "Attestation parameters (format: \"type=sbom,generator=image\")") buildCommand.Flags().StringArray("ssh", nil, "SSH agent socket or keys to expose to the build (format: default|[=|[,]])") buildCommand.Flags().BoolP("quiet", "q", false, "Suppress the build output and print image ID on success") + buildCommand.Flags().String("sbom", "", "Shorthand for \"--attest=type=sbom\"") buildCommand.Flags().StringArray("cache-from", nil, "External cache sources (eg. user/app:cache, type=local,src=path/to/dir)") buildCommand.Flags().StringArray("cache-to", nil, "Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir)") buildCommand.Flags().Bool("rm", true, "Remove intermediate containers after a successful build") @@ -165,6 +169,26 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu if err != nil { return types.BuilderBuildOptions{}, err } + + attest, err := cmd.Flags().GetStringArray("attest") + if err != nil { + return types.BuilderBuildOptions{}, err + } + sbom, err := cmd.Flags().GetString("sbom") + if err != nil { + return types.BuilderBuildOptions{}, err + } + if sbom != "" { + attest = append(attest, canonicalizeAttest("sbom", sbom)) + } + provenance, err := cmd.Flags().GetString("provenance") + if err != nil { + return types.BuilderBuildOptions{}, err + } + if provenance != "" { + attest = append(attest, canonicalizeAttest("provenance", provenance)) + } + return types.BuilderBuildOptions{ GOptions: globalOptions, BuildKitHost: buildKitHost, @@ -179,6 +203,7 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu NoCache: noCache, Secret: secret, Allow: allow, + Attest: attest, SSH: ssh, CacheFrom: cacheFrom, CacheTo: cacheTo, @@ -222,3 +247,14 @@ func buildAction(cmd *cobra.Command, args []string) error { return builder.Build(ctx, client, options) } + +// canonicalizeAttest is from https://github.com/docker/buildx/blob/v0.12/util/buildflags/attests.go##L13-L21 +func canonicalizeAttest(attestType string, in string) string { + if in == "" { + return "" + } + if b, err := strconv.ParseBool(in); err == nil { + return fmt.Sprintf("type=%s,disabled=%t", attestType, !b) + } + return fmt.Sprintf("type=%s,%s", attestType, in) +} diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index 96cb281a9c2..e43a3a2ace8 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -498,3 +498,60 @@ func TestBuildNetworkShellCompletion(t *testing.T) { networkName := "default" base.Cmd(gsc, "build", "--network", "").AssertOutContains(networkName) } + +func buildWithNamedBuilder(base *testutil.Base, builderName string, args ...string) *testutil.Cmd { + buildArgs := []string{"build"} + if testutil.GetTarget() == testutil.Docker { + buildArgs = append(buildArgs, "--builder", builderName) + } + buildArgs = append(buildArgs, args...) + return base.Cmd(buildArgs...) +} + +func TestBuildAttestation(t *testing.T) { + t.Parallel() + testutil.RequiresBuild(t) + base := testutil.NewBase(t) + builderName := testutil.Identifier(t) + if testutil.GetTarget() == testutil.Docker { + // create named builder for docker + defer base.Cmd("buildx", "rm", builderName).AssertOK() + base.Cmd("buildx", "create", "--name", builderName, "--bootstrap", "--use").AssertOK() + } + defer base.Cmd("builder", "prune").Run() + + dockerfile := "FROM " + testutil.NginxAlpineImage + buildCtx, err := createBuildContext(dockerfile) + assert.NilError(t, err) + defer os.RemoveAll(buildCtx) + + // Test sbom + outputSBOMDir := t.TempDir() + buildWithNamedBuilder(base, builderName, "--sbom=true", "-o", fmt.Sprintf("type=local,dest=%s", outputSBOMDir), buildCtx).AssertOK() + const testSBOMFileName = "sbom.spdx.json" + testSBOMFilePath := filepath.Join(outputSBOMDir, testSBOMFileName) + if _, err := os.Stat(testSBOMFilePath); err != nil { + t.Fatal(err) + } + + // Test provenance + outputProvenanceDir := t.TempDir() + buildWithNamedBuilder(base, builderName, "--provenance=mode=min", "-o", fmt.Sprintf("type=local,dest=%s", outputProvenanceDir), buildCtx).AssertOK() + const testProvenanceFileName = "provenance.json" + testProvenanceFilePath := filepath.Join(outputProvenanceDir, testProvenanceFileName) + if _, err := os.Stat(testProvenanceFilePath); err != nil { + t.Fatal(err) + } + + // Test attestation + outputAttestationDir := t.TempDir() + buildWithNamedBuilder(base, builderName, "--attest=type=provenance,mode=min", "--attest=type=sbom", "-o", fmt.Sprintf("type=local,dest=%s", outputAttestationDir), buildCtx).AssertOK() + testSBOMFilePath = filepath.Join(outputAttestationDir, testSBOMFileName) + testProvenanceFilePath = filepath.Join(outputAttestationDir, testProvenanceFileName) + if _, err := os.Stat(testSBOMFilePath); err != nil { + t.Fatal(err) + } + if _, err := os.Stat(testProvenanceFilePath); err != nil { + t.Fatal(err) + } +} diff --git a/docs/command-reference.md b/docs/command-reference.md index cbd79627998..4d2b93c9e7d 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -680,10 +680,13 @@ Flags: - :whale: `type=tar[,dest=path/to/output.tar]`: Raw tar ball - :whale: `type=image,name=example.com/image,push=true`: Push to a registry (see [`buildctl build`](https://github.com/moby/buildkit/tree/v0.9.0#imageregistry) documentation) - :whale: `--progress=(auto|plain|tty)`: Set type of progress output (auto, plain, tty). Use plain to show container output +- :whale: `--provenance`: Shorthand for \"--attest=type=provenance\", see [`buildx_build.md`](https://github.com/docker/buildx/blob/v0.12.1/docs/reference/buildx_build.md#provenance) documentation - :whale: `--secret`: Secret file to expose to the build: id=mysecret,src=/local/secret - :whale: `--allow`: Allow extra privileged entitlement, e.g. network.host, security.insecure (It’s required to configure the buildkitd to enable the feature, see [`buildkitd.toml`](https://github.com/moby/buildkit/blob/master/docs/buildkitd.toml.md) documentation) +- :whale: `--attest`: Attestation parameters (format: "type=sbom,generator=image"), see [`buildx_build.md`](https://github.com/docker/buildx/blob/v0.12.1/docs/reference/buildx_build.md#attest) documentation - :whale: `--ssh`: SSH agent socket or keys to expose to the build (format: `default|[=|[,]]`) - :whale: `-q, --quiet`: Suppress the build output and print image ID on success +- :whale: `--sbom`: Shorthand for \"--attest=type=sbom\", see [`buildx_build.md`](https://github.com/docker/buildx/blob/v0.12.1/docs/reference/buildx_build.md#sbom) documentation - :whale: `--cache-from=CACHE`: External cache sources (eg. user/app:cache, type=local,src=path/to/dir) (compatible with `docker buildx build`) - :whale: `--cache-to=CACHE`: Cache export destinations (eg. user/app:cache, type=local,dest=path/to/dir) (compatible with `docker buildx build`) - :whale: `--platform=(amd64|arm64|...)`: Set target platform for build (compatible with `docker buildx build`) diff --git a/pkg/api/types/builder_types.go b/pkg/api/types/builder_types.go index 460814e9c0d..f7fb0f772fa 100644 --- a/pkg/api/types/builder_types.go +++ b/pkg/api/types/builder_types.go @@ -45,6 +45,8 @@ type BuilderBuildOptions struct { Secret []string // Allow extra privileged entitlement, e.g. network.host, security.insecure Allow []string + // Attestation parameters (format: "type=sbom,generator=image")" + Attest []string // SSH agent socket or keys to expose to the build (format: default|[=|[,]]) SSH []string // Quiet suppress the build output and print image ID on success diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 85c6e227247..99eb9b2e0ba 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -338,6 +338,16 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option buildctlArgs = append(buildctlArgs, "--allow="+s) } + for _, s := range strutil.DedupeStrSlice(options.Attest) { + optAttestType, optAttestAttrs, _ := strings.Cut(s, ",") + if strings.HasPrefix(optAttestType, "type=") { + optAttestType := strings.TrimPrefix(optAttestType, "type=") + buildctlArgs = append(buildctlArgs, fmt.Sprintf("--opt=attest:%s=%s", optAttestType, optAttestAttrs)) + } else { + return "", nil, false, "", nil, nil, fmt.Errorf("attestation type not specified") + } + } + for _, s := range strutil.DedupeStrSlice(options.SSH) { buildctlArgs = append(buildctlArgs, "--ssh="+s) } From 6a229537458cfb2cf71448915208604561b9f815 Mon Sep 17 00:00:00 2001 From: roman-kiselenko Date: Mon, 5 Feb 2024 12:24:49 +0300 Subject: [PATCH 0324/1066] `containerd-rootless-setuptool.sh uninstall` cleanup all relevant services Signed-off-by: roman-kiselenko --- extras/rootless/containerd-rootless-setuptool.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extras/rootless/containerd-rootless-setuptool.sh b/extras/rootless/containerd-rootless-setuptool.sh index 1ecc63e4351..9b31d5efe2c 100755 --- a/extras/rootless/containerd-rootless-setuptool.sh +++ b/extras/rootless/containerd-rootless-setuptool.sh @@ -512,8 +512,14 @@ cmd_entrypoint_install_ipfs() { cmd_entrypoint_uninstall() { init uninstall_systemd_unit "${SYSTEMD_BUILDKIT_UNIT}" + if [ -n "${CONTAINERD_NAMESPACE:-}" ]; then + uninstall_systemd_unit "${CONTAINERD_NAMESPACE}-${SYSTEMD_BUILDKIT_UNIT}" + fi uninstall_systemd_unit "${SYSTEMD_FUSE_OVERLAYFS_UNIT}" uninstall_systemd_unit "${SYSTEMD_CONTAINERD_UNIT}" + uninstall_systemd_unit "${SYSTEMD_STARGZ_UNIT}" + uninstall_systemd_unit "${SYSTEMD_IPFS_UNIT}" + uninstall_systemd_unit "${SYSTEMD_BYPASS4NETNSD_UNIT}" INFO "This uninstallation tool does NOT remove containerd binaries and data." INFO "To remove data, run: \`$BIN/rootlesskit rm -rf ${XDG_DATA_HOME}/containerd\`" From c797578e06112ebfede3decfefc52471f9d444ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 22:41:22 +0000 Subject: [PATCH 0325/1066] build(deps): bump github.com/klauspost/compress from 1.17.5 to 1.17.6 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.5 to 1.17.6. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.5...v1.17.6) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c64965409b2..0cdaa9cc60b 100644 --- a/go.mod +++ b/go.mod @@ -96,7 +96,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.5 + github.com/klauspost/compress v1.17.6 github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect diff --git a/go.sum b/go.sum index c9e98c38f65..71ee6ede05e 100644 --- a/go.sum +++ b/go.sum @@ -178,8 +178,8 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPquI5E= -github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= +github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= From ae224f40faf6e3065ea981aa6e00ff9911d142e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 22:41:31 +0000 Subject: [PATCH 0326/1066] build(deps): bump github.com/containerd/console from 1.0.3 to 1.0.4 Bumps [github.com/containerd/console](https://github.com/containerd/console) from 1.0.3 to 1.0.4. - [Release notes](https://github.com/containerd/console/releases) - [Commits](https://github.com/containerd/console/compare/v1.0.3...v1.0.4) --- updated-dependencies: - dependency-name: github.com/containerd/console dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c64965409b2..5ea418d6aa3 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/compose-spec/compose-go v1.20.2 github.com/containerd/accelerated-container-image v1.0.2 github.com/containerd/cgroups/v3 v3.0.3 - github.com/containerd/console v1.0.3 + github.com/containerd/console v1.0.4 github.com/containerd/containerd v1.7.13 github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 diff --git a/go.sum b/go.sum index c9e98c38f65..8aae7acf0a6 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,8 @@ github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHq github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +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.13 h1:wPYKIeGMN8vaggSKuV1X0wZulpMz4CrgEsZdaCyB6Is= github.com/containerd/containerd v1.7.13/go.mod h1:zT3up6yTRfEUa6+GsITYIJNgSVL9NQ4x4h1RPzk0Wu4= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= From 5733be85e407a978fb992050785ddb06f391ce7f Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 6 Feb 2024 12:02:52 +0900 Subject: [PATCH 0327/1066] update RootlessKit (2.0.1) https://github.com/rootless-containers/rootlesskit/releases/tag/v2.0.1 Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 8 ++++---- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.0 | 6 ------ Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.1 | 6 ++++++ 4 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 683c3e7cbc0..27378e313bf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -162,7 +162,7 @@ jobs: target: test-integration-rootless - ubuntu: 20.04 containerd: v1.7.13 - rootlesskit: v2.0.0 + rootlesskit: v2.0.1 target: test-integration-rootless - ubuntu: 22.04 containerd: v1.7.13 @@ -170,7 +170,7 @@ jobs: target: test-integration-rootless - ubuntu: 22.04 containerd: main - rootlesskit: v2.0.0 + rootlesskit: v2.0.1 target: test-integration-rootless - ubuntu: 20.04 containerd: v1.6.28 @@ -178,7 +178,7 @@ jobs: target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 containerd: v1.7.13 - rootlesskit: v2.0.0 + rootlesskit: v2.0.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: v1.7.13 @@ -186,7 +186,7 @@ jobs: target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main - rootlesskit: v2.0.0 + rootlesskit: v2.0.1 target: test-integration-rootless-port-slirp4netns env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" diff --git a/Dockerfile b/Dockerfile index 956995d25f8..9bdb566c253 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption ARG IMGCRYPT_VERSION=v1.1.9 # Extra deps: Rootless -ARG ROOTLESSKIT_VERSION=v2.0.0 +ARG ROOTLESSKIT_VERSION=v2.0.1 ARG SLIRP4NETNS_VERSION=v1.2.2 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.4.0 diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.0 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.0 deleted file mode 100644 index 933f7fc1276..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.0 +++ /dev/null @@ -1,6 +0,0 @@ -c24c13b0a7d74ea2ce9c44ca13810844149c93b5d193a08bf21166d08706621c rootlesskit-aarch64.tar.gz -da79e531f38688aad050c93e0c4d2b1f33e888e9dc6301f9866eabfec93bc75f rootlesskit-armv7l.tar.gz -181e9ff0c9ee0286b7b5384893b5dc6498098eee7014de253f053e3b50fdcbdb rootlesskit-ppc64le.tar.gz -709527301c6c4046cbe0ef5043a866ca7cfd105d91dee4a49ef3c85c8e57de5a rootlesskit-riscv64.tar.gz -28a8d3eb8eb6fc49cba4819a3a74be6319e7060707e37ca02425107ed65c034e rootlesskit-s390x.tar.gz -8205e3f96ca9eb576a0b182455fb5ad1067bf019a7fe50a1816f6c04b581723f rootlesskit-x86_64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.1 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.1 new file mode 100644 index 00000000000..6923226f370 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.1 @@ -0,0 +1,6 @@ +d250ae03e58541bce83842f8ec4f2190a2a55a437a3c9c156c1f20093522cca1 rootlesskit-aarch64.tar.gz +386745a013dc38681a2f797cb13d466f99c351d613c687ad4540449088deaa36 rootlesskit-armv7l.tar.gz +9569dc8efdb6dd07b8ce81c45f607b15f7bb41b55cfa7f15ad3cb6ae85061d82 rootlesskit-ppc64le.tar.gz +064b10c554c19a4d86934d825e37a97e83e3bc92ec70f0460c9533a383794804 rootlesskit-riscv64.tar.gz +9d03267f3a18c4d78055f877d5b0dc2e08e8d019d7b3e866e3361ef528ae0dda rootlesskit-s390x.tar.gz +6b1ecb61a48d85e6b41c4a67b81f6db47f626e010a481666a1859776b45439aa rootlesskit-x86_64.tar.gz From 2d59841bdc4834dab6e98ba78bf0e62cfcbe768e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 03:13:23 +0000 Subject: [PATCH 0328/1066] build(deps): bump github.com/rootless-containers/rootlesskit/v2 Bumps [github.com/rootless-containers/rootlesskit/v2](https://github.com/rootless-containers/rootlesskit) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/rootless-containers/rootlesskit/releases) - [Commits](https://github.com/rootless-containers/rootlesskit/compare/v2.0.0...v2.0.1) --- updated-dependencies: - dependency-name: github.com/rootless-containers/rootlesskit/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 5ea418d6aa3..a0fe836ba9a 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( 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 - github.com/rootless-containers/rootlesskit/v2 v2.0.0 + github.com/rootless-containers/rootlesskit/v2 v2.0.1 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/tidwall/gjson v1.17.0 @@ -91,7 +91,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/uuid v1.5.0 // indirect + github.com/google/uuid v1.6.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 diff --git a/go.sum b/go.sum index 8aae7acf0a6..41b539cae96 100644 --- a/go.sum +++ b/go.sum @@ -161,8 +161,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.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= @@ -270,8 +270,8 @@ github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwa github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rootless-containers/bypass4netns v0.4.0 h1:7pcI4XWnOMQkgCsPKMXxMzQKhZUjaQ8J1n+eIYiHS0Y= github.com/rootless-containers/bypass4netns v0.4.0/go.mod h1:RPNWMSRT951DMtq9Xv72IZoJPWFeJL6Wg5pF79Lkano= -github.com/rootless-containers/rootlesskit/v2 v2.0.0 h1:oAtnD6sgsNmdxXCm5zont5nEYTAkSqExmQOalZYiYJM= -github.com/rootless-containers/rootlesskit/v2 v2.0.0/go.mod h1:G7x0sK6onoLhFYZahpSsM/HaWEAh664SK5nCeQs4MQE= +github.com/rootless-containers/rootlesskit/v2 v2.0.1 h1:yMUDTn9dMWtTkccosPDJpMVxjhmEjSD6jYyaePCXshg= +github.com/rootless-containers/rootlesskit/v2 v2.0.1/go.mod h1:ZwETpgA/DPizAF7Zdui4ZHOfYK5rZ4Z4SUO6omyZVfY= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= From cfc063ccedf8ddf1d016ef8bd6708380229b3fe3 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 7 Feb 2024 02:22:03 +0900 Subject: [PATCH 0329/1066] update slirp4netns (1.2.3) https://github.com/rootless-containers/slirp4netns/releases/tag/v1.2.3 Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.2 | 7 ------- Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.3 | 7 +++++++ 3 files changed, 8 insertions(+), 8 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.2 create mode 100644 Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.3 diff --git a/Dockerfile b/Dockerfile index 9bdb566c253..c8d173d3de8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 ARG IMGCRYPT_VERSION=v1.1.9 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v2.0.1 -ARG SLIRP4NETNS_VERSION=v1.2.2 +ARG SLIRP4NETNS_VERSION=v1.2.3 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.4.0 # Extra deps: FUSE-OverlayFS diff --git a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.2 b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.2 deleted file mode 100644 index 651745bffc8..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.2 +++ /dev/null @@ -1,7 +0,0 @@ -d269b4788a54e6bcc0669a80704ec75e4f6be7c827846b57163b9da3d4efdefe SOURCE_DATE_EPOCH -f7d4913ff27f017e22a5aa66a233f0d403549539a6fab594cbbad258f965af1a slirp4netns-aarch64 -091cb02fae4af0c43596fecdde2eac0cb76c7c5c30963c4b87fc282cb9489571 slirp4netns-armv7l -228144e9ba9f19905ffbe95767fed10361e620f01f0867c8d1162cf60807b37e slirp4netns-ppc64le -5898887f3ababd4e4886932535d5167a87d7497cd2851e259cae566b1b6d636a slirp4netns-riscv64 -9cf1d1880b8016bd47023a32582655e2f5f96a0ff266faeb932fbf4ef6159dee slirp4netns-s390x -2b59dd438ec1814dcd00c3106c0288ca174c3fe9a178f3400baa06818edaae8d slirp4netns-x86_64 diff --git a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.3 b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.3 new file mode 100644 index 00000000000..a2ac3e552f6 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.3 @@ -0,0 +1,7 @@ +5ccf6a6cabc312d33332709486ea90110f4608b8371954d6dc2a1ed865457f92 SOURCE_DATE_EPOCH +289b0838f849da0d6d5de596e6c5010fbb134a2912d3cc32a0e2e2b759543278 slirp4netns-aarch64 +43db5430758edb8d095a0923dcbf2757a2fded9f22aa851d18aad9b82c245fb6 slirp4netns-armv7l +fe565401ffefa1c4f1e6c141788405825ae5513e0bb1122bdfe6acdd00be9e71 slirp4netns-ppc64le +cb9f92d496541b9ee2163bd64d522bf82a4136ccbbb01e3883be078a5e65af6f slirp4netns-riscv64 +09e68bd9707fdab67884256bea5ca09ae9057a4ebf3f8382e369602c7ae21734 slirp4netns-s390x +2051ae25baba59c96f42bf2b7b7efa2eabb022e497b6c4b692b1428d2b2d1f5b slirp4netns-x86_64 From c6236eeaa9eabffe99cf994903b469acf2eca7d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 22:21:31 +0000 Subject: [PATCH 0330/1066] build(deps): bump tonistiigi/xx from 1.3.0 to 1.4.0 Bumps tonistiigi/xx from 1.3.0 to 1.4.0. --- updated-dependencies: - dependency-name: tonistiigi/xx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9bdb566c253..b51fa21b7cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,7 +51,7 @@ ARG GOTESTSUM_VERSION=v1.11.0 ARG NYDUS_VERSION=v2.2.4 ARG SOCI_SNAPSHOTTER_VERSION=0.4.0 -FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.3.0 AS xx +FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.4.0 AS xx FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bullseye AS build-base-debian From 679adcf89e6db00a18157002c12aed8221cd3768 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 22:45:39 +0000 Subject: [PATCH 0331/1066] build(deps): bump golang.org/x/crypto from 0.18.0 to 0.19.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.18.0 to 0.19.0. - [Commits](https://github.com/golang/crypto/compare/v0.18.0...v0.19.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index bc3f8ed5acb..6242e23cb33 100644 --- a/go.mod +++ b/go.mod @@ -55,11 +55,11 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.18.0 + golang.org/x/crypto v0.19.0 golang.org/x/net v0.20.0 golang.org/x/sync v0.6.0 - golang.org/x/sys v0.16.0 - golang.org/x/term v0.16.0 + golang.org/x/sys v0.17.0 + golang.org/x/term v0.17.0 golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 diff --git a/go.sum b/go.sum index f90c094e4de..67b7274d548 100644 --- a/go.sum +++ b/go.sum @@ -344,8 +344,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= @@ -405,11 +405,11 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From cad6b2af3ae6a22ad38258a4db0c43c65ab569b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Feb 2024 22:16:46 +0000 Subject: [PATCH 0332/1066] build(deps): bump golangci/golangci-lint-action from 3.7.0 to 3.7.1 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.7.0 to 3.7.1. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3.7.0...v3.7.1) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 27378e313bf..832a5b7da21 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,7 +46,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v3.7.0 + uses: golangci/golangci-lint-action@v3.7.1 with: version: v1.55.2 args: --verbose From 6fd3fb73c6d3e3913a07481b5296da04f5cbdb20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 03:13:11 +0000 Subject: [PATCH 0333/1066] build(deps): bump golang.org/x/net from 0.20.0 to 0.21.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.20.0 to 0.21.0. - [Commits](https://github.com/golang/net/compare/v0.20.0...v0.21.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6242e23cb33..43ef74a17ba 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 golang.org/x/crypto v0.19.0 - golang.org/x/net v0.20.0 + golang.org/x/net v0.21.0 golang.org/x/sync v0.6.0 golang.org/x/sys v0.17.0 golang.org/x/term v0.17.0 diff --git a/go.sum b/go.sum index 67b7274d548..7b2088c02b3 100644 --- a/go.sum +++ b/go.sum @@ -368,8 +368,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 09168445af4a99c3f01f0566136b9fc8d90986c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 22:47:14 +0000 Subject: [PATCH 0334/1066] build(deps): bump golangci/golangci-lint-action from 3.7.1 to 4.0.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3.7.1 to 4.0.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3.7.1...v4.0.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 832a5b7da21..058e87188fa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,7 +46,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v3.7.1 + uses: golangci/golangci-lint-action@v4.0.0 with: version: v1.55.2 args: --verbose From fdf7968bb323ca4297d89b80067b8f4ba7676b29 Mon Sep 17 00:00:00 2001 From: Monirul Islam Date: Fri, 9 Feb 2024 14:44:46 -0800 Subject: [PATCH 0335/1066] Fix soci image push with multi-platforms flags Signed-off-by: Monirul Islam --- pkg/snapshotterutil/sociutil.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pkg/snapshotterutil/sociutil.go b/pkg/snapshotterutil/sociutil.go index 9770a571316..54ceb9e7985 100644 --- a/pkg/snapshotterutil/sociutil.go +++ b/pkg/snapshotterutil/sociutil.go @@ -53,12 +53,16 @@ func CreateSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform boo sociCmd.Args = append(sociCmd.Args, "create") if allPlatform { - sociCmd.Args = append(sociCmd.Args, "--all-platforms", strconv.FormatBool(allPlatform)) + sociCmd.Args = append(sociCmd.Args, "--all-platforms") } if len(platforms) > 0 { - sociCmd.Args = append(sociCmd.Args, "--platform") - sociCmd.Args = append(sociCmd.Args, strings.Join(platforms, ",")) + // multiple values need to be passed as separate, repeating flags in soci as it uses urfave + // https://github.com/urfave/cli/blob/main/docs/v2/examples/flags.md#multiple-values-per-single-flag + for _, p := range platforms { + sociCmd.Args = append(sociCmd.Args, "--platform", p) + } } + if sOpts.SpanSize != -1 { sociCmd.Args = append(sociCmd.Args, "--span-size", strconv.FormatInt(sOpts.SpanSize, 10)) } @@ -107,11 +111,14 @@ func PushSoci(rawRef string, gOpts types.GlobalCommandOptions, allPlatform bool, sociCmd.Args = append(sociCmd.Args, "push") if allPlatform { - sociCmd.Args = append(sociCmd.Args, "--all-platforms", strconv.FormatBool(allPlatform)) + sociCmd.Args = append(sociCmd.Args, "--all-platforms") } if len(platforms) > 0 { - sociCmd.Args = append(sociCmd.Args, "--platform") - sociCmd.Args = append(sociCmd.Args, strings.Join(platforms, ",")) + // multiple values need to be passed as separate, repeating flags in soci as it uses urfave + // https://github.com/urfave/cli/blob/main/docs/v2/examples/flags.md#multiple-values-per-single-flag + for _, p := range platforms { + sociCmd.Args = append(sociCmd.Args, "--platform", p) + } } if gOpts.InsecureRegistry { sociCmd.Args = append(sociCmd.Args, "--skip-verify") From 1eada1af6f8487f6a5507aea4dfe39dc612620d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 23:00:57 +0000 Subject: [PATCH 0336/1066] build(deps): bump github.com/opencontainers/runtime-spec Bumps [github.com/opencontainers/runtime-spec](https://github.com/opencontainers/runtime-spec) from 1.1.0 to 1.2.0. - [Release notes](https://github.com/opencontainers/runtime-spec/releases) - [Changelog](https://github.com/opencontainers/runtime-spec/blob/main/ChangeLog) - [Commits](https://github.com/opencontainers/runtime-spec/compare/v1.1.0...v1.2.0) --- updated-dependencies: - dependency-name: github.com/opencontainers/runtime-spec dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 43ef74a17ba..26b7d165370 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( github.com/muesli/cancelreader v0.2.2 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0-rc6 - github.com/opencontainers/runtime-spec v1.1.0 + github.com/opencontainers/runtime-spec v1.2.0 github.com/pelletier/go-toml/v2 v2.1.1 github.com/rootless-containers/bypass4netns v0.4.0 github.com/rootless-containers/rootlesskit/v2 v2.0.1 diff --git a/go.sum b/go.sum index 7b2088c02b3..e77a97f36f2 100644 --- a/go.sum +++ b/go.sum @@ -250,8 +250,8 @@ github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3I github.com/opencontainers/image-spec v1.1.0-rc6 h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU= github.com/opencontainers/image-spec v1.1.0-rc6/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= +github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= +github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= From 4c29703ba1746e3e1d282891c3ca1ce8489f8149 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 14 Feb 2024 18:00:00 +0900 Subject: [PATCH 0337/1066] rootless: fix `Not Authorized(uid): org.fedoraproject.FirewallD1.config` Fix issue 2818 > nerdctl run - failed to add the address > (`failed to add the address 10.4.0.17/32 to trusted zone: Not Authorized(uid): > org.fedoraproject.FirewallD1.config`) To apply this fix on a non-fresh installation, run: ``` nerdctl network rm bridge nerdctl network create bridge ``` Signed-off-by: Akihiro Suda --- pkg/netutil/cni_plugin_unix.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/netutil/cni_plugin_unix.go b/pkg/netutil/cni_plugin_unix.go index 588f339c669..2a0233860f3 100644 --- a/pkg/netutil/cni_plugin_unix.go +++ b/pkg/netutil/cni_plugin_unix.go @@ -18,6 +18,8 @@ package netutil +import "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + // bridgeConfig describes the bridge plugin type bridgeConfig struct { PluginType string `json:"type"` @@ -97,10 +99,15 @@ type firewallConfig struct { } func newFirewallPlugin() *firewallConfig { - return &firewallConfig{ + c := &firewallConfig{ PluginType: "firewall", IngressPolicy: "same-bridge", } + if rootlessutil.IsRootless() { + // https://github.com/containerd/nerdctl/issues/2818 + c.Backend = "iptables" + } + return c } func (*firewallConfig) GetPluginType() string { From 1b05ff3ec715aeba1db806c48ea45301bcbba6f6 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 14 Feb 2024 18:17:11 +0900 Subject: [PATCH 0338/1066] Remove the support for the old CNI isolation plugin The old [CNI isolation plugin](https://github.com/AkihiroSuda/cni-isolation) has been deprecated since nerdctl v0.18 (Mar 25, 2022), in favor of the CNI firewall plugin v1.1. Signed-off-by: Akihiro Suda --- README.md | 2 +- docs/cni.md | 5 +---- pkg/netutil/cni_plugin.go | 14 ------------ pkg/netutil/netutil_unix.go | 45 +++++++++---------------------------- 4 files changed, 13 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 7e3ee8b8c77..4b5a02aba72 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ Binaries are available here: In addition to containerd, the following components should be installed: - [CNI plugins](https://github.com/containernetworking/plugins): for using `nerdctl run`. - - v1.1.0 or later is highly recommended. Older versions require extra [CNI isolation plugin](https://github.com/AkihiroSuda/cni-isolation) for isolating bridge networks (`nerdctl network create`). + - v1.1.0 or later is highly recommended. - [BuildKit](https://github.com/moby/buildkit) (OPTIONAL): for using `nerdctl build`. BuildKit daemon (`buildkitd`) needs to be running. See also [the document about setting up BuildKit](./docs/build.md). - v0.11.0 or later is highly recommended. Some features, such as pruning caches with `nerdctl system prune`, do not work with older versions. - [RootlessKit](https://github.com/rootless-containers/rootlesskit) and [slirp4netns](https://github.com/rootless-containers/slirp4netns) (OPTIONAL): for [Rootless mode](./docs/rootless.md) diff --git a/docs/cni.md b/docs/cni.md index f404e6405fc..50dfde8043e 100644 --- a/docs/cni.md +++ b/docs/cni.md @@ -61,10 +61,7 @@ Configuration of the default network `bridge` of Linux: nerdctl >= 0.18 sets the `ingressPolicy` to `same-bridge` when `firewall` plugin >= 1.1.0 is installed. This `ingressPolicy` replaces the CNI `isolation` plugin used in nerdctl <= 0.17. -When the `isolation` plugin is found, nerdctl uses the `isolation` plugin instead of `ingressPolicy`. -The `isolation` plugin has been deprecated, and a future version of `nerdctl` will solely support `ingressPolicy`. - -When neither of `firewall` plugin >= 1.1.0 or `isolation` plugin is found, nerdctl does not enable the bridge isolation. +When `firewall` plugin >= 1.1.0 is not found, nerdctl does not enable the bridge isolation. This means a container in `--net=foo` can connect to a container in `--net=bar`. ## macvlan/IPvlan networks diff --git a/pkg/netutil/cni_plugin.go b/pkg/netutil/cni_plugin.go index b333d5c15e4..f4d65359f2e 100644 --- a/pkg/netutil/cni_plugin.go +++ b/pkg/netutil/cni_plugin.go @@ -33,17 +33,3 @@ type IPAMRoute struct { GW string `json:"gw,omitempty"` Gateway string `json:"gateway,omitempty"` } - -type isolationConfig struct { - PluginType string `json:"type"` -} - -func newIsolationPlugin() *isolationConfig { - return &isolationConfig{ - PluginType: "isolation", - } -} - -func (*isolationConfig) GetPluginType() string { - return "isolation" -} diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index 7b9dff23b5a..12c39df982a 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -128,7 +128,17 @@ func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string] bridge.Capabilities["ips"] = true } plugins = []CNIPlugin{bridge, newPortMapPlugin(), newFirewallPlugin(), newTuningPlugin()} - plugins = fixUpIsolation(e, name, plugins) + if name != DefaultNetworkName { + firewallPath := filepath.Join(e.Path, "firewall") + ok, err := firewallPluginGEQ110(firewallPath) + if err != nil { + log.L.WithError(err).Warnf("Failed to detect whether %q is newer than v1.1.0", firewallPath) + } + if !ok { + log.L.Warnf("To isolate bridge networks, CNI plugin \"firewall\" (>= 1.1.0) needs to be installed in CNI_PATH (%q), see https://github.com/containernetworking/plugins", + e.Path) + } + } case "macvlan", "ipvlan": mtu := 0 mode := "" @@ -235,39 +245,6 @@ func (e *CNIEnv) parseIPAMRanges(subnets []string, gateway, ipRange string, ipv6 return ranges, findIPv4, nil } -func fixUpIsolation(e *CNIEnv, name string, plugins []CNIPlugin) []CNIPlugin { - isolationPath := filepath.Join(e.Path, "isolation") - if _, err := exec.LookPath(isolationPath); err == nil { - // the warning is suppressed for DefaultNetworkName (because multi-bridge networking is not involved) - if name != DefaultNetworkName { - log.L.Warnf(`network %q: Using the deprecated CNI "isolation" plugin instead of CNI "firewall" plugin (>= 1.1.0) ingressPolicy. -To dismiss this warning, uninstall %q and install CNI "firewall" plugin (>= 1.1.0) from https://github.com/containernetworking/plugins`, - name, isolationPath) - } - plugins = append(plugins, newIsolationPlugin()) - for _, f := range plugins { - if x, ok := f.(*firewallConfig); ok { - if name != DefaultNetworkName { - log.L.Warnf("network %q: Unsetting firewall ingressPolicy %q (because using the deprecated \"isolation\" plugin)", name, x.IngressPolicy) - } - x.IngressPolicy = "" - } - } - } else if name != DefaultNetworkName { - firewallPath := filepath.Join(e.Path, "firewall") - ok, err := firewallPluginGEQ110(firewallPath) - if err != nil { - log.L.WithError(err).Warnf("Failed to detect whether %q is newer than v1.1.0", firewallPath) - } - if !ok { - log.L.Warnf("To isolate bridge networks, CNI plugin \"firewall\" (>= 1.1.0) needs to be installed in CNI_PATH (%q), see https://github.com/containernetworking/plugins", - e.Path) - } - } - - return plugins -} - func firewallPluginGEQ110(firewallPath string) (bool, error) { // TODO: guess true by default in 2023 guessed := false From 8d840dae1ec5604650861bb672e39ef99da85a89 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 15 Feb 2024 14:44:26 +0800 Subject: [PATCH 0339/1066] doc: should use master tag for binfmt Signed-off-by: Wei Zhang --- docs/multi-platform.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/multi-platform.md b/docs/multi-platform.md index 22113eeccf7..e2213c36482 100644 --- a/docs/multi-platform.md +++ b/docs/multi-platform.md @@ -11,7 +11,7 @@ e.g., ARM on Intel, and vice versa. ```console $ sudo systemctl start containerd -$ sudo nerdctl run --privileged --rm tonistiigi/binfmt --install all +$ sudo nerdctl run --privileged --rm tonistiigi/binfmt:master --install all $ ls -1 /proc/sys/fs/binfmt_misc/qemu* /proc/sys/fs/binfmt_misc/qemu-aarch64 From 72a9737d12ffa7b0f46ff2956204a0bbcae76903 Mon Sep 17 00:00:00 2001 From: Wei Zhang Date: Thu, 15 Feb 2024 15:24:28 +0800 Subject: [PATCH 0340/1066] platform: support loongarch64 Signed-off-by: Wei Zhang --- pkg/platformutil/binfmt.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/platformutil/binfmt.go b/pkg/platformutil/binfmt.go index bfe1023dc57..1539426790d 100644 --- a/pkg/platformutil/binfmt.go +++ b/pkg/platformutil/binfmt.go @@ -36,6 +36,8 @@ func qemuArchFromOCIArch(ociArch string) (string, error) { return ociArch, nil case "mips64le": return "mips64el", nil // NOT typo + case "loong64": + return "loongarch64", nil // NOT typo } return "", fmt.Errorf("unknown OCI architecture string: %q", ociArch) } From 07dc8a584be66914ef4d5886cb9b705020baccab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 22:12:31 +0000 Subject: [PATCH 0341/1066] build(deps): bump github.com/opencontainers/image-spec Bumps [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec) from 1.1.0-rc6 to 1.1.0. - [Release notes](https://github.com/opencontainers/image-spec/releases) - [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md) - [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0-rc6...v1.1.0) --- updated-dependencies: - dependency-name: github.com/opencontainers/image-spec dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 26b7d165370..aa13f960071 100644 --- a/go.mod +++ b/go.mod @@ -43,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-rc6 + github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/runtime-spec v1.2.0 github.com/pelletier/go-toml/v2 v2.1.1 github.com/rootless-containers/bypass4netns v0.4.0 diff --git a/go.sum b/go.sum index e77a97f36f2..5ae61ab8ddb 100644 --- a/go.sum +++ b/go.sum @@ -247,8 +247,8 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= 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-rc6 h1:XDqvyKsJEbRtATzkgItUqBA7QHk58yxX1Ov9HERHNqU= -github.com/opencontainers/image-spec v1.1.0-rc6/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= +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.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= From 6f1c767e574251559ec8703234f5535f08260863 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 22:12:45 +0000 Subject: [PATCH 0342/1066] build(deps): bump github.com/tidwall/gjson from 1.17.0 to 1.17.1 Bumps [github.com/tidwall/gjson](https://github.com/tidwall/gjson) from 1.17.0 to 1.17.1. - [Commits](https://github.com/tidwall/gjson/compare/v1.17.0...v1.17.1) --- updated-dependencies: - dependency-name: github.com/tidwall/gjson dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 26b7d165370..451e9db1b9e 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/rootless-containers/rootlesskit/v2 v2.0.1 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 - github.com/tidwall/gjson v1.17.0 + github.com/tidwall/gjson v1.17.1 github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 diff --git a/go.sum b/go.sum index e77a97f36f2..44508be56d3 100644 --- a/go.sum +++ b/go.sum @@ -299,8 +299,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= -github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= +github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= From 4acb599ee574922b5a8593912965690fcff4ec88 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Feb 2024 11:02:26 +0900 Subject: [PATCH 0343/1066] CI: test compilation with Go 1.22 The release artifacts are still built with Go 1.21, as Go 1.22 is incompatible with runc (golang/go issue 65625). Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 058e87188fa..9d61b45cb2d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -209,7 +209,7 @@ jobs: timeout-minutes: 40 strategy: matrix: - go-version: ["1.20.x", "1.21.x"] + go-version: ["1.21.x", "1.22.x"] steps: - uses: actions/checkout@v4.1.1 with: From 4420aa67ce9918169ca2970f9b7dd702e812fa34 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 16 Feb 2024 10:58:51 +0900 Subject: [PATCH 0344/1066] update BuildKit (0.13.0-rc1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta3 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-rc1 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta3 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-rc1 diff --git a/Dockerfile b/Dockerfile index d148f210fdb..f9d1bdd2bb4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.12 ARG CNI_PLUGINS_VERSION=v1.4.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.13.0-beta3 +ARG BUILDKIT_VERSION=v0.13.0-rc1 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta3 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta3 deleted file mode 100644 index 98ab016effd..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-beta3 +++ /dev/null @@ -1,2 +0,0 @@ -c0137ed55fd7f87ec4a04e940415ee449e3c70ae716194d5d1660b3e93e72e14 buildkit-v0.13.0-beta3.linux-amd64.tar.gz -9a877ecb952820fbd05885732d4cfb6df8d2de0a8041d8f957be72c6bff0c8c6 buildkit-v0.13.0-beta3.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-rc1 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-rc1 new file mode 100644 index 00000000000..38deac342ab --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-rc1 @@ -0,0 +1,2 @@ +e3ca21393aba992e755f5819eccddf0d4043e6038a4bba3462a84e157b59477e buildkit-v0.13.0-rc1.linux-amd64.tar.gz +da7a6cced9c21af8d1098c587d6ec6a21b7c034d0143e50c6481888189e7a3fa buildkit-v0.13.0-rc1.linux-arm64.tar.gz From 41b83493e1e41b8a76db25f2dbfb5046edf685ee Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Sun, 18 Feb 2024 20:21:01 +0100 Subject: [PATCH 0345/1066] Rootlesskit Network Design Signed-off-by: fahed dorgaa --- docs/images/rootlessKit-network-design.png | Bin 0 -> 684421 bytes docs/rootless.md | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 docs/images/rootlessKit-network-design.png diff --git a/docs/images/rootlessKit-network-design.png b/docs/images/rootlessKit-network-design.png new file mode 100644 index 0000000000000000000000000000000000000000..5a1696b70956d45828c06ce0b815be65cb4c5860 GIT binary patch literal 684421 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≥Ktd5S3oYq5} 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

e%-a(ti)MYgi0ro4G(VMZ6%(d`Ie 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∈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

ucJ}RFhp=TFQHR7p7rE$u-winlN@V4gdINNM?}f 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 z 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 C{1a0E literal 0 HcmV?d00001 diff --git a/docs/rootless.md b/docs/rootless.md index 6c9d048fe02..c8c738df06c 100644 --- a/docs/rootless.md +++ b/docs/rootless.md @@ -164,3 +164,22 @@ systemctl --user restart containerd ### Hint to Fedora users - If SELinux is enabled on your host and your kernel is older than 5.13, you need to use [`fuse-overlayfs` instead of `overlayfs`](#fuse-overlayfs). + +## Rootlesskit Network Design + +In `detach-netns` mode: + +- Network namespace is detached and stored in `$ROOTLESSKIT_STATE_DIR/netns`. +- The child command executes within the host's network namespace, allowing actions like `pull` and `push` to happen in the host network namespace. +- For creating and configuring the container's network namespace, the child command switches temporarily to the relevant namespace located in `$ROOTLESSKIT_STATE_DIR/netns`. This ensures necessary network setup while maintaining isolation in the host namespace. + +![rootlessKit-network-design.png](images/rootlessKit-network-design.png) + +- Rootlesskit Parent NetNS and Child NetNS are already configured by the startup script [containerd-rootless.sh](https://github.com/containerd/nerdctl/blob/main/extras/rootless/containerd-rootless.sh) +- Rootlesskit Parent NetNS is the host network namespace +- step1: `nerdctl` calls `containerd` in the host network namespace. +- step2: `containerd` calls `runc` in the host network namespace. +- step3: `runc` creates container with dedicated namespaces (e.g network ns) in the Parent netns. +- step4: `runc` nsenter Rootlesskit Child NetNS before triggering nerdctl ocihook. +- step5: `nerdctl` ocihook module leverages CNI. +- step6: CNI configures container network namespace: create network interfaces `eth0` -> `veth0` -> `nerdctl0`. From 261bd97c40c8c2760ef9609f60efa89922f93fdc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 22:20:32 +0000 Subject: [PATCH 0346/1066] build(deps): bump github.com/klauspost/compress from 1.17.6 to 1.17.7 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.6 to 1.17.7. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.6...v1.17.7) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ebb95c2c9bc..821748dbea6 100644 --- a/go.mod +++ b/go.mod @@ -96,7 +96,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.6 + github.com/klauspost/compress v1.17.7 github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect diff --git a/go.sum b/go.sum index de3ce08d4f6..88107b20b0c 100644 --- a/go.sum +++ b/go.sum @@ -178,8 +178,8 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= -github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= From d8412eed72f6cdcda2745aa11756841769f5e521 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Feb 2024 22:22:34 +0000 Subject: [PATCH 0347/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.7 to 0.13.8. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.7...v0.13.8) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ebb95c2c9bc..d2c00dd6589 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.9 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.7 + github.com/containerd/nydus-snapshotter v0.13.8 github.com/containerd/platforms v0.1.1 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 diff --git a/go.sum b/go.sum index de3ce08d4f6..7268cc5e1aa 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,8 @@ github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= 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.7 h1:x7DHvGnzJOu1ZPwPYkeOPk5MjZZYbdddygEjaSDoFTk= -github.com/containerd/nydus-snapshotter v0.13.7/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= +github.com/containerd/nydus-snapshotter v0.13.8 h1:ChSXEn4iudHtFkKrRPOpjRkqhajyx8vuFw24r9Wo8cw= +github.com/containerd/nydus-snapshotter v0.13.8/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= github.com/containerd/platforms v0.1.1 h1:gp0xXBoY+1CjH54gJDon0kBjIbK2C4XSX1BGwP5ptG0= github.com/containerd/platforms v0.1.1/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= github.com/containerd/stargz-snapshotter v0.15.1 h1:fpsP4kf/Z4n2EYnU0WT8ZCE3eiKDwikDhL6VwxIlgeA= From 18f29fb006ebb79590acdb07253bdc75527cdcf5 Mon Sep 17 00:00:00 2001 From: Alessio Greggi Date: Fri, 23 Feb 2024 16:59:37 +0100 Subject: [PATCH 0348/1066] fix: add onstartcontainer hook Signed-off-by: Alessio Greggi --- pkg/cmd/container/create.go | 6 ++++++ pkg/ocihook/ocihook.go | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 694981ec395..2045b820c44 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -484,6 +484,12 @@ func withNerdctlOCIHook(cmd string, args []string) (oci.SpecOpts, error) { Args: crArgs, Env: os.Environ(), }) + scArgs := append(args, "startContainer") + s.Hooks.CreateRuntime = append(s.Hooks.StartContainer, specs.Hook{ + Path: cmd, + Args: scArgs, + Env: os.Environ(), + }) argsCopy := append([]string(nil), args...) psArgs := append(argsCopy, "postStop") s.Hooks.Poststop = append(s.Hooks.Poststop, specs.Hook{ diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index ebbd95150bd..dcf4c978c6b 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -89,6 +89,8 @@ func Run(stdin io.Reader, stderr io.Writer, event, dataStore, cniPath, cniNetcon switch event { case "createRuntime": return onCreateRuntime(opts) + case "startContainer": + return onStartContainer(opts) case "postStop": return onPostStop(opts) default: @@ -468,6 +470,31 @@ func onCreateRuntime(opts *handlerOpts) error { return nil } +func onStartContainer(opts *handlerOpts) error { + // restore portmapping in case it was removed by kill/stop command + if opts.cni != nil { + portMapOpts, err := getPortMapOpts(opts) + if err != nil { + return err + } + nsPath, err := getNetNSPath(opts.state) + if err != nil { + return err + } + ctx := context.Background() + fmt.Println(portMapOpts) + + var namespaceOpts []gocni.NamespaceOpts + namespaceOpts = append(namespaceOpts, portMapOpts...) + cniRes, err := opts.cni.Setup(ctx, opts.fullID, nsPath, namespaceOpts...) + if err != nil { + return fmt.Errorf("failed to call cni.Setup: %w", err) + } + fmt.Println(cniRes) + } + return nil +} + func onPostStop(opts *handlerOpts) error { ctx := context.Background() ns := opts.state.Annotations[labels.Namespace] From d94c8f59ba1b977ccb905ac442ed260ff7d1358a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 22:17:38 +0000 Subject: [PATCH 0349/1066] build(deps): bump golang.org/x/crypto from 0.19.0 to 0.20.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.19.0 to 0.20.0. - [Commits](https://github.com/golang/crypto/compare/v0.19.0...v0.20.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3467e9eb054..2917208e452 100644 --- a/go.mod +++ b/go.mod @@ -55,7 +55,7 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.19.0 + golang.org/x/crypto v0.20.0 golang.org/x/net v0.21.0 golang.org/x/sync v0.6.0 golang.org/x/sys v0.17.0 diff --git a/go.sum b/go.sum index 2b7816d80b1..594da1e0802 100644 --- a/go.sum +++ b/go.sum @@ -344,8 +344,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= +golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= From 772d479107beab9b42407aa4a8b19ea5fce115e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Feb 2024 22:57:16 +0000 Subject: [PATCH 0350/1066] build(deps): bump github.com/containerd/accelerated-container-image Bumps [github.com/containerd/accelerated-container-image](https://github.com/containerd/accelerated-container-image) from 1.0.2 to 1.0.3. - [Release notes](https://github.com/containerd/accelerated-container-image/releases) - [Commits](https://github.com/containerd/accelerated-container-image/compare/v1.0.2...v1.0.3) --- updated-dependencies: - dependency-name: github.com/containerd/accelerated-container-image dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3467e9eb054..afd54d77d80 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Microsoft/hcsshim v0.11.4 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.0.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd v1.7.13 diff --git a/go.sum b/go.sum index 2b7816d80b1..e8016e9f5e9 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,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.0.3 h1:p6/1PI7EhwqjGdIyxq7TSfV1OmkZHd8m+gdDHqfARaU= +github.com/containerd/accelerated-container-image v1.0.3/go.mod h1:6+elKy0e2efrXQL9U8aaSFb3Ih9DVLsDizTKPKBCoSA= 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= From 3d28dbf603a5b95a322ce62e0fbda4a4df967308 Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Mon, 4 Mar 2024 14:51:36 +0800 Subject: [PATCH 0351/1066] fix: typos Signed-off-by: guoguangwu --- docs/ipfs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ipfs.md b/docs/ipfs.md index 29a98524a1b..488a1488f90 100644 --- a/docs/ipfs.md +++ b/docs/ipfs.md @@ -121,7 +121,7 @@ localhost:5050/ipfs/ Here, `CID` is the IPFS CID of the image. -:information_source: In the futural version of nerdctl and BuildKit, `ipfs://` prefix should be supported in Dockerfile. +:information_source: In the future version of nerdctl and BuildKit, `ipfs://` prefix should be supported in Dockerfile. Using this image reference, you can build an image on IPFS. @@ -179,7 +179,7 @@ By default, nerdctl exposes the registry at `localhost:5050` (configurable via f Optionally you can create systemd unit file of `nerdctl ipfs registry serve`. An example systemd unit file for `nerdctl ipfs registry serve` can be the following. -`nerdctl ipfs registry serve` is aware of environemnt variables for configuring the behaviour (e.g. listening port) so you can use `EnvironmentFile` for configuring it. +`nerdctl ipfs registry serve` is aware of environment variables for configuring the behaviour (e.g. listening port) so you can use `EnvironmentFile` for configuring it. ``` [Unit] From f15952629f8863d7e1752d20aad7153f00acb6c2 Mon Sep 17 00:00:00 2001 From: Derek McGowan Date: Mon, 4 Mar 2024 14:05:49 -0800 Subject: [PATCH 0352/1066] Use json marshal/unmarshal to copy Just call marshal/unmarshal rather depend on a CRI util package. Signed-off-by: Derek McGowan --- cmd/nerdctl/container_update.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index d4f79775db9..534ceb4961b 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -18,6 +18,7 @@ package main import ( "context" + "encoding/json" "errors" "fmt" "runtime" @@ -25,7 +26,6 @@ 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/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -380,8 +380,16 @@ func updateContainerSpec(ctx context.Context, container containerd.Container, sp func copySpec(spec *runtimespec.Spec) (*runtimespec.Spec, error) { var copySpec runtimespec.Spec - if err := util.DeepCopy(©Spec, spec); err != nil { - return nil, fmt.Errorf("failed to deep copy:%w", err) + if spec == nil { + return nil, errors.New("spec cannot be nil") + } + bytes, err := json.Marshal(spec) + if err != nil { + return nil, fmt.Errorf("unable to marshal spec: %w", err) + } + err = json.Unmarshal(bytes, ©Spec) + if err != nil { + return nil, fmt.Errorf("unable to unmarshal into spec copy: %w", err) } return ©Spec, nil } From be0061005f384948bb1b8e62acc2d2cf27fe4d09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 22:16:12 +0000 Subject: [PATCH 0353/1066] build(deps): bump golang.org/x/crypto from 0.20.0 to 0.21.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.20.0 to 0.21.0. - [Commits](https://github.com/golang/crypto/compare/v0.20.0...v0.21.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index af91ccc3c20..bd632922450 100644 --- a/go.mod +++ b/go.mod @@ -55,11 +55,11 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.20.0 + golang.org/x/crypto v0.21.0 golang.org/x/net v0.21.0 golang.org/x/sync v0.6.0 - golang.org/x/sys v0.17.0 - golang.org/x/term v0.17.0 + golang.org/x/sys v0.18.0 + golang.org/x/term v0.18.0 golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 diff --git a/go.sum b/go.sum index 0a7ab9607f3..bf9028a3d68 100644 --- a/go.sum +++ b/go.sum @@ -344,8 +344,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= -golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= @@ -405,11 +405,11 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 45b86c219cdd7495b6f69028cca03a3665daf3c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 23:16:44 +0000 Subject: [PATCH 0354/1066] build(deps): bump golang.org/x/net from 0.21.0 to 0.22.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.21.0 to 0.22.0. - [Commits](https://github.com/golang/net/compare/v0.21.0...v0.22.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bd632922450..01e198b6416 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 golang.org/x/crypto v0.21.0 - golang.org/x/net v0.21.0 + golang.org/x/net v0.22.0 golang.org/x/sync v0.6.0 golang.org/x/sys v0.18.0 golang.org/x/term v0.18.0 diff --git a/go.sum b/go.sum index bf9028a3d68..4e224b54d1d 100644 --- a/go.sum +++ b/go.sum @@ -368,8 +368,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From f853ab8542dfd85a8a53c435ebf39d1d1b10cd85 Mon Sep 17 00:00:00 2001 From: Shubhranshu Mahapatra Date: Mon, 19 Feb 2024 16:26:28 -0800 Subject: [PATCH 0355/1066] Enhance default platform comparision for image shareablity #2810 Partially Addresses: https://github.com/containerd/nerdctl/issues/2810 There are cases where --platform flag may be passed during nerdctl build. In such a situation if platform matches the runtime platform the image is shareable. Signed-off-by: Shubhranshu Mahapatra --- cmd/nerdctl/builder_build_test.go | 32 +++++ pkg/cmd/builder/build.go | 41 ++++++- pkg/cmd/builder/build_test.go | 189 ++++++++++++++++++++++++++++++ pkg/testutil/testutil.go | 17 +++ 4 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 pkg/cmd/builder/build_test.go diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index e43a3a2ace8..72168df5752 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -24,6 +24,7 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/platforms" "gotest.tools/v3/assert" ) @@ -57,6 +58,37 @@ CMD ["echo", "nerdctl-build-test-string"] } } +func TestBuildIsShareableForCompatiblePlatform(t *testing.T) { + testutil.RequiresBuild(t) + base := testutil.NewBase(t) + defer base.Cmd("builder", "prune").Run() + imageName := testutil.Identifier(t) + defer base.Cmd("rmi", imageName).Run() + + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-build-test-string"] + `, testutil.CommonImage) + + buildCtx, err := createBuildContext(dockerfile) + assert.NilError(t, err) + defer os.RemoveAll(buildCtx) + + base.Cmd("build", buildCtx, "-t", imageName).AssertErrNotContains("tarball") + + d := platforms.DefaultSpec() + platformConfig := fmt.Sprintf("%s/%s", d.OS, d.Architecture) + base.Cmd("build", buildCtx, "-t", imageName, "--platform", platformConfig).AssertOK() + base.Cmd("build", buildCtx, "-t", imageName, "--platform", platformConfig, "--progress", "plain").AssertErrNotContains("tarball") + + n := platforms.Platform{OS: "linux", Architecture: "arm", Variant: ""} + if n.OS != d.OS && n.Architecture != d.Architecture { + notCompatiblePlatformConfig := fmt.Sprintf("%s/%s", n.OS, n.Architecture) + base.Cmd("build", buildCtx, "-t", imageName, "--platform", notCompatiblePlatformConfig).AssertOK() + base.Cmd("build", buildCtx, "-t", imageName, "--platform", notCompatiblePlatformConfig, "--progress", "plain").AssertErrContains("tarball") + } + +} + // TestBuildBaseImage tests if an image can be built on the previously built image. // This isn't currently supported by nerdctl with BuildKit OCI worker. func TestBuildBaseImage(t *testing.T) { diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 99eb9b2e0ba..5bbdd06cb44 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -42,6 +42,21 @@ import ( "github.com/containerd/platforms" ) +type PlatformParser interface { + Parse(platform string) (platforms.Platform, error) + DefaultSpec() platforms.Platform +} + +type platformParser struct{} + +func (p platformParser) Parse(platform string) (platforms.Platform, error) { + return platforms.Parse(platform) +} + +func (p platformParser) DefaultSpec() platforms.Platform { + return platforms.DefaultSpec() +} + func Build(ctx context.Context, client *containerd.Client, options types.BuilderBuildOptions) error { buildctlBinary, buildctlArgs, needsLoading, metaFile, tags, cleanup, err := generateBuildctlArgs(ctx, client, options) if err != nil { @@ -419,6 +434,29 @@ func getDigestFromMetaFile(path string) (string, error) { return digest, nil } +func isMatchingRuntimePlatform(platform string, parser PlatformParser) bool { + p, err := parser.Parse(platform) + if err != nil { + return false + } + d := parser.DefaultSpec() + + if p.OS == d.OS && p.Architecture == d.Architecture && (p.Variant == "" || p.Variant == d.Variant) { + return true + } + + return false +} + +func isBuildPlatformDefault(platform []string, parser PlatformParser) bool { + if len(platform) == 0 { + return true + } else if len(platform) == 1 { + return isMatchingRuntimePlatform(platform[0], parser) + } + return false +} + func isImageSharable(buildkitHost, namespace, uuid, snapshotter string, platform []string) (bool, error) { labels, err := buildkitutil.GetWorkerLabels(buildkitHost) if err != nil { @@ -445,5 +483,6 @@ func isImageSharable(buildkitHost, namespace, uuid, snapshotter string, platform // Dockerfile doesn't contain instructions require base images like RUN) even if `--output type=image,unpack=true` // is passed to BuildKit. Thus, we need to use `type=docker` or `type=oci` when nerdctl builds non-default platform // image using `platform` option. - return executor == "containerd" && containerdUUID == uuid && containerdNamespace == namespace && workerSnapshotter == snapshotter && len(platform) == 0, nil + parser := new(platformParser) + return executor == "containerd" && containerdUUID == uuid && containerdNamespace == namespace && workerSnapshotter == snapshotter && isBuildPlatformDefault(platform, parser), nil } diff --git a/pkg/cmd/builder/build_test.go b/pkg/cmd/builder/build_test.go new file mode 100644 index 00000000000..c1fa0caba36 --- /dev/null +++ b/pkg/cmd/builder/build_test.go @@ -0,0 +1,189 @@ +/* + 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 builder + +import ( + "reflect" + "testing" + + "github.com/containerd/containerd/platforms" + "go.uber.org/mock/gomock" + "gotest.tools/v3/assert" +) + +type MockParse struct { + ctrl *gomock.Controller + recorder *MockParseRecorder +} + +type MockParseRecorder struct { + mock *MockParse +} + +func newMockParser(ctrl *gomock.Controller) *MockParse { + mock := &MockParse{ctrl: ctrl} + mock.recorder = &MockParseRecorder{mock} + return mock +} + +func (m *MockParse) EXPECT() *MockParseRecorder { + return m.recorder +} + +func (m *MockParse) Parse(platform string) (platforms.Platform, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Parse") + ret0, _ := ret[0].(platforms.Platform) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +func (m *MockParseRecorder) Parse(platform string) *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Parse", reflect.TypeOf((*MockParse)(nil).Parse)) +} + +func (m *MockParse) DefaultSpec() platforms.Platform { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DefaultSpec") + ret0, _ := ret[0].(platforms.Platform) + return ret0 +} + +func (m *MockParseRecorder) DefaultSpec() *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType(m.mock, "DefaultSpec", reflect.TypeOf((*MockParse)(nil).DefaultSpec)) +} + +func TestIsMatchingRuntimePlatform(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + mock func(*MockParse) + want bool + }{ + { + name: "Image is shareable when Runtime and build platform match for os, arch and variant", + mock: func(mockParser *MockParse) { + mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}, nil) + mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + }, + want: true, + }, + { + name: "Image is shareable when Runtime and build platform match for os, arch. Variant is not defined", + mock: func(mockParser *MockParse) { + mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: ""}, nil) + mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + }, + want: true, + }, + { + name: "Image is not shareable when Runtime and build platform donot math OS", + mock: func(mockParser *MockParse) { + mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "OS", Architecture: "mockArch", Variant: ""}, nil) + mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + }, + want: false, + }, + { + name: "Image is not shareable when Runtime and build platform donot math Arch", + mock: func(mockParser *MockParse) { + mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "mockOS", Architecture: "Arch", Variant: ""}, nil) + mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + }, + want: false, + }, + { + name: "Image is not shareable when Runtime and build platform donot math Variant", + mock: func(mockParser *MockParse) { + mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "Variant"}, nil) + mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + }, + want: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + mockParser := newMockParser(ctrl) + tc.mock(mockParser) + r := isMatchingRuntimePlatform("test", mockParser) + assert.Equal(t, r, tc.want, tc.name) + }) + } +} + +func TestIsBuildPlatformDefault(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + mock func(*MockParse) + platform []string + want bool + }{ + { + name: "Image is shreable when len of platform is 0", + platform: make([]string, 0), + want: true, + }, + { + name: "Image is shareable when Runtime and build platform match for os, arch and variant", + platform: []string{"test"}, + mock: func(mockParser *MockParse) { + mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}, nil) + mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + }, + want: true, + }, + { + name: "Image is not shareable when Runtime build platform dont match", + platform: []string{"test"}, + mock: func(mockParser *MockParse) { + mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "OS", Architecture: "mockArch", Variant: "mockVariant"}, nil) + mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + }, + want: false, + }, + { + name: "Image is not shareable when more than 2 platforms are passed", + platform: []string{"test1", "test2"}, + want: false, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + mockParser := newMockParser(ctrl) + if len(tc.platform) == 1 { + tc.mock(mockParser) + } + r := isBuildPlatformDefault(tc.platform, mockParser) + assert.Equal(t, r, tc.want, tc.name) + }) + } +} diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 35d3bdef447..e64271bca57 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -387,6 +387,14 @@ func (c *Cmd) AssertOutContains(s string) { c.Assert(expected) } +func (c *Cmd) AssertErrContains(s string) { + c.Base.T.Helper() + expected := icmd.Expected{ + Err: s, + } + c.Assert(expected) +} + func (c *Cmd) AssertCombinedOutContains(s string) { c.Base.T.Helper() res := c.Run() @@ -430,6 +438,15 @@ func (c *Cmd) AssertOutNotContains(s string) { }) } +func (c *Cmd) AssertErrNotContains(s string) { + c.AssertOutWithFunc(func(stderr string) error { + if strings.Contains(stderr, s) { + return fmt.Errorf("expected stdout to not contain %q", s) + } + return nil + }) +} + func (c *Cmd) AssertOutExactly(s string) { c.Base.T.Helper() fn := func(stdout string) error { From 26c02362b0014463080c9f2fd07b3e187f66d776 Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Tue, 5 Mar 2024 15:26:44 +0800 Subject: [PATCH 0356/1066] chore: remove useless error check Signed-off-by: guoguangwu --- cmd/nerdctl/main_unix.go | 4 +--- cmd/nerdctl/network_create.go | 3 --- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/cmd/nerdctl/main_unix.go b/cmd/nerdctl/main_unix.go index 93ac2f9134e..eea216ee903 100644 --- a/cmd/nerdctl/main_unix.go +++ b/cmd/nerdctl/main_unix.go @@ -35,9 +35,7 @@ func shellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete s _ = rootlessutil.ParentMain(globalOptions.HostGatewayIP) return nil, cobra.ShellCompDirectiveNoFileComp } - if err != nil { - return nil, cobra.ShellCompDirectiveNoFileComp - } + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) if err != nil { return nil, cobra.ShellCompDirectiveError diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index d00cf8fe5c2..252984a45b4 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -61,9 +61,6 @@ func networkCreateAction(cmd *cobra.Command, args []string) error { if err := identifiers.Validate(name); err != nil { return fmt.Errorf("malformed name %s: %w", name, err) } - if err != nil { - return err - } driver, err := cmd.Flags().GetString("driver") if err != nil { return err From 74e273746a3d23aa3f28047b5c3853f6b3aa7dc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 22:02:44 +0000 Subject: [PATCH 0357/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.11.4 to 0.12.0 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.11.4 to 0.12.0. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.11.4...v0.12.0) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: Akihiro Suda --- go.mod | 17 ++++++++--------- go.sum | 36 ++++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 01e198b6416..b4ca5d66a6a 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/containerd/nerdctl/v2 -go 1.20 +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/hcsshim v0.12.0 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.3 @@ -65,15 +65,13 @@ 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 github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 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 // indirect github.com/containerd/go-runc v1.0.0 // indirect github.com/containerd/ttrpc v1.2.2 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect @@ -107,6 +105,7 @@ require ( github.com/moby/sys/mountinfo v0.7.1 // 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.1.0 // indirect 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 @@ -137,9 +136,9 @@ require ( 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/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/grpc v1.62.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/go.sum b/go.sum index 4e224b54d1d..67045d2ae6f 100644 --- a/go.sum +++ b/go.sum @@ -7,12 +7,13 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOEl github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 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/hcsshim v0.12.0 h1:rbICA+XZFwrBef2Odk++0LjFvClNCJGRK+fsrP254Ts= +github.com/Microsoft/hcsshim v0.12.0/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= 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= @@ -29,8 +30,6 @@ github.com/compose-spec/compose-go v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTb github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM= github.com/containerd/accelerated-container-image v1.0.3 h1:p6/1PI7EhwqjGdIyxq7TSfV1OmkZHd8m+gdDHqfARaU= github.com/containerd/accelerated-container-image v1.0.3/go.mod h1:6+elKy0e2efrXQL9U8aaSFb3Ih9DVLsDizTKPKBCoSA= -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= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= @@ -40,6 +39,8 @@ github.com/containerd/containerd v1.7.13 h1:wPYKIeGMN8vaggSKuV1X0wZulpMz4CrgEsZd github.com/containerd/containerd v1.7.13/go.mod h1:zT3up6yTRfEUa6+GsITYIJNgSVL9NQ4x4h1RPzk0Wu4= 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= @@ -78,6 +79,7 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -112,6 +114,7 @@ github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= +github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= @@ -123,6 +126,7 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -160,6 +164,7 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 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.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -184,7 +189,9 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -241,10 +248,12 @@ github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs= +github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= 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 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -267,7 +276,9 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rootless-containers/bypass4netns v0.4.0 h1:7pcI4XWnOMQkgCsPKMXxMzQKhZUjaQ8J1n+eIYiHS0Y= github.com/rootless-containers/bypass4netns v0.4.0/go.mod h1:RPNWMSRT951DMtq9Xv72IZoJPWFeJL6Wg5pF79Lkano= github.com/rootless-containers/rootlesskit/v2 v2.0.1 h1:yMUDTn9dMWtTkccosPDJpMVxjhmEjSD6jYyaePCXshg= @@ -338,6 +349,7 @@ go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319 go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= 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= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -437,18 +449,18 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 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-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= +google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= 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= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -461,8 +473,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= From 62d013c11cbe28c42ace79075d46b5406d93de14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 22:07:46 +0000 Subject: [PATCH 0358/1066] build(deps): bump github.com/rootless-containers/rootlesskit/v2 Bumps [github.com/rootless-containers/rootlesskit/v2](https://github.com/rootless-containers/rootlesskit) from 2.0.1 to 2.0.2. - [Release notes](https://github.com/rootless-containers/rootlesskit/releases) - [Commits](https://github.com/rootless-containers/rootlesskit/compare/v2.0.1...v2.0.2) --- updated-dependencies: - dependency-name: github.com/rootless-containers/rootlesskit/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b4ca5d66a6a..823d9669ab7 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/opencontainers/runtime-spec v1.2.0 github.com/pelletier/go-toml/v2 v2.1.1 github.com/rootless-containers/bypass4netns v0.4.0 - github.com/rootless-containers/rootlesskit/v2 v2.0.1 + github.com/rootless-containers/rootlesskit/v2 v2.0.2 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/tidwall/gjson v1.17.1 diff --git a/go.sum b/go.sum index 67045d2ae6f..1b3e37aa5ef 100644 --- a/go.sum +++ b/go.sum @@ -281,8 +281,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rootless-containers/bypass4netns v0.4.0 h1:7pcI4XWnOMQkgCsPKMXxMzQKhZUjaQ8J1n+eIYiHS0Y= github.com/rootless-containers/bypass4netns v0.4.0/go.mod h1:RPNWMSRT951DMtq9Xv72IZoJPWFeJL6Wg5pF79Lkano= -github.com/rootless-containers/rootlesskit/v2 v2.0.1 h1:yMUDTn9dMWtTkccosPDJpMVxjhmEjSD6jYyaePCXshg= -github.com/rootless-containers/rootlesskit/v2 v2.0.1/go.mod h1:ZwETpgA/DPizAF7Zdui4ZHOfYK5rZ4Z4SUO6omyZVfY= +github.com/rootless-containers/rootlesskit/v2 v2.0.2 h1:wztWcDYFlk+EVAUuPJwlNMFXZIk1G14T45lv47WWGuA= +github.com/rootless-containers/rootlesskit/v2 v2.0.2/go.mod h1:hE+ztevrQxNi+tdZyPKumzDk7VKDAf0E4seOzlOyBsY= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= From da007062d43cdc9645fd604536f7426377f53a32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Mar 2024 22:59:44 +0000 Subject: [PATCH 0359/1066] build(deps): bump github.com/go-jose/go-jose/v3 from 3.0.1 to 3.0.3 Bumps [github.com/go-jose/go-jose/v3](https://github.com/go-jose/go-jose) from 3.0.1 to 3.0.3. - [Release notes](https://github.com/go-jose/go-jose/releases) - [Changelog](https://github.com/go-jose/go-jose/blob/v3.0.3/CHANGELOG.md) - [Commits](https://github.com/go-jose/go-jose/compare/v3.0.1...v3.0.3) --- updated-dependencies: - dependency-name: github.com/go-jose/go-jose/v3 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 32 ++++++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 823d9669ab7..2c3ec349d22 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/felixge/httpsnoop v1.0.3 // indirect - github.com/go-jose/go-jose/v3 v3.0.1 // indirect + github.com/go-jose/go-jose/v3 v3.0.3 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect diff --git a/go.sum b/go.sum index 1b3e37aa5ef..ba4d01ba252 100644 --- a/go.sum +++ b/go.sum @@ -117,8 +117,8 @@ github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= -github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= +github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -160,6 +160,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -303,7 +304,6 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -336,6 +336,7 @@ github.com/yuchanns/srslog v1.1.0 h1:CEm97Xxxd8XpJThE0gc/XsqUGgPufh5u5MUjC27/KOk github.com/yuchanns/srslog v1.1.0/go.mod h1:HsLjdv3XV02C3kgBW2bTyW6i88OQE+VYJZIxrPKPPak= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= @@ -353,9 +354,10 @@ go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -366,6 +368,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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= @@ -379,7 +383,11 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -389,6 +397,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -409,22 +419,34 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -437,6 +459,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 41b669d7312aaff97aba165657755be387f31a99 Mon Sep 17 00:00:00 2001 From: Alessio Greggi Date: Fri, 23 Feb 2024 17:00:22 +0100 Subject: [PATCH 0360/1066] feat: create network cleanup function for kill and stop cmd Signed-off-by: Alessio Greggi --- cmd/nerdctl/container_kill_linux_test.go | 78 +++++++++++ cmd/nerdctl/container_stop_linux_test.go | 49 +++++++ pkg/cmd/container/kill.go | 84 ++++++++++++ pkg/cmd/container/stop.go | 3 + pkg/ocihook/ocihook.go | 167 +++++++++++------------ pkg/testutil/iptables/iptables.go | 99 ++++++++++++++ 6 files changed, 390 insertions(+), 90 deletions(-) create mode 100644 cmd/nerdctl/container_kill_linux_test.go create mode 100644 pkg/testutil/iptables/iptables.go diff --git a/cmd/nerdctl/container_kill_linux_test.go b/cmd/nerdctl/container_kill_linux_test.go new file mode 100644 index 00000000000..3651c06c6a9 --- /dev/null +++ b/cmd/nerdctl/container_kill_linux_test.go @@ -0,0 +1,78 @@ +/* + 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" + + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + iptablesutil "github.com/containerd/nerdctl/v2/pkg/testutil/iptables" + "github.com/coreos/go-iptables/iptables" + "gotest.tools/v3/assert" +) + +// TestKillCleanupForwards runs a container that exposes a port and then kill it. +// The test checks that the kill command effectively clean up +// the iptables forwards creted from the run. +func TestKillCleanupForwards(t *testing.T) { + const ( + hostPort = 9999 + testContainerName = "ngx" + ) + base := testutil.NewBase(t) + defer func() { + base.Cmd("rm", "-f", testContainerName).Run() + }() + + // skip if rootless + if rootlessutil.IsRootless() { + t.Skip("pkg/testutil/iptables does not support rootless") + } + + ipt, err := iptables.New() + assert.NilError(t, err) + + containerID := base.Cmd("run", "-d", + "--restart=no", + "--name", testContainerName, + "-p", fmt.Sprintf("127.0.0.1:%d:80", hostPort), + testutil.NginxAlpineImage).Run().Stdout() + containerID = strings.TrimSuffix(containerID, "\n") + + containerIP := base.Cmd("inspect", + "-f", + "'{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}'", + testContainerName).Run().Stdout() + containerIP = strings.ReplaceAll(containerIP, "'", "") + containerIP = strings.TrimSuffix(containerIP, "\n") + + // define iptables chain name depending on the target (docker/nerdctl) + var chain string + if testutil.GetTarget() == testutil.Docker { + chain = "DOCKER" + } else { + redirectChain := "CNI-HOSTPORT-DNAT" + chain = iptablesutil.GetRedirectedChain(t, ipt, redirectChain, testutil.Namespace, containerID) + } + assert.Equal(t, iptablesutil.ForwardExists(t, ipt, chain, containerIP, hostPort), true) + + base.Cmd("kill", testContainerName).AssertOK() + assert.Equal(t, iptablesutil.ForwardExists(t, ipt, chain, containerIP, hostPort), false) +} diff --git a/cmd/nerdctl/container_stop_linux_test.go b/cmd/nerdctl/container_stop_linux_test.go index de5338f7998..a29e697bdb6 100644 --- a/cmd/nerdctl/container_stop_linux_test.go +++ b/cmd/nerdctl/container_stop_linux_test.go @@ -22,8 +22,11 @@ import ( "strings" "testing" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" + iptablesutil "github.com/containerd/nerdctl/v2/pkg/testutil/iptables" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/coreos/go-iptables/iptables" "gotest.tools/v3/assert" ) @@ -86,3 +89,49 @@ echo "signal quit"`).AssertOK() base.Cmd("stop", testContainerName).AssertOK() base.Cmd("logs", "-f", testContainerName).AssertOutContains("signal quit") } + +func TestStopCleanupForwards(t *testing.T) { + const ( + hostPort = 9999 + testContainerName = "ngx" + ) + base := testutil.NewBase(t) + defer func() { + base.Cmd("rm", "-f", testContainerName).Run() + }() + + // skip if rootless + if rootlessutil.IsRootless() { + t.Skip("pkg/testutil/iptables does not support rootless") + } + + ipt, err := iptables.New() + assert.NilError(t, err) + + containerID := base.Cmd("run", "-d", + "--restart=no", + "--name", testContainerName, + "-p", fmt.Sprintf("127.0.0.1:%d:80", hostPort), + testutil.NginxAlpineImage).Run().Stdout() + containerID = strings.TrimSuffix(containerID, "\n") + + containerIP := base.Cmd("inspect", + "-f", + "'{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}'", + testContainerName).Run().Stdout() + containerIP = strings.ReplaceAll(containerIP, "'", "") + containerIP = strings.TrimSuffix(containerIP, "\n") + + // define iptables chain name depending on the target (docker/nerdctl) + var chain string + if testutil.GetTarget() == testutil.Docker { + chain = "DOCKER" + } else { + redirectChain := "CNI-HOSTPORT-DNAT" + chain = iptablesutil.GetRedirectedChain(t, ipt, redirectChain, testutil.Namespace, containerID) + } + assert.Equal(t, iptablesutil.ForwardExists(t, ipt, chain, containerIP, hostPort), true) + + base.Cmd("stop", testContainerName).AssertOK() + assert.Equal(t, iptablesutil.ForwardExists(t, ipt, chain, containerIP, hostPort), false) +} diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index ad2104b283c..20c9bd9efed 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -18,6 +18,7 @@ package container import ( "context" + "encoding/json" "fmt" "os" "strings" @@ -26,10 +27,16 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" "github.com/containerd/containerd/errdefs" + gocni "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/netutil" + "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" + "github.com/containerd/nerdctl/v2/pkg/portutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/moby/sys/signal" ) @@ -50,6 +57,9 @@ func Kill(ctx context.Context, client *containerd.Client, reqs []string, options if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } + if err := cleanupNetwork(ctx, found.Container, options.GOptions); err != nil { + return fmt.Errorf("unable to cleanup network for container: %s, %q", found.Req, err) + } if err := killContainer(ctx, found.Container, parsedSignal); err != nil { if errdefs.IsNotFound(err) { fmt.Fprintf(options.Stderr, "No such container: %s\n", found.Req) @@ -106,3 +116,77 @@ func killContainer(ctx context.Context, container containerd.Container, signal s } return nil } + +// cleanupNetwork removes cni network setup, specifically the forwards +func cleanupNetwork(ctx context.Context, container containerd.Container, globalOpts types.GlobalCommandOptions) error { + return rootlessutil.WithDetachedNetNSIfAny(func() error { + // retrieve info to get current active port mappings + info, err := container.Info(ctx, containerd.WithoutRefreshedMetadata) + if err != nil { + return err + } + ports, portErr := portutil.ParsePortsLabel(info.Labels) + if portErr != nil { + return fmt.Errorf("no oci spec: %q", portErr) + } + portMappings := []gocni.NamespaceOpts{ + gocni.WithCapabilityPortMap(ports), + } + + // retrieve info to get cni instance + spec, err := container.Spec(ctx) + if err != nil { + return err + } + networksJSON := spec.Annotations[labels.Networks] + var networks []string + if err := json.Unmarshal([]byte(networksJSON), &networks); err != nil { + return err + } + netType, err := nettype.Detect(networks) + if err != nil { + return err + } + + switch netType { + case nettype.Host, nettype.None, nettype.Container: + // NOP + case nettype.CNI: + e, err := netutil.NewCNIEnv(globalOpts.CNIPath, globalOpts.CNINetConfPath, netutil.WithDefaultNetwork()) + if err != nil { + return err + } + cniOpts := []gocni.Opt{ + gocni.WithPluginDir([]string{globalOpts.CNIPath}), + } + netMap, err := e.NetworkMap() + if err != nil { + return err + } + for _, netstr := range networks { + net, ok := netMap[netstr] + if !ok { + return fmt.Errorf("no such network: %q", netstr) + } + cniOpts = append(cniOpts, gocni.WithConfListBytes(net.Bytes)) + } + cni, err := gocni.New(cniOpts...) + if err != nil { + return err + } + + var namespaceOpts []gocni.NamespaceOpts + namespaceOpts = append(namespaceOpts, portMappings...) + namespace := spec.Annotations[labels.Namespace] + fullID := namespace + "-" + container.ID() + if err := cni.Remove(ctx, fullID, "", namespaceOpts...); err != nil { + log.L.WithError(err).Errorf("failed to call cni.Remove") + return err + } + return nil + default: + return fmt.Errorf("unexpected network type %v", netType) + } + return nil + }) +} diff --git a/pkg/cmd/container/stop.go b/pkg/cmd/container/stop.go index 6398abe9e65..35457835d0d 100644 --- a/pkg/cmd/container/stop.go +++ b/pkg/cmd/container/stop.go @@ -35,6 +35,9 @@ func Stop(ctx context.Context, client *containerd.Client, reqs []string, opt typ if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } + if err := cleanupNetwork(ctx, found.Container, opt.GOptions); err != nil { + return fmt.Errorf("unable to cleanup network for container: %s", found.Req) + } if err := containerutil.Stop(ctx, found.Container, opt.Timeout); err != nil { if errdefs.IsNotFound(err) { fmt.Fprintf(opt.Stderr, "No such container: %s\n", found.Req) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index dcf4c978c6b..243d9a9af9a 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -390,107 +390,94 @@ func getIP6AddressOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { return nil, nil } -func onCreateRuntime(opts *handlerOpts) error { - loadAppArmor() - - if opts.cni != nil { - portMapOpts, err := getPortMapOpts(opts) - if err != nil { - return err - } - nsPath, err := getNetNSPath(opts.state) - if err != nil { - return err - } - ctx := context.Background() - hs, err := hostsstore.NewStore(opts.dataStore) - if err != nil { - return err - } - ipAddressOpts, err := getIPAddressOpts(opts) - if err != nil { - return err - } - macAddressOpts, err := getMACAddressOpts(opts) - if err != nil { - return err - } - ip6AddressOpts, err := getIP6AddressOpts(opts) - if err != nil { - return err - } - var namespaceOpts []gocni.NamespaceOpts - namespaceOpts = append(namespaceOpts, portMapOpts...) - namespaceOpts = append(namespaceOpts, ipAddressOpts...) - namespaceOpts = append(namespaceOpts, macAddressOpts...) - namespaceOpts = append(namespaceOpts, ip6AddressOpts...) - hsMeta := hostsstore.Meta{ - Namespace: opts.state.Annotations[labels.Namespace], - ID: opts.state.ID, - Networks: make(map[string]*types100.Result, len(opts.cniNames)), - Hostname: opts.state.Annotations[labels.Hostname], - ExtraHosts: opts.extraHosts, - Name: opts.state.Annotations[labels.Name], - } - cniRes, err := opts.cni.Setup(ctx, opts.fullID, nsPath, namespaceOpts...) - if err != nil { - return fmt.Errorf("failed to call cni.Setup: %w", err) - } - cniResRaw := cniRes.Raw() - for i, cniName := range opts.cniNames { - hsMeta.Networks[cniName] = cniResRaw[i] - } +func applyNetworkSettings(opts *handlerOpts) error { + portMapOpts, err := getPortMapOpts(opts) + if err != nil { + return err + } + nsPath, err := getNetNSPath(opts.state) + if err != nil { + return err + } + ctx := context.Background() + hs, err := hostsstore.NewStore(opts.dataStore) + if err != nil { + return err + } + ipAddressOpts, err := getIPAddressOpts(opts) + if err != nil { + return err + } + macAddressOpts, err := getMACAddressOpts(opts) + if err != nil { + return err + } + ip6AddressOpts, err := getIP6AddressOpts(opts) + if err != nil { + return err + } + var namespaceOpts []gocni.NamespaceOpts + namespaceOpts = append(namespaceOpts, portMapOpts...) + namespaceOpts = append(namespaceOpts, ipAddressOpts...) + namespaceOpts = append(namespaceOpts, macAddressOpts...) + namespaceOpts = append(namespaceOpts, ip6AddressOpts...) + hsMeta := hostsstore.Meta{ + Namespace: opts.state.Annotations[labels.Namespace], + ID: opts.state.ID, + Networks: make(map[string]*types100.Result, len(opts.cniNames)), + Hostname: opts.state.Annotations[labels.Hostname], + ExtraHosts: opts.extraHosts, + Name: opts.state.Annotations[labels.Name], + } + cniRes, err := opts.cni.Setup(ctx, opts.fullID, nsPath, namespaceOpts...) + if err != nil { + return fmt.Errorf("failed to call cni.Setup: %w", err) + } + cniResRaw := cniRes.Raw() + for i, cniName := range opts.cniNames { + hsMeta.Networks[cniName] = cniResRaw[i] + } - b4nnEnabled, err := bypass4netnsutil.IsBypass4netnsEnabled(opts.state.Annotations) - if err != nil { - return err - } + b4nnEnabled, err := bypass4netnsutil.IsBypass4netnsEnabled(opts.state.Annotations) + if err != nil { + return err + } - if err := hs.Acquire(hsMeta); err != nil { - return err - } + if err := hs.Acquire(hsMeta); err != nil { + return err + } - if rootlessutil.IsRootlessChild() { - if b4nnEnabled { - bm, err := bypass4netnsutil.NewBypass4netnsCNIBypassManager(opts.bypassClient, opts.rootlessKitClient) - if err != nil { - return err - } - err = bm.StartBypass(ctx, opts.ports, opts.state.ID, opts.state.Annotations[labels.StateDir]) - if err != nil { - return fmt.Errorf("bypass4netnsd not running? (Hint: run `containerd-rootless-setuptool.sh install-bypass4netnsd`): %w", err) - } - } else if len(opts.ports) > 0 { - if err := exposePortsRootless(ctx, opts.rootlessKitClient, opts.ports); err != nil { - return fmt.Errorf("failed to expose ports in rootless mode: %s", err) - } + if rootlessutil.IsRootlessChild() { + if b4nnEnabled { + bm, err := bypass4netnsutil.NewBypass4netnsCNIBypassManager(opts.bypassClient, opts.rootlessKitClient) + if err != nil { + return err + } + err = bm.StartBypass(ctx, opts.ports, opts.state.ID, opts.state.Annotations[labels.StateDir]) + if err != nil { + return fmt.Errorf("bypass4netnsd not running? (Hint: run `containerd-rootless-setuptool.sh install-bypass4netnsd`): %w", err) + } + } else if len(opts.ports) > 0 { + if err := exposePortsRootless(ctx, opts.rootlessKitClient, opts.ports); err != nil { + return fmt.Errorf("failed to expose ports in rootless mode: %s", err) } } } return nil } -func onStartContainer(opts *handlerOpts) error { - // restore portmapping in case it was removed by kill/stop command +func onCreateRuntime(opts *handlerOpts) error { + loadAppArmor() + if opts.cni != nil { - portMapOpts, err := getPortMapOpts(opts) - if err != nil { - return err - } - nsPath, err := getNetNSPath(opts.state) - if err != nil { - return err - } - ctx := context.Background() - fmt.Println(portMapOpts) + return applyNetworkSettings(opts) + } + return nil +} - var namespaceOpts []gocni.NamespaceOpts - namespaceOpts = append(namespaceOpts, portMapOpts...) - cniRes, err := opts.cni.Setup(ctx, opts.fullID, nsPath, namespaceOpts...) - if err != nil { - return fmt.Errorf("failed to call cni.Setup: %w", err) - } - fmt.Println(cniRes) +func onStartContainer(opts *handlerOpts) error { + if opts.cni != nil { + return applyNetworkSettings(opts) } return nil } diff --git a/pkg/testutil/iptables/iptables.go b/pkg/testutil/iptables/iptables.go new file mode 100644 index 00000000000..c0dcea4d42d --- /dev/null +++ b/pkg/testutil/iptables/iptables.go @@ -0,0 +1,99 @@ +/* + 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 iptables + +import ( + "fmt" + "regexp" + "testing" + + "github.com/coreos/go-iptables/iptables" +) + +// ForwardExists check that at least 2 rules are present in the CNI-HOSTPORT-DNAT chain +// and checks for regex matches in the list of rules +func ForwardExists(t *testing.T, ipt *iptables.IPTables, chain, containerIP string, port int) bool { + rules, err := ipt.List("nat", chain) + if err != nil { + t.Logf("error listing rules in chain: %q\n", err) + return false + } + + if len(rules) < 1 { + t.Logf("not enough rules: %d", len(rules)) + return false + } + + // here we check if at least one of the rules in the chain + // matches the required string to identify that the rule was applied + found := false + matchRule := `--dport ` + fmt.Sprintf("%d", port) + ` .+ --to-destination ` + containerIP + for _, rule := range rules { + foundInRule, err := regexp.MatchString(matchRule, rule) + if err != nil { + t.Logf("error in match string: %q\n", err) + return false + } + if foundInRule { + found = foundInRule + } + } + return found +} + +// GetRedirectedChain returns the chain where the traffic is being redirected. +// This is how libcni manage its port maps. +// Suppose you have the following rule: +// -A CNI-HOSTPORT-DNAT -p tcp -m comment --comment "dnat name: \"bridge\" id: \"default-YYYYYY\"" -m multiport --dports 9999 -j CNI-DN-XXXXXX +// So the chain where the traffic is redirected is CNI-DN-XXXXXX +// Returns an empty string in case nothing was found. +func GetRedirectedChain(t *testing.T, ipt *iptables.IPTables, chain, namespace, containerID string) string { + rules, err := ipt.List("nat", chain) + if err != nil { + t.Logf("error listing rules in chain: %q\n", err) + return "" + } + + if len(rules) < 1 { + t.Logf("not enough rules: %d", len(rules)) + return "" + } + + var redirectedChain string + re := regexp.MustCompile(`-j\s+([^ ]+)`) + for _, rule := range rules { + // first we verify the comment section is present: "dnat name: \"bridge\" id: \"default-YYYYYY\"" + matchesContainer, err := regexp.MatchString(namespace+"-"+containerID, rule) + if err != nil { + t.Logf("error in match string: %q\n", err) + return "" + } + if matchesContainer { + // then we find the appropriate chain in the rule + matches := re.FindStringSubmatch(rule) + fmt.Println(matches) + if len(matches) >= 2 { + redirectedChain = matches[1] + } + } + } + if redirectedChain == "" { + t.Logf("no redirectced chain found") + return "" + } + return redirectedChain +} From ca56bc42258112ea01faa3accbcc5892ea2746e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 22:14:52 +0000 Subject: [PATCH 0361/1066] build(deps): bump docker/build-push-action from 5.1.0 to 5.2.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.1.0 to 5.2.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v5.1.0...v5.2.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index cff2cbdc9cb..5e2f8297fe4 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -59,7 +59,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v5.1.0 + uses: docker/build-push-action@v5.2.0 with: context: . platforms: linux/amd64,linux/arm64 From 341c60d46f735d01eb6820d9a7881ad9b95dc1b4 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Sun, 10 Mar 2024 06:41:04 +0000 Subject: [PATCH 0362/1066] update BuildKit (0.13.0) Signed-off-by: Kay Yan --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0 | 2 ++ Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-rc1 | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0 delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-rc1 diff --git a/Dockerfile b/Dockerfile index f9d1bdd2bb4..666bea984fe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.12 ARG CNI_PLUGINS_VERSION=v1.4.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.13.0-rc1 +ARG BUILDKIT_VERSION=v0.13.0 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0 new file mode 100644 index 00000000000..8f1b1c5fc18 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0 @@ -0,0 +1,2 @@ +0893f55180c3da895ad998af25305f32413676a72a36b4372607ff7396f607e8 buildkit-v0.13.0.linux-amd64.tar.gz +265f9756102de5fe3b8f299b7e96a9ef4ff69763805642676129c2713477071d buildkit-v0.13.0.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-rc1 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-rc1 deleted file mode 100644 index 38deac342ab..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0-rc1 +++ /dev/null @@ -1,2 +0,0 @@ -e3ca21393aba992e755f5819eccddf0d4043e6038a4bba3462a84e157b59477e buildkit-v0.13.0-rc1.linux-amd64.tar.gz -da7a6cced9c21af8d1098c587d6ec6a21b7c034d0143e50c6481888189e7a3fa buildkit-v0.13.0-rc1.linux-arm64.tar.gz From bc8450e843b64b8ed466afaee6e8a8b51dbcf4c4 Mon Sep 17 00:00:00 2001 From: Joao Pargana Date: Thu, 7 Mar 2024 17:02:57 +0000 Subject: [PATCH 0363/1066] feat: add extra contexts to buildctl call #2835 Signed-off-by: Joao Pargana --- cmd/nerdctl/builder_build.go | 56 +++++++++++++++++-------------- cmd/nerdctl/builder_build_test.go | 44 ++++++++++++++++++++++++ docs/command-reference.md | 1 + pkg/api/types/builder_types.go | 2 ++ pkg/cmd/builder/build.go | 37 ++++++++++++++++++++ 5 files changed, 115 insertions(+), 25 deletions(-) diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index 4952451f0df..9b060cbbe07 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -72,6 +72,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" buildCommand.Flags().StringSlice("platform", []string{}, "Set target platform for build (e.g., \"amd64\", \"arm64\")") buildCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + buildCommand.Flags().StringArray("build-context", []string{}, "Additional build contexts (e.g., name=path)") // #endregion buildCommand.Flags().String("iidfile", "", "Write the image ID to the file") @@ -188,33 +189,38 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu if provenance != "" { attest = append(attest, canonicalizeAttest("provenance", provenance)) } + extendedBuildCtx, err := cmd.Flags().GetStringArray("build-context") + if err != nil { + return types.BuilderBuildOptions{}, err + } return types.BuilderBuildOptions{ - GOptions: globalOptions, - BuildKitHost: buildKitHost, - BuildContext: buildContext, - Output: output, - Tag: tagValue, - Progress: progress, - File: filename, - Target: target, - BuildArgs: buildArgs, - Label: label, - NoCache: noCache, - Secret: secret, - Allow: allow, - Attest: attest, - SSH: ssh, - CacheFrom: cacheFrom, - CacheTo: cacheTo, - Rm: rm, - IidFile: iidfile, - Quiet: quiet, - Platform: platform, - Stdout: cmd.OutOrStdout(), - Stderr: cmd.OutOrStderr(), - Stdin: cmd.InOrStdin(), - NetworkMode: network, + GOptions: globalOptions, + BuildKitHost: buildKitHost, + BuildContext: buildContext, + Output: output, + Tag: tagValue, + Progress: progress, + File: filename, + Target: target, + BuildArgs: buildArgs, + Label: label, + NoCache: noCache, + Secret: secret, + Allow: allow, + Attest: attest, + SSH: ssh, + CacheFrom: cacheFrom, + CacheTo: cacheTo, + Rm: rm, + IidFile: iidfile, + Quiet: quiet, + Platform: platform, + Stdout: cmd.OutOrStdout(), + Stderr: cmd.OutOrStderr(), + Stdin: cmd.InOrStdin(), + NetworkMode: network, + ExtendedBuildContext: extendedBuildCtx, }, nil } diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index 72168df5752..f5c160653ac 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -456,6 +456,50 @@ CMD ["echo", "nerdctl-build-notag-string"] base.Cmd("image", "prune", "--force", "--all").AssertOK() } +func TestBuildContextDockerImageAlias(t *testing.T) { + testutil.RequiresBuild(t) + base := testutil.NewBase(t) + defer base.Cmd("builder", "prune").AssertOK() + base.Cmd("image", "prune", "--force", "--all").AssertOK() + + dockerfile := `FROM myorg/myapp +CMD ["echo", "nerdctl-build-myorg/myapp"]` + buildCtx, err := createBuildContext(dockerfile) + assert.NilError(t, err) + defer os.RemoveAll(buildCtx) + + base.Cmd("build", buildCtx, fmt.Sprintf("--build-context=myorg/myapp=docker-image://%s", testutil.CommonImage)).AssertOK() + base.Cmd("images").AssertOutContains("") + base.Cmd("image", "prune", "--force", "--all").AssertOK() +} + +func TestBuildContextWithCopyFromDir(t *testing.T) { + testutil.RequiresBuild(t) + base := testutil.NewBase(t) + defer base.Cmd("builder", "prune").AssertOK() + base.Cmd("image", "prune", "--force", "--all").AssertOK() + + content := "hello_from_dir_2" + filename := "hello.txt" + + dir2 := t.TempDir() + filePath := filepath.Join(dir2, filename) + err := os.WriteFile(filePath, []byte(content), 0644) + assert.NilError(t, err) + + dockerfile := fmt.Sprintf(`FROM %s +COPY --from=dir2 /%s /hello_from_dir2.txt +RUN ["cat", "/hello_from_dir2.txt"]`, testutil.CommonImage, filename) + + buildCtx, err := createBuildContext(dockerfile) + assert.NilError(t, err) + defer os.RemoveAll(buildCtx) + + base.Cmd("build", buildCtx, fmt.Sprintf("--build-context=dir2=%s", dir2)).AssertOK() + base.Cmd("images").AssertOutContains("") + base.Cmd("image", "prune", "--force", "--all").AssertOK() +} + // TestBuildSourceDateEpoch tests that $SOURCE_DATE_EPOCH is propagated from the client env // https://github.com/docker/buildx/pull/1482 func TestBuildSourceDateEpoch(t *testing.T) { diff --git a/docs/command-reference.md b/docs/command-reference.md index 00d69ee420c..afe15b42797 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -703,6 +703,7 @@ Flags: - :nerd_face: `--ipfs`: Build image with pulling base images from IPFS. See [`ipfs.md`](./ipfs.md) for details. - :whale: `--label`: Set metadata for an image - :whale: `--network=(default|host|none)`: Set the networking mode for the RUN instructions during build.(compatible with `buildctl build`) +- :whale: --build-context: Set additional contexts for build (e.g. dir2=/path/to/dir2, myorg/myapp=docker-image://path/to/myorg/myapp) Unimplemented `docker build` flags: `--add-host`, `--squash` diff --git a/pkg/api/types/builder_types.go b/pkg/api/types/builder_types.go index f7fb0f772fa..7a0dd4cb885 100644 --- a/pkg/api/types/builder_types.go +++ b/pkg/api/types/builder_types.go @@ -65,6 +65,8 @@ type BuilderBuildOptions struct { Label []string // BuildContext is the build context BuildContext string + // ExtendedBuildContext is a pair of key=value (e.g. myorg/myapp=docker-image://path/to/image, dir2=/path/to/dir2) + ExtendedBuildContext []string // NetworkMode mode for the build context NetworkMode string } diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 5bbdd06cb44..fe544ac4a39 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -284,6 +284,28 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option return "", nil, false, "", nil, nil, err } + buildCtx, err := parseContextNames(options.ExtendedBuildContext) + if err != nil { + return "", nil, false, "", nil, nil, err + } + + for k, v := range buildCtx { + isURL := strings.HasPrefix(v, "https://") || strings.HasPrefix(v, "http://") + isDockerImage := strings.HasPrefix(v, "docker-image://") || strings.HasPrefix(v, "target:") + + if isURL || isDockerImage { + buildctlArgs = append(buildctlArgs, fmt.Sprintf("--opt=context:%s=%s", k, v)) + continue + } + + path, err := filepath.Abs(v) + if err != nil { + return "", nil, false, "", nil, nil, err + } + buildctlArgs = append(buildctlArgs, fmt.Sprintf("--local=%s=%s", k, path)) + buildctlArgs = append(buildctlArgs, fmt.Sprintf("--opt=context:%s=local:%s", k, k)) + } + buildctlArgs = append(buildctlArgs, "--local=dockerfile="+dir) buildctlArgs = append(buildctlArgs, "--opt=filename="+file) @@ -486,3 +508,18 @@ func isImageSharable(buildkitHost, namespace, uuid, snapshotter string, platform parser := new(platformParser) return executor == "containerd" && containerdUUID == uuid && containerdNamespace == namespace && workerSnapshotter == snapshotter && isBuildPlatformDefault(platform, parser), nil } + +func parseContextNames(values []string) (map[string]string, error) { + if len(values) == 0 { + return nil, nil + } + result := make(map[string]string, len(values)) + for _, value := range values { + kv := strings.SplitN(value, "=", 2) + if len(kv) != 2 { + return nil, fmt.Errorf("invalid context value: %s, expected key=value", value) + } + result[kv[0]] = kv[1] + } + return result, nil +} From 258362b8bb5538fdd3ca515d735784d8dd0a30d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 22:40:40 +0000 Subject: [PATCH 0364/1066] build(deps): bump github.com/containerd/containerd from 1.7.13 to 1.7.14 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.13 to 1.7.14. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.13...v1.7.14) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 16 ++++------------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 2c3ec349d22..03c80d2345e 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.0.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd v1.7.13 + github.com/containerd/containerd v1.7.14 github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 @@ -73,7 +73,7 @@ require ( github.com/cilium/ebpf v0.11.0 // indirect github.com/containerd/errdefs v0.1.0 // indirect github.com/containerd/go-runc v1.0.0 // indirect - github.com/containerd/ttrpc v1.2.2 // indirect + github.com/containerd/ttrpc v1.2.3 // 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 diff --git a/go.sum b/go.sum index ba4d01ba252..567c41f345d 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ 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.13 h1:wPYKIeGMN8vaggSKuV1X0wZulpMz4CrgEsZdaCyB6Is= -github.com/containerd/containerd v1.7.13/go.mod h1:zT3up6yTRfEUa6+GsITYIJNgSVL9NQ4x4h1RPzk0Wu4= +github.com/containerd/containerd v1.7.14 h1:H/XLzbnGuenZEGK+v0RkwTdv2u1QFAruMe5N0GNPJwA= +github.com/containerd/containerd v1.7.14/go.mod h1:YMC9Qt5yzNqXx/fO4j/5yYVIHXSRrlB3H7sxkUTvspg= 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= @@ -61,8 +61,8 @@ github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G 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.2 h1:9vqZr0pxwOF5koz6N0N3kJ0zDHokrcPxIR/ZR2YFtOs= -github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak= +github.com/containerd/ttrpc v1.2.3 h1:4jlhbXIGvijRtNC8F/5CpuJZ7yKOBFGFOOXg1bkISz0= +github.com/containerd/ttrpc v1.2.3/go.mod h1:ieWsXucbb8Mj9PH0rXCw1i8IunRbbAiDkpXkbfflWBM= 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= @@ -139,7 +139,6 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -158,7 +157,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -275,7 +273,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= @@ -286,7 +283,6 @@ github.com/rootless-containers/rootlesskit/v2 v2.0.2 h1:wztWcDYFlk+EVAUuPJwlNMFX github.com/rootless-containers/rootlesskit/v2 v2.0.2/go.mod h1:hE+ztevrQxNi+tdZyPKumzDk7VKDAf0E4seOzlOyBsY= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -396,7 +392,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= @@ -417,7 +412,6 @@ golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -471,7 +465,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= @@ -481,7 +474,6 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= From 533f16b95e1044892a593101e0b05aa101db9ddc Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 12 Mar 2024 13:00:39 +0900 Subject: [PATCH 0365/1066] CI: update FreeBSD to 14 Signed-off-by: Akihiro Suda --- Vagrantfile.freebsd | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Vagrantfile.freebsd b/Vagrantfile.freebsd index 1aaadf5d6d9..4fe7ef0000d 100644 --- a/Vagrantfile.freebsd +++ b/Vagrantfile.freebsd @@ -17,9 +17,7 @@ # Vagrantfile for FreeBSD Vagrant.configure("2") do |config| - config.vm.box = "generic/freebsd13" - # workaround for https://github.com/containerd/nerdctl/issues/2596 - config.vm.box_version = "4.3.2" + config.vm.box = "generic/freebsd14" memory = 2048 cpus = 1 From 4d9abe27af343b5b7585542ecbc3bd12a8a1ce10 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 12 Mar 2024 04:53:40 +0000 Subject: [PATCH 0366/1066] update containerd (1.7.14),(1.6.30) Signed-off-by: Kay Yan --- .github/workflows/test.yml | 24 ++++++++++++------------ Dockerfile | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9d61b45cb2d..ca46ee68230 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,11 +77,11 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.28 + containerd: v1.6.30 - ubuntu: 20.04 - containerd: v1.7.13 + containerd: v1.7.14 - ubuntu: 22.04 - containerd: v1.7.13 + containerd: v1.7.14 - ubuntu: 22.04 containerd: main env: @@ -113,7 +113,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 22.04 - containerd: v1.7.13 + containerd: v1.7.14 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -157,15 +157,15 @@ jobs: # ubuntu-22.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.28 + containerd: v1.6.30 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.13 + containerd: v1.7.14 rootlesskit: v2.0.1 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.13 + containerd: v1.7.14 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 @@ -173,15 +173,15 @@ jobs: rootlesskit: v2.0.1 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.6.28 + containerd: v1.6.30 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.13 + containerd: v1.7.14 rootlesskit: v2.0.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.13 + containerd: v1.7.14 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 @@ -275,7 +275,7 @@ jobs: - uses: actions/checkout@v4.1.1 with: repository: containerd/containerd - ref: v1.7.13 + ref: v1.7.14 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -283,7 +283,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.13 + ctrdVersion: 1.7.14 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index 666bea984fe..e62142fcbdc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.13 +ARG CONTAINERD_VERSION=v1.7.14 ARG RUNC_VERSION=v1.1.12 ARG CNI_PLUGINS_VERSION=v1.4.0 From 0ec5c7e90c8c50b8c6a18abfd35d889560499475 Mon Sep 17 00:00:00 2001 From: Joao Pargana Date: Mon, 11 Mar 2024 12:18:52 +0000 Subject: [PATCH 0367/1066] refactor: replace os.MkdirTemp with t.TempDir with cleanup Signed-off-by: Joao Pargana --- cmd/nerdctl/builder_build_test.go | 83 +++++-------------- cmd/nerdctl/builder_linux_test.go | 6 +- cmd/nerdctl/container_run_mount_linux_test.go | 20 ++--- cmd/nerdctl/container_run_test.go | 8 +- .../container_run_verify_linux_test.go | 6 +- cmd/nerdctl/image_list_test.go | 9 +- cmd/nerdctl/image_prune_test.go | 10 +-- cmd/nerdctl/image_pull_linux_test.go | 13 +-- cmd/nerdctl/ipfs_build_linux_test.go | 5 +- cmd/nerdctl/multi_platform_linux_test.go | 9 +- 10 files changed, 41 insertions(+), 128 deletions(-) diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index f5c160653ac..6df2f7bd210 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -39,9 +39,7 @@ func TestBuild(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("build", buildCtx, "-t", imageName).AssertOK() @@ -69,9 +67,7 @@ func TestBuildIsShareableForCompatiblePlatform(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", buildCtx, "-t", imageName).AssertErrNotContains("tarball") @@ -86,7 +82,6 @@ CMD ["echo", "nerdctl-build-test-string"] base.Cmd("build", buildCtx, "-t", imageName, "--platform", notCompatiblePlatformConfig).AssertOK() base.Cmd("build", buildCtx, "-t", imageName, "--platform", notCompatiblePlatformConfig, "--progress", "plain").AssertErrContains("tarball") } - } // TestBuildBaseImage tests if an image can be built on the previously built image. @@ -105,9 +100,7 @@ RUN echo hello > /hello CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("build", buildCtx, "-t", imageName).AssertOK() @@ -117,9 +110,7 @@ RUN echo hello2 > /hello2 CMD ["cat", "/hello2"] `, imageName) - buildCtx2, err := createBuildContext(dockerfile2) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx2) + buildCtx2 := createBuildContext(t, dockerfile2) base.Cmd("build", "-t", imageName2, buildCtx2).AssertOK() base.Cmd("build", buildCtx2, "-t", imageName2).AssertOK() @@ -152,9 +143,7 @@ RUN echo hello2 > /hello2 CMD ["cat", "/hello2"] `, imageName) - buildCtx2, err := createBuildContext(dockerfile2) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx2) + buildCtx2 := createBuildContext(t, dockerfile2) base.Cmd("build", "-t", imageName2, buildCtx2).AssertOK() base.Cmd("build", buildCtx2, "-t", imageName2).AssertOK() @@ -225,9 +214,7 @@ func TestBuildLocal(t *testing.T) { COPY %s /`, testFileName) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) if err := os.WriteFile(filepath.Join(buildCtx, testFileName), []byte(testContent), 0644); err != nil { t.Fatal(err) @@ -253,15 +240,11 @@ COPY %s /`, assert.Equal(t, string(data), testContent) } -func createBuildContext(dockerfile string) (string, error) { - tmpDir, err := os.MkdirTemp("", "nerdctl-build-test") - if err != nil { - return "", err - } - if err = os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil { - return "", err - } - return tmpDir, nil +func createBuildContext(t *testing.T, dockerfile string) string { + tmpDir := t.TempDir() + err := os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644) + assert.NilError(t, err) + return tmpDir } func TestBuildWithBuildArg(t *testing.T) { @@ -277,9 +260,7 @@ ENV TEST_STRING=$TEST_STRING CMD echo $TEST_STRING `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", buildCtx, "-t", imageName).AssertOK() base.Cmd("run", "--rm", imageName).AssertOutExactly("1\n") @@ -324,9 +305,7 @@ func TestBuildWithIIDFile(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) fileName := filepath.Join(t.TempDir(), "id.txt") base.Cmd("build", "-t", imageName, buildCtx, "--iidfile", fileName).AssertOK() @@ -350,9 +329,7 @@ func TestBuildWithLabels(t *testing.T) { LABEL name=nerdctl-build-test-label `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx, "--label", "label=test").AssertOK() defer base.Cmd("rmi", imageName).Run() @@ -375,9 +352,7 @@ func TestBuildMultipleTags(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "%s"] `, testutil.CommonImage, output) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", img, buildCtx).AssertOK() base.Cmd("build", buildCtx, "-t", img, "-t", imgWithNoTag, "-t", imgWithCustomTag).AssertOK() @@ -430,9 +405,7 @@ CMD ["echo", "dockerfile"] err = os.WriteFile(filepath.Join(tmpDir, "Containerfile"), []byte(containerfile), 0644) assert.NilError(t, err) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("run", "--rm", imageName).AssertOutExactly("dockerfile\n") @@ -447,9 +420,7 @@ func TestBuildNoTag(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-notag-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", buildCtx).AssertOK() base.Cmd("images").AssertOutContains("") @@ -464,9 +435,7 @@ func TestBuildContextDockerImageAlias(t *testing.T) { dockerfile := `FROM myorg/myapp CMD ["echo", "nerdctl-build-myorg/myapp"]` - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", buildCtx, fmt.Sprintf("--build-context=myorg/myapp=docker-image://%s", testutil.CommonImage)).AssertOK() base.Cmd("images").AssertOutContains("") @@ -491,9 +460,7 @@ func TestBuildContextWithCopyFromDir(t *testing.T) { COPY --from=dir2 /%s /hello_from_dir2.txt RUN ["cat", "/hello_from_dir2.txt"]`, testutil.CommonImage, filename) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", buildCtx, fmt.Sprintf("--build-context=dir2=%s", dir2)).AssertOK() base.Cmd("images").AssertOutContains("") @@ -515,9 +482,7 @@ RUN echo $SOURCE_DATE_EPOCH >/source-date-epoch CMD ["cat", "/source-date-epoch"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) const sourceDateEpochEnvStr = "1111111111" t.Setenv("SOURCE_DATE_EPOCH", sourceDateEpochEnvStr) @@ -538,9 +503,7 @@ func TestBuildNetwork(t *testing.T) { RUN apk add --no-cache curl RUN curl -I http://google.com `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) validCases := []struct { name string @@ -597,9 +560,7 @@ func TestBuildAttestation(t *testing.T) { defer base.Cmd("builder", "prune").Run() dockerfile := "FROM " + testutil.NginxAlpineImage - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) // Test sbom outputSBOMDir := t.TempDir() diff --git a/cmd/nerdctl/builder_linux_test.go b/cmd/nerdctl/builder_linux_test.go index bdf1cc402d5..717e83ac1cf 100644 --- a/cmd/nerdctl/builder_linux_test.go +++ b/cmd/nerdctl/builder_linux_test.go @@ -19,11 +19,9 @@ package main import ( "bytes" "fmt" - "os" "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) func TestBuilderDebug(t *testing.T) { @@ -34,9 +32,7 @@ func TestBuilderDebug(t *testing.T) { CMD ["echo", "nerdctl-builder-debug-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("builder", "debug", buildCtx).CmdOption(testutil.WithStdin(bytes.NewReader([]byte("c\n")))).AssertOK() } diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container_run_mount_linux_test.go index 55527bf0ae7..ee8a8b6d14a 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container_run_mount_linux_test.go @@ -122,9 +122,7 @@ func TestRunAnonymousVolumeWithBuild(t *testing.T) { VOLUME /foo `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("run", "--rm", "-v", "/foo", testutil.AlpineImage, @@ -146,9 +144,7 @@ RUN mkdir -p /mnt && echo hi > /mnt/initial_file CMD ["cat", "/mnt/initial_file"] `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() @@ -176,9 +172,7 @@ VOLUME /mnt CMD ["cat", "/mnt/initial_file"] `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() //AnonymousVolume @@ -211,9 +205,7 @@ CMD ["readlink", "/mnt/passwd"] `, testutil.AlpineImage) const expected = "../../../../../../../../../../../../../../../../../../etc/passwd\n" - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() @@ -240,9 +232,7 @@ func TestRunCopyingUpInitialContentsShouldNotResetTheCopiedContents(t *testing.T RUN echo -n "rev0" > /mnt/file `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index 6b70d362b6b..2fb732573c7 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -49,9 +49,7 @@ ENTRYPOINT ["echo", "foo"] CMD ["echo", "bar"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("run", "--rm", imageName).AssertOutExactly("foo echo bar\n") @@ -428,9 +426,7 @@ FROM scratch COPY --from=builder /go/src/logger/logger / ` - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) tmpDir := t.TempDir() base.Cmd("build", buildCtx, "--output", fmt.Sprintf("type=local,src=/go/src/logger/logger,dest=%s", tmpDir)).AssertOK() defer base.Cmd("image", "rm", "-f", imageName).AssertOK() diff --git a/cmd/nerdctl/container_run_verify_linux_test.go b/cmd/nerdctl/container_run_verify_linux_test.go index 80e9ac5d99e..e5c500d59da 100644 --- a/cmd/nerdctl/container_run_verify_linux_test.go +++ b/cmd/nerdctl/container_run_verify_linux_test.go @@ -18,12 +18,10 @@ package main import ( "fmt" - "os" "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" - "gotest.tools/v3/assert" ) func TestRunVerifyCosign(t *testing.T) { @@ -48,9 +46,7 @@ func TestRunVerifyCosign(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() diff --git a/cmd/nerdctl/image_list_test.go b/cmd/nerdctl/image_list_test.go index 4043cf26633..bb989137d6d 100644 --- a/cmd/nerdctl/image_list_test.go +++ b/cmd/nerdctl/image_list_test.go @@ -18,7 +18,6 @@ package main import ( "fmt" - "os" "strings" "testing" @@ -88,9 +87,7 @@ CMD ["echo", "nerdctl-build-test-string"] \n LABEL foo=bar LABEL version=0.1`, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", tempName, "-f", buildCtx+"/Dockerfile", buildCtx).AssertOK() defer base.Cmd("rmi", tempName).AssertOK() @@ -128,10 +125,8 @@ func TestImagesFilterDangling(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-notag-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) + buildCtx := createBuildContext(t, dockerfile) - defer os.RemoveAll(buildCtx) base.Cmd("build", "-f", buildCtx+"/Dockerfile", buildCtx).AssertOK() // dangling image test diff --git a/cmd/nerdctl/image_prune_test.go b/cmd/nerdctl/image_prune_test.go index 63ba0f5bdea..b7f0a02e833 100644 --- a/cmd/nerdctl/image_prune_test.go +++ b/cmd/nerdctl/image_prune_test.go @@ -18,11 +18,9 @@ package main import ( "fmt" - "os" "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) func TestImagePrune(t *testing.T) { @@ -36,9 +34,7 @@ func TestImagePrune(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune"]`, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", buildCtx).AssertOK() base.Cmd("build", "-t", imageName, buildCtx).AssertOK() @@ -59,9 +55,7 @@ func TestImagePruneAll(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune"]`, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() // The following commands will clean up all images, so it should fail at this point. diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image_pull_linux_test.go index 82c83871f3a..931d7905737 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image_pull_linux_test.go @@ -79,9 +79,7 @@ func TestImageVerifyWithCosign(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() @@ -103,9 +101,7 @@ func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() base.Cmd("--insecure-registry", "push", testImageRef).AssertOK() base.Cmd("--insecure-registry", "pull", testImageRef).AssertOK() @@ -133,9 +129,7 @@ func TestImageVerifyWithCosignShouldFailWhenKeyIsNotCorrect(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() @@ -202,5 +196,4 @@ func TestPullSoci(t *testing.T) { } }) } - } diff --git a/cmd/nerdctl/ipfs_build_linux_test.go b/cmd/nerdctl/ipfs_build_linux_test.go index 55a629aa13c..5fc6efc307e 100644 --- a/cmd/nerdctl/ipfs_build_linux_test.go +++ b/cmd/nerdctl/ipfs_build_linux_test.go @@ -18,7 +18,6 @@ package main import ( "fmt" - "os" "strings" "testing" "time" @@ -44,9 +43,7 @@ func TestIPFSBuild(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, ipfsCIDBase) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) done := ipfsRegistryUp(t, base) defer done() diff --git a/cmd/nerdctl/multi_platform_linux_test.go b/cmd/nerdctl/multi_platform_linux_test.go index cc76cae4f08..f46210b98ff 100644 --- a/cmd/nerdctl/multi_platform_linux_test.go +++ b/cmd/nerdctl/multi_platform_linux_test.go @@ -19,7 +19,6 @@ package main import ( "fmt" "io" - "os" "strings" "testing" @@ -68,9 +67,7 @@ func TestMultiPlatformBuildPush(t *testing.T) { RUN echo dummy `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, "--platform=amd64,arm64,linux/arm/v7", buildCtx).AssertOK() testMultiPlatformRun(base, imageName) @@ -97,9 +94,7 @@ func TestMultiPlatformBuildPushNoRun(t *testing.T) { CMD echo dummy `, testutil.AlpineImage) - buildCtx, err := createBuildContext(dockerfile) - assert.NilError(t, err) - defer os.RemoveAll(buildCtx) + buildCtx := createBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, "--platform=amd64,arm64,linux/arm/v7", buildCtx).AssertOK() testMultiPlatformRun(base, imageName) From 6958d07cc9461cf54802c78a5da41658e455c0ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 22:10:52 +0000 Subject: [PATCH 0368/1066] build(deps): bump actions/checkout from 4.1.1 to 4.1.2 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.1...v4.1.2) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 5e2f8297fe4..ac7d0eb6f87 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index af5c1baa700..de2c9162b32 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 - uses: actions/setup-go@v5 with: go-version: 1.21.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ca46ee68230..2f2abe4ebeb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -88,7 +88,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -118,7 +118,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: fetch-depth: 1 - name: Enable ipv4 and ipv6 forwarding @@ -194,7 +194,7 @@ jobs: ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -211,7 +211,7 @@ jobs: matrix: go-version: ["1.21.x", "1.22.x"] steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -226,7 +226,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 30 steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -263,7 +263,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -272,7 +272,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: repository: containerd/containerd ref: v1.7.14 @@ -295,7 +295,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 - uses: actions/cache@v4 with: path: /root/.vagrant.d From 046bfc06229896998ddb7fd867cf2b93454a10e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 22:56:20 +0000 Subject: [PATCH 0369/1066] build(deps): bump github.com/containernetworking/plugins Bumps [github.com/containernetworking/plugins](https://github.com/containernetworking/plugins) from 1.4.0 to 1.4.1. - [Release notes](https://github.com/containernetworking/plugins/releases) - [Commits](https://github.com/containernetworking/plugins/compare/v1.4.0...v1.4.1) --- updated-dependencies: - dependency-name: github.com/containernetworking/plugins dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 03c80d2345e..b666e51fed0 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/containerd/stargz-snapshotter/ipfs v0.15.1 github.com/containerd/typeurl/v2 v2.1.1 github.com/containernetworking/cni v1.1.2 - github.com/containernetworking/plugins v1.4.0 + github.com/containernetworking/plugins v1.4.1 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.4 @@ -82,7 +82,7 @@ require ( github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/go-jose/go-jose/v3 v3.0.3 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -134,8 +134,8 @@ require ( go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.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 + golang.org/x/mod v0.14.0 // indirect + golang.org/x/tools v0.17.0 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/grpc v1.62.0 // indirect diff --git a/go.sum b/go.sum index 567c41f345d..93d3040ed1c 100644 --- a/go.sum +++ b/go.sum @@ -69,8 +69,8 @@ github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9Fqctt github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ= 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/containernetworking/plugins v1.4.1 h1:+sJRRv8PKhLkXIl6tH1D7RMi+CbbHutDGU+ErLBORWA= +github.com/containernetworking/plugins v1.4.1/go.mod h1:n6FFGKcaY4o2o5msgu/UImtoC+fpQXM3076VHfHbj60= github.com/containers/ocicrypt v1.1.9 h1:2Csfba4jse85Raxk5HIyEk8OwZNjRvfkhEGijOjIdEM= github.com/containers/ocicrypt v1.1.9/go.mod h1:dTKx1918d8TDkxXvarscpNVY+lyPakPNFN4jwA9GBys= github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8= @@ -120,8 +120,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -246,13 +246,13 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs= -github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= +github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM= +github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -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/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= +github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= 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 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -366,8 +366,8 @@ 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/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.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= @@ -455,8 +455,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 4dbac7f878b4438e463a17041ddee39a26376bc6 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Mar 2024 17:12:05 +0900 Subject: [PATCH 0370/1066] update CNI plugins (1.4.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.0 | 2 -- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 diff --git a/Dockerfile b/Dockerfile index e62142fcbdc..68f062d1ce8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ # Basic deps ARG CONTAINERD_VERSION=v1.7.14 ARG RUNC_VERSION=v1.1.12 -ARG CNI_PLUGINS_VERSION=v1.4.0 +ARG CNI_PLUGINS_VERSION=v1.4.1 # Extra deps: Build ARG BUILDKIT_VERSION=v0.13.0 diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.0 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.0 deleted file mode 100644 index f78938c4f04..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.0 +++ /dev/null @@ -1,2 +0,0 @@ -c2485ddb3ffc176578ae30ae58137f0b88e50f7c7f2af7d53a569276b2949a33 cni-plugins-linux-amd64-v1.4.0.tgz -304d4389d5b732b7a73513d002c4895f731d030682d40653f411e10e39114194 cni-plugins-linux-arm64-v1.4.0.tgz diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 new file mode 100644 index 00000000000..0baa626f8ab --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 @@ -0,0 +1,2 @@ +1511f6c003ace805eafeb1132727791326283cff88a923d76329e1892bba7a10 cni-plugins-linux-amd64-v1.4.1.tgz +72644e13557cda8a5b39baf97fc5e93d23fdf7baba7700000e7e9efd8bdf9234 cni-plugins-linux-arm64-v1.4.1.tgz From 4917c16a45eedf878d05b01217a8dd050267e944 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Mar 2024 17:19:21 +0900 Subject: [PATCH 0371/1066] update RootlessKit (2.0.2) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 8 ++++---- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.1 | 6 ------ Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.2 | 6 ++++++ 4 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2f2abe4ebeb..59955e8838f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -162,7 +162,7 @@ jobs: target: test-integration-rootless - ubuntu: 20.04 containerd: v1.7.14 - rootlesskit: v2.0.1 + rootlesskit: v2.0.2 target: test-integration-rootless - ubuntu: 22.04 containerd: v1.7.14 @@ -170,7 +170,7 @@ jobs: target: test-integration-rootless - ubuntu: 22.04 containerd: main - rootlesskit: v2.0.1 + rootlesskit: v2.0.2 target: test-integration-rootless - ubuntu: 20.04 containerd: v1.6.30 @@ -178,7 +178,7 @@ jobs: target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 containerd: v1.7.14 - rootlesskit: v2.0.1 + rootlesskit: v2.0.2 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: v1.7.14 @@ -186,7 +186,7 @@ jobs: target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main - rootlesskit: v2.0.1 + rootlesskit: v2.0.2 target: test-integration-rootless-port-slirp4netns env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" diff --git a/Dockerfile b/Dockerfile index 68f062d1ce8..c54cdc6eda3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption ARG IMGCRYPT_VERSION=v1.1.9 # Extra deps: Rootless -ARG ROOTLESSKIT_VERSION=v2.0.1 +ARG ROOTLESSKIT_VERSION=v2.0.2 ARG SLIRP4NETNS_VERSION=v1.2.3 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.4.0 diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.1 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.1 deleted file mode 100644 index 6923226f370..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.1 +++ /dev/null @@ -1,6 +0,0 @@ -d250ae03e58541bce83842f8ec4f2190a2a55a437a3c9c156c1f20093522cca1 rootlesskit-aarch64.tar.gz -386745a013dc38681a2f797cb13d466f99c351d613c687ad4540449088deaa36 rootlesskit-armv7l.tar.gz -9569dc8efdb6dd07b8ce81c45f607b15f7bb41b55cfa7f15ad3cb6ae85061d82 rootlesskit-ppc64le.tar.gz -064b10c554c19a4d86934d825e37a97e83e3bc92ec70f0460c9533a383794804 rootlesskit-riscv64.tar.gz -9d03267f3a18c4d78055f877d5b0dc2e08e8d019d7b3e866e3361ef528ae0dda rootlesskit-s390x.tar.gz -6b1ecb61a48d85e6b41c4a67b81f6db47f626e010a481666a1859776b45439aa rootlesskit-x86_64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.2 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.2 new file mode 100644 index 00000000000..4e284401a0e --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.2 @@ -0,0 +1,6 @@ +4dafc86e1cbee2fbedac6822bf46e459d54ec998803d273f535b67a6e62edb30 rootlesskit-aarch64.tar.gz +c633c5e7f84d3390c4ebe8102af0cd8bdecd1f10e9fc007036636ef94d95b449 rootlesskit-armv7l.tar.gz +598a2c685cd383ba1abd3bf20a5c1bd55c283ceea1b3a9479c76f0fb96df75d5 rootlesskit-ppc64le.tar.gz +af9bbb79de33b0b3f901b3848341ae4b05ca4e0838f103044f082aab91f3b7f5 rootlesskit-riscv64.tar.gz +b1539a7f8059150f8dfdfc4de3a2714a199c09fdfe9c7670ce69824b8fdad7b9 rootlesskit-s390x.tar.gz +a218beb65d243183d13024a8b18fc08543e238ef38d306166e8375bde0efd57c rootlesskit-x86_64.tar.gz From ee2f8d64aa3bee5fb9f02644dbddb1b44b532dfa Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 13 Mar 2024 17:21:21 +0900 Subject: [PATCH 0372/1066] update Kubo (0.27.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c54cdc6eda3..2ed174ecb24 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ ARG BYPASS4NETNS_VERSION=v0.4.0 ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 # Extra deps: IPFS -ARG KUBO_VERSION=v0.26.0 +ARG KUBO_VERSION=v0.27.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug From 8c75ca70248cb18c7f84e9069d2424cf36742960 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 22:34:40 +0000 Subject: [PATCH 0373/1066] build(deps): bump docker/login-action from 3.0.0 to 3.1.0 Bumps [docker/login-action](https://github.com/docker/login-action) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v3.0.0...v3.1.0) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index ac7d0eb6f87..67e53885076 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -42,7 +42,7 @@ jobs: # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} if: github.event_name != 'pull_request' - uses: docker/login-action@v3.0.0 + uses: docker/login-action@v3.1.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} From 5e7857051bc9d64cb527ff93848b21a3e0d35b64 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 22:56:39 +0000 Subject: [PATCH 0374/1066] build(deps): bump github.com/containerd/accelerated-container-image Bumps [github.com/containerd/accelerated-container-image](https://github.com/containerd/accelerated-container-image) from 1.0.3 to 1.0.4. - [Release notes](https://github.com/containerd/accelerated-container-image/releases) - [Commits](https://github.com/containerd/accelerated-container-image/compare/v1.0.3...v1.0.4) --- updated-dependencies: - dependency-name: github.com/containerd/accelerated-container-image dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b666e51fed0..196d8f9159d 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Microsoft/hcsshim v0.12.0 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.3 + github.com/containerd/accelerated-container-image v1.0.4 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd v1.7.14 diff --git a/go.sum b/go.sum index 93d3040ed1c..440b295b299 100644 --- a/go.sum +++ b/go.sum @@ -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.3 h1:p6/1PI7EhwqjGdIyxq7TSfV1OmkZHd8m+gdDHqfARaU= -github.com/containerd/accelerated-container-image v1.0.3/go.mod h1:6+elKy0e2efrXQL9U8aaSFb3Ih9DVLsDizTKPKBCoSA= +github.com/containerd/accelerated-container-image v1.0.4 h1:2WDo44n7ohyDeqkynC1C8BboaZrrIIICGdmunz0jCXs= +github.com/containerd/accelerated-container-image v1.0.4/go.mod h1:iPvBVzJWG0WbfBEGk4Ap+HLWPaUWnx4toLpVkBafIDI= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= From d83f9f136928bf63abddd778ba772e4803ceacd0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 22:56:44 +0000 Subject: [PATCH 0375/1066] build(deps): bump github.com/containerd/imgcrypt from 1.1.9 to 1.1.10 Bumps [github.com/containerd/imgcrypt](https://github.com/containerd/imgcrypt) from 1.1.9 to 1.1.10. - [Release notes](https://github.com/containerd/imgcrypt/releases) - [Changelog](https://github.com/containerd/imgcrypt/blob/main/CHANGES) - [Commits](https://github.com/containerd/imgcrypt/compare/v1.1.9...v1.1.10) --- updated-dependencies: - dependency-name: github.com/containerd/imgcrypt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index b666e51fed0..ce6d9742745 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 - github.com/containerd/imgcrypt v1.1.9 + github.com/containerd/imgcrypt v1.1.10 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.13.8 github.com/containerd/platforms v0.1.1 @@ -75,7 +75,7 @@ require ( github.com/containerd/go-runc v1.0.0 // indirect github.com/containerd/ttrpc v1.2.3 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect - github.com/containers/ocicrypt v1.1.9 // indirect + github.com/containers/ocicrypt v1.1.10 // indirect github.com/distribution/reference v0.5.0 // indirect github.com/djherbis/times v1.5.0 // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect diff --git a/go.sum b/go.sum index 93d3040ed1c..d71099d8e7c 100644 --- a/go.sum +++ b/go.sum @@ -47,8 +47,8 @@ github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9 github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0= github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.1.9 h1:AnXt0sMq1Z2uIdaLt/fIHcMgtfVlFx6XpuaZzoC2XV0= -github.com/containerd/imgcrypt v1.1.9/go.mod h1:zEN6Nz5d5XIKgq06Tzk82YRlPZULKGSJ8fxhXhMwrYY= +github.com/containerd/imgcrypt v1.1.10 h1:vtyGzTna2wC5BSQcqHWgY4xsBLHWFWyecgK0+9Np8aE= +github.com/containerd/imgcrypt v1.1.10/go.mod h1:9eIPG34EQy+j00fr+4r0knul2MkYDKD2uzKkw8548aw= 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.8 h1:ChSXEn4iudHtFkKrRPOpjRkqhajyx8vuFw24r9Wo8cw= @@ -71,8 +71,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.1 h1:+sJRRv8PKhLkXIl6tH1D7RMi+CbbHutDGU+ErLBORWA= github.com/containernetworking/plugins v1.4.1/go.mod h1:n6FFGKcaY4o2o5msgu/UImtoC+fpQXM3076VHfHbj60= -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= From 0f9c8de41810a7e9fae213c02747525e8e678072 Mon Sep 17 00:00:00 2001 From: Alessio Greggi Date: Tue, 12 Mar 2024 19:55:28 +0100 Subject: [PATCH 0376/1066] feat(compose_up): add --abort-on-container-exit flag Signed-off-by: Alessio Greggi --- cmd/nerdctl/compose_up.go | 29 +++++++++++------- cmd/nerdctl/compose_up_linux_test.go | 45 ++++++++++++++++++++++++++++ docs/command-reference.md | 3 +- pkg/composer/logs.go | 21 +++++++++---- pkg/composer/up.go | 19 ++++++------ pkg/composer/up_service.go | 12 ++++++-- 6 files changed, 100 insertions(+), 29 deletions(-) diff --git a/cmd/nerdctl/compose_up.go b/cmd/nerdctl/compose_up.go index 4fe07ae11d7..b36e4ede0bb 100644 --- a/cmd/nerdctl/compose_up.go +++ b/cmd/nerdctl/compose_up.go @@ -36,7 +36,8 @@ func newComposeUpCommand() *cobra.Command { SilenceUsage: true, SilenceErrors: true, } - composeUpCommand.Flags().BoolP("detach", "d", false, "Detached mode: Run containers in the background") + composeUpCommand.Flags().Bool("abort-on-container-exit", false, "Stops all containers if any container was stopped. Incompatible with -d.") + composeUpCommand.Flags().BoolP("detach", "d", false, "Detached mode: Run containers in the background. Incompatible with --abort-on-container-exit.") composeUpCommand.Flags().Bool("no-build", false, "Don't build an image, even if it's missing.") composeUpCommand.Flags().Bool("no-color", false, "Produce monochrome output") composeUpCommand.Flags().Bool("no-log-prefix", false, "Don't print prefix in logs") @@ -57,6 +58,13 @@ func composeUpAction(cmd *cobra.Command, services []string) error { if err != nil { return err } + abortOnContainerExit, err := cmd.Flags().GetBool("abort-on-container-exit") + if detach && abortOnContainerExit { + return fmt.Errorf("--abort-on-container-exit flag is incompatible with flag --detach") + } + if err != nil { + return err + } noBuild, err := cmd.Flags().GetBool("no-build") if err != nil { return err @@ -121,15 +129,16 @@ func composeUpAction(cmd *cobra.Command, services []string) error { } uo := composer.UpOptions{ - Detach: detach, - NoBuild: noBuild, - NoColor: noColor, - NoLogPrefix: noLogPrefix, - ForceBuild: build, - IPFS: enableIPFS, - QuietPull: quietPull, - RemoveOrphans: removeOrphans, - Scale: scale, + AbortOnContainerExit: abortOnContainerExit, + Detach: detach, + NoBuild: noBuild, + NoColor: noColor, + NoLogPrefix: noLogPrefix, + ForceBuild: build, + IPFS: enableIPFS, + QuietPull: quietPull, + RemoveOrphans: removeOrphans, + Scale: scale, } return c.Up(ctx, uo, services) } diff --git a/cmd/nerdctl/compose_up_linux_test.go b/cmd/nerdctl/compose_up_linux_test.go index 0580e10b28d..ddbea597ef5 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/cmd/nerdctl/compose_up_linux_test.go @@ -33,6 +33,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" ) func TestComposeUp(t *testing.T) { @@ -585,3 +586,47 @@ services: psCmd.AssertOutContains(serviceRegular) psCmd.AssertOutNotContains(serviceProfiled) } + +func TestComposeUpAbortOnContainerExit(t *testing.T) { + base := testutil.NewBase(t) + serviceRegular := "regular" + serviceProfiled := "exited" + dockerComposeYAML := fmt.Sprintf(` +services: + %s: + image: %s + ports: + - 8080:80 + %s: + image: %s + entrypoint: /bin/sh -c "exit 1" +`, serviceRegular, testutil.NginxAlpineImage, serviceProfiled, testutil.BusyboxImage) + comp := testutil.NewComposeDir(t, dockerComposeYAML) + defer comp.CleanUp() + + // here we run 'compose up --abort-on-container-exit' command + base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "--abort-on-container-exit").AssertExitCode(1) + time.Sleep(3 * time.Second) + psCmd := base.Cmd("ps", "-a", "--format={{.Names}}", "--filter", "status=exited") + + psCmd.AssertOutContains(serviceRegular) + psCmd.AssertOutContains(serviceProfiled) + base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").AssertOK() + + // this time we run 'compose up' command without --abort-on-container-exit flag + base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "-d").AssertOK() + time.Sleep(3 * time.Second) + psCmd = base.Cmd("ps", "-a", "--format={{.Names}}", "--filter", "status=exited") + + // this time the regular service should not be listed in the output + psCmd.AssertOutNotContains(serviceRegular) + psCmd.AssertOutContains(serviceProfiled) + base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").AssertOK() + + // in this sub-test we are ensuring that flags '-d' and '--abort-on-container-exit' cannot be ran together + c := base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "-d", "--abort-on-container-exit") + expected := icmd.Expected{ + ExitCode: 1, + } + c.Assert(expected) +} diff --git a/docs/command-reference.md b/docs/command-reference.md index afe15b42797..dcdde45ec83 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1383,7 +1383,8 @@ Usage: `nerdctl compose up [OPTIONS] [SERVICE...]` Flags: -- :whale: `-d, --detach`: Detached mode: Run containers in the background +- :whale: `--abort-on-container-exit`: Stops all containers if any container was stopped. Incompatible with `-d`. +- :whale: `-d, --detach`: Detached mode: Run containers in the background. Incompatible with `--abort-on-container-exit`. - :whale: `--no-build`: Don't build an image, even if it's missing. - :whale: `--no-color`: Produce monochrome output - :whale: `--no-log-prefix`: Don't print prefix in logs diff --git a/pkg/composer/logs.go b/pkg/composer/logs.go index 21cb4fb5623..d9c0cb93a00 100644 --- a/pkg/composer/logs.go +++ b/pkg/composer/logs.go @@ -18,6 +18,7 @@ package composer import ( "context" + "fmt" "os" "os/exec" "os/signal" @@ -32,11 +33,12 @@ import ( ) type LogsOptions struct { - Follow bool - Timestamps bool - Tail string - NoColor bool - NoLogPrefix bool + AbortOnContainerExit bool + Follow bool + Timestamps bool + Tail string + NoColor bool + NoLogPrefix bool } func (c *Composer) Logs(ctx context.Context, lo LogsOptions, services []string) error { @@ -133,6 +135,7 @@ func (c *Composer) logs(ctx context.Context, containers []containerd.Container, signal.Notify(interruptChan, os.Interrupt) logsEOFMap := make(map[string]struct{}) // key: container name + var containerError error selectLoop: for { // Wait for Ctrl-C, or `nerdctl compose down` in another terminal @@ -144,6 +147,12 @@ selectLoop: if lo.Follow { // When `nerdctl logs -f` has exited, we can assume that the container has exited log.G(ctx).Infof("Container %q exited", containerName) + // In case a container has exited and the parameter --abort-on-container-exit, + // we break the loop and set an error, so we can exit the program with 1 + if lo.AbortOnContainerExit { + containerError = fmt.Errorf("container %q exited", containerName) + break selectLoop + } } else { log.G(ctx).Debugf("Logs for container %q reached EOF", containerName) } @@ -167,5 +176,5 @@ selectLoop: } } - return nil + return containerError } diff --git a/pkg/composer/up.go b/pkg/composer/up.go index eb2239476cd..4b6fc48a844 100644 --- a/pkg/composer/up.go +++ b/pkg/composer/up.go @@ -28,15 +28,16 @@ import ( ) type UpOptions struct { - Detach bool - NoBuild bool - NoColor bool - NoLogPrefix bool - ForceBuild bool - IPFS bool - QuietPull bool - RemoveOrphans bool - Scale map[string]uint64 // map of service name to replicas + AbortOnContainerExit bool + Detach bool + NoBuild bool + NoColor bool + NoLogPrefix bool + ForceBuild bool + IPFS bool + QuietPull bool + RemoveOrphans bool + Scale map[string]uint64 // map of service name to replicas } func (c *Composer) Up(ctx context.Context, uo UpOptions, services []string) error { diff --git a/pkg/composer/up_service.go b/pkg/composer/up_service.go index ce4a5d798b3..8838eced927 100644 --- a/pkg/composer/up_service.go +++ b/pkg/composer/up_service.go @@ -75,11 +75,17 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars return nil } + // this is used to stop containers in case --abort-on-container-exit flag is set. + // c.Logs returns an error, so we don't need Ctrl-c to reach the "Stopping containers (forcibly)" + if uo.AbortOnContainerExit { + defer c.stopContainersFromParsedServices(ctx, containers) + } log.G(ctx).Info("Attaching to logs") lo := LogsOptions{ - Follow: true, - NoColor: uo.NoColor, - NoLogPrefix: uo.NoLogPrefix, + AbortOnContainerExit: uo.AbortOnContainerExit, + Follow: true, + NoColor: uo.NoColor, + NoLogPrefix: uo.NoLogPrefix, } if err := c.Logs(ctx, lo, services); err != nil { return err From 9d60dbb03822d2e28d55f5e8adcc9f8bc58c3bf2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 01:02:36 +0000 Subject: [PATCH 0377/1066] build(deps): bump google.golang.org/protobuf from 1.32.0 to 1.33.0 Bumps google.golang.org/protobuf from 1.32.0 to 1.33.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4cde7fd9839..5f985ca7a63 100644 --- a/go.mod +++ b/go.mod @@ -139,6 +139,6 @@ require ( google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/grpc v1.62.0 // indirect - google.golang.org/protobuf v1.32.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 f80b6fa1b10..3cdcd950f99 100644 --- a/go.sum +++ b/go.sum @@ -489,8 +489,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= From 1c3713936ad2b74f35b35a1de40ec4a80b589ec0 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 14 Mar 2024 16:41:03 +0900 Subject: [PATCH 0378/1066] update imgcrypt (1.1.10) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2ed174ecb24..bf4b02fd969 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ ARG BUILDKIT_VERSION=v0.13.0 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption -ARG IMGCRYPT_VERSION=v1.1.9 +ARG IMGCRYPT_VERSION=v1.1.10 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v2.0.2 ARG SLIRP4NETNS_VERSION=v1.2.3 From 3b12a202aaca923d644239b67a082669bd7bcd30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 22:21:15 +0000 Subject: [PATCH 0379/1066] build(deps): bump docker/build-push-action from 5.2.0 to 5.3.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.2.0 to 5.3.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v5.2.0...v5.3.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 67e53885076..91b21f4d474 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -59,7 +59,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v5.2.0 + uses: docker/build-push-action@v5.3.0 with: context: . platforms: linux/amd64,linux/arm64 From 2122a714dca0ff4da6de1439abed66214622bf54 Mon Sep 17 00:00:00 2001 From: Jin Dong Date: Sun, 24 Mar 2024 13:56:40 -0700 Subject: [PATCH 0380/1066] update cosign image to latest release Signed-off-by: Jin Dong --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index bf4b02fd969..eb5bf9686f4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -288,7 +288,7 @@ WORKDIR /go/src/github.com/containerd/nerdctl VOLUME /tmp ENV CGO_ENABLED=0 # copy cosign binary for integration test -COPY --from=gcr.io/projectsigstore/cosign:v2.0.0@sha256:728944a9542a7235b4358c4ab2bcea855840e9d4b9594febca5c2207f5da7f38 /ko-app/cosign /usr/local/bin/cosign +COPY --from=gcr.io/projectsigstore/cosign:v2.2.3@sha256:8fc9cad121611e8479f65f79f2e5bea58949e8a87ffac2a42cb99cf0ff079ba7 /ko-app/cosign /usr/local/bin/cosign # installing soci for integration test ARG SOCI_SNAPSHOTTER_VERSION RUN fname="soci-snapshotter-${SOCI_SNAPSHOTTER_VERSION}-${TARGETOS:-linux}-${TARGETARCH:-amd64}.tar.gz" && \ From 8ae661e96554fe4d7f850536b1004b2de8d37888 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 00:49:28 +0000 Subject: [PATCH 0381/1066] build(deps): bump github.com/pelletier/go-toml/v2 from 2.1.1 to 2.2.0 Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.1.1 to 2.2.0. - [Release notes](https://github.com/pelletier/go-toml/releases) - [Changelog](https://github.com/pelletier/go-toml/blob/v2/.goreleaser.yaml) - [Commits](https://github.com/pelletier/go-toml/compare/v2.1.1...v2.2.0) --- updated-dependencies: - dependency-name: github.com/pelletier/go-toml/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 5f985ca7a63..ed30d16ed4d 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/runtime-spec v1.2.0 - github.com/pelletier/go-toml/v2 v2.1.1 + github.com/pelletier/go-toml/v2 v2.2.0 github.com/rootless-containers/bypass4netns v0.4.0 github.com/rootless-containers/rootlesskit/v2 v2.0.2 github.com/spf13/cobra v1.8.0 diff --git a/go.sum b/go.sum index 3cdcd950f99..deca1c94128 100644 --- a/go.sum +++ b/go.sum @@ -264,8 +264,8 @@ github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaL github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= +github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -295,8 +295,9 @@ github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 h1:lIOOH github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= 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= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -304,8 +305,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= From 70ee810a4738af420ac3743f6110229f1f096166 Mon Sep 17 00:00:00 2001 From: David Son Date: Fri, 22 Mar 2024 18:10:21 +0000 Subject: [PATCH 0382/1066] pkg/api/types: remove dependencies on nerdctl pkg/api/types had a dependency on netutil and imgutil packages. This would create issues with circular dependencies, e.g. in #2638 imgutil could not import types due to its dependency on netutil. This change moves NetworkCreateOptions and RemoteSnapshotterFlags into types to remove any future circular dependencies. This should also help us to clean our function headers, since we no longer need to explode the options struct into many different pieces. Signed-off-by: David Son --- cmd/nerdctl/image_pull.go | 3 +-- cmd/nerdctl/network_create.go | 25 +++++++++++-------------- pkg/api/types/image_types.go | 10 +++++++--- pkg/api/types/network_types.go | 15 +++++++++++---- pkg/cmd/compose/compose.go | 4 ++-- pkg/cmd/network/create.go | 10 +++++----- pkg/imgutil/imgutil.go | 5 +++-- pkg/imgutil/snapshotter.go | 17 +++++++---------- pkg/imgutil/snapshotter_test.go | 3 ++- pkg/ipfs/image.go | 3 ++- pkg/netutil/netutil.go | 18 +++--------------- 11 files changed, 54 insertions(+), 59 deletions(-) diff --git a/cmd/nerdctl/image_pull.go b/cmd/nerdctl/image_pull.go index 8c478fb68d9..ffb5f45e874 100644 --- a/cmd/nerdctl/image_pull.go +++ b/cmd/nerdctl/image_pull.go @@ -20,7 +20,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" - "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/spf13/cobra" ) @@ -113,7 +112,7 @@ func processPullCommandFlags(cmd *cobra.Command) (types.ImagePullOptions, error) Unpack: unpackStr, Quiet: quiet, IPFSAddress: ipfsAddressStr, - RFlags: imgutil.RemoteSnapshotterFlags{ + RFlags: types.RemoteSnapshotterFlags{ SociIndexDigest: sociIndexDigest, }, Stdout: cmd.OutOrStdout(), diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index 252984a45b4..c5fba0cac6b 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -22,7 +22,6 @@ import ( "github.com/containerd/containerd/identifiers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" - "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/spf13/cobra" @@ -100,18 +99,16 @@ func networkCreateAction(cmd *cobra.Command, args []string) error { } return network.Create(types.NetworkCreateOptions{ - GOptions: globalOptions, - CreateOptions: netutil.CreateOptions{ - Name: name, - Driver: driver, - Options: strutil.ConvertKVStringsToMap(opts), - IPAMDriver: ipamDriver, - IPAMOptions: strutil.ConvertKVStringsToMap(ipamOpts), - Subnets: subnets, - Gateway: gatewayStr, - IPRange: ipRangeStr, - Labels: labels, - IPv6: ipv6, - }, + GOptions: globalOptions, + Name: name, + Driver: driver, + Options: strutil.ConvertKVStringsToMap(opts), + IPAMDriver: ipamDriver, + IPAMOptions: strutil.ConvertKVStringsToMap(ipamOpts), + Subnets: subnets, + Gateway: gatewayStr, + IPRange: ipRangeStr, + Labels: labels, + IPv6: ipv6, }, cmd.OutOrStdout()) } diff --git a/pkg/api/types/image_types.go b/pkg/api/types/image_types.go index 16a6602b06e..084e5bedd78 100644 --- a/pkg/api/types/image_types.go +++ b/pkg/api/types/image_types.go @@ -18,8 +18,6 @@ package types import ( "io" - - "github.com/containerd/nerdctl/v2/pkg/imgutil" ) // ImageListOptions specifies options for `nerdctl image list`. @@ -181,6 +179,12 @@ type ImagePushOptions struct { AllowNondistributableArtifacts bool } +// RemoteSnapshotterFlags are used for pulling with remote snapshotters +// e.g. SOCI, stargz, overlaybd +type RemoteSnapshotterFlags struct { + SociIndexDigest string +} + // ImagePullOptions specifies options for `nerdctl (image) pull`. type ImagePullOptions struct { Stdout io.Writer @@ -198,7 +202,7 @@ type ImagePullOptions struct { // multiaddr of IPFS API (default uses $IPFS_PATH env variable if defined or local directory ~/.ipfs) IPFSAddress string // Flags to pass into remote snapshotters - RFlags imgutil.RemoteSnapshotterFlags + RFlags RemoteSnapshotterFlags } // ImageTagOptions specifies options for `nerdctl (image) tag`. diff --git a/pkg/api/types/network_types.go b/pkg/api/types/network_types.go index c8fa1cc5645..5cb26b3ea15 100644 --- a/pkg/api/types/network_types.go +++ b/pkg/api/types/network_types.go @@ -18,16 +18,23 @@ package types import ( "io" - - "github.com/containerd/nerdctl/v2/pkg/netutil" ) // NetworkCreateOptions specifies options for `nerdctl network create`. type NetworkCreateOptions struct { // GOptions is the global options GOptions GlobalCommandOptions - // CreateOptions is the option for creating network - CreateOptions netutil.CreateOptions + + Name string + Driver string + Options map[string]string + IPAMDriver string + IPAMOptions map[string]string + Subnets []string + Gateway string + IPRange string + Labels []string + IPv6 bool } // NetworkInspectOptions specifies options for `nerdctl network inspect`. diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 6517412088f..515a91a8a7f 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -125,7 +125,7 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op ipfsPath = dir } _, err = ipfs.EnsureImage(ctx, client, stdout, stderr, globalOptions.Snapshotter, scheme, ref, - pullMode, ocispecPlatforms, nil, quiet, ipfsPath, imgutil.RemoteSnapshotterFlags{}) + pullMode, ocispecPlatforms, nil, quiet, ipfsPath, types.RemoteSnapshotterFlags{}) return err } @@ -136,7 +136,7 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op } _, err = imgutil.EnsureImage(ctx, client, stdout, stderr, globalOptions.Snapshotter, ref, - pullMode, globalOptions.InsecureRegistry, globalOptions.HostsDir, ocispecPlatforms, nil, quiet, imgutil.RemoteSnapshotterFlags{}) + pullMode, globalOptions.InsecureRegistry, globalOptions.HostsDir, ocispecPlatforms, nil, quiet, types.RemoteSnapshotterFlags{}) return err } diff --git a/pkg/cmd/network/create.go b/pkg/cmd/network/create.go index f1dd42a1b6b..3115a127640 100644 --- a/pkg/cmd/network/create.go +++ b/pkg/cmd/network/create.go @@ -26,21 +26,21 @@ import ( ) func Create(options types.NetworkCreateOptions, stdout io.Writer) error { - if len(options.CreateOptions.Subnets) == 0 { - if options.CreateOptions.Gateway != "" || options.CreateOptions.IPRange != "" { + if len(options.Subnets) == 0 { + if options.Gateway != "" || options.IPRange != "" { return fmt.Errorf("cannot set gateway or ip-range without subnet, specify --subnet manually") } - options.CreateOptions.Subnets = []string{""} + options.Subnets = []string{""} } e, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath) if err != nil { return err } - net, err := e.CreateNetwork(options.CreateOptions) + net, err := e.CreateNetwork(options) if err != nil { if errdefs.IsAlreadyExists(err) { - return fmt.Errorf("network with name %s already exists", options.CreateOptions.Name) + return fmt.Errorf("network with name %s already exists", options.Name) } return err } diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 1608d642033..e51850920a9 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -32,6 +32,7 @@ import ( "github.com/containerd/imgcrypt" "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/errutil" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" @@ -103,7 +104,7 @@ func GetExistingImage(ctx context.Context, client *containerd.Client, snapshotte // # When insecure is set, skips verifying certs, and also falls back to HTTP when the registry does not speak HTTPS // // FIXME: this func has too many args -func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter, rawRef string, mode PullMode, insecure bool, hostsDirs []string, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, rFlags RemoteSnapshotterFlags) (*EnsuredImage, error) { +func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter, rawRef string, mode PullMode, insecure bool, hostsDirs []string, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, rFlags types.RemoteSnapshotterFlags) (*EnsuredImage, error) { switch mode { case "always", "missing", "never": // NOP @@ -194,7 +195,7 @@ func ResolveDigest(ctx context.Context, rawRef string, insecure bool, hostsDirs } // PullImage pulls an image using the specified resolver. -func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter string, resolver remotes.Resolver, ref string, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, rFlags RemoteSnapshotterFlags) (*EnsuredImage, error) { +func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter string, resolver remotes.Resolver, ref string, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, rFlags types.RemoteSnapshotterFlags) (*EnsuredImage, error) { ctx, done, err := client.WithLease(ctx) if err != nil { return nil, err diff --git a/pkg/imgutil/snapshotter.go b/pkg/imgutil/snapshotter.go index 46ff8b5f3ac..9fd30e72f8c 100644 --- a/pkg/imgutil/snapshotter.go +++ b/pkg/imgutil/snapshotter.go @@ -24,6 +24,7 @@ import ( "github.com/containerd/containerd/images" ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" "github.com/containerd/stargz-snapshotter/fs/source" ) @@ -48,14 +49,10 @@ var builtinRemoteSnapshotterOpts = map[string]snapshotterOpts{ snapshotterNameCvmfs: &remoteSnapshotterOpts{snapshotter: "cvmfs-snapshotter"}, } -type RemoteSnapshotterFlags struct { - SociIndexDigest string -} - // snapshotterOpts is used to update pull config // for different snapshotters type snapshotterOpts interface { - apply(config *pull.Config, ref string, rFlags RemoteSnapshotterFlags) + apply(config *pull.Config, ref string, rFlags types.RemoteSnapshotterFlags) isRemote() bool } @@ -77,14 +74,14 @@ func getSnapshotterOpts(snapshotter string) snapshotterOpts { // interface `snapshotterOpts.isRemote()` function type remoteSnapshotterOpts struct { snapshotter string - extraLabels func(func(images.Handler) images.Handler, RemoteSnapshotterFlags) func(images.Handler) images.Handler + extraLabels func(func(images.Handler) images.Handler, types.RemoteSnapshotterFlags) func(images.Handler) images.Handler } func (rs *remoteSnapshotterOpts) isRemote() bool { return true } -func (rs *remoteSnapshotterOpts) apply(config *pull.Config, ref string, rFlags RemoteSnapshotterFlags) { +func (rs *remoteSnapshotterOpts) apply(config *pull.Config, ref string, rFlags types.RemoteSnapshotterFlags) { h := ctdsnapshotters.AppendInfoHandlerWrapper(ref) if rs.extraLabels != nil { h = rs.extraLabels(h, rFlags) @@ -102,7 +99,7 @@ type defaultSnapshotterOpts struct { snapshotter string } -func (dsn *defaultSnapshotterOpts) apply(config *pull.Config, _ref string, rFlags RemoteSnapshotterFlags) { +func (dsn *defaultSnapshotterOpts) apply(config *pull.Config, _ref string, rFlags types.RemoteSnapshotterFlags) { config.RemoteOpts = append( config.RemoteOpts, containerd.WithPullSnapshotter(dsn.snapshotter)) @@ -113,10 +110,10 @@ func (dsn *defaultSnapshotterOpts) isRemote() bool { return false } -func stargzExtraLabels(f func(images.Handler) images.Handler, rFlags RemoteSnapshotterFlags) func(images.Handler) images.Handler { +func stargzExtraLabels(f func(images.Handler) images.Handler, rFlags types.RemoteSnapshotterFlags) func(images.Handler) images.Handler { return source.AppendExtraLabelsHandler(prefetchSize, f) } -func sociExtraLabels(f func(images.Handler) images.Handler, rFlags RemoteSnapshotterFlags) func(images.Handler) images.Handler { +func sociExtraLabels(f func(images.Handler) images.Handler, rFlags types.RemoteSnapshotterFlags) func(images.Handler) images.Handler { return socisource.AppendDefaultLabelsHandlerWrapper(rFlags.SociIndexDigest, f) } diff --git a/pkg/imgutil/snapshotter_test.go b/pkg/imgutil/snapshotter_test.go index f09da014012..e719b8086b0 100644 --- a/pkg/imgutil/snapshotter_test.go +++ b/pkg/imgutil/snapshotter_test.go @@ -23,6 +23,7 @@ import ( "github.com/containerd/containerd" ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -93,7 +94,7 @@ func sameOpts(want snapshotterOpts) func(*testing.T, snapshotterOpts) { func getAndApplyRemoteOpts(t *testing.T, sn string) *containerd.RemoteContext { config := &pull.Config{} snOpts := getSnapshotterOpts(sn) - rFlags := RemoteSnapshotterFlags{} + rFlags := types.RemoteSnapshotterFlags{} snOpts.apply(config, testRef, rFlags) rc := &containerd.RemoteContext{} diff --git a/pkg/ipfs/image.go b/pkg/ipfs/image.go index ffe2db4eb34..41e1b40f6cc 100644 --- a/pkg/ipfs/image.go +++ b/pkg/ipfs/image.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/containerd/images/converter" "github.com/containerd/containerd/remotes" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" @@ -40,7 +41,7 @@ import ( const ipfsPathEnv = "IPFS_PATH" // EnsureImage pull the specified image from IPFS. -func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter string, scheme string, ref string, mode imgutil.PullMode, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, ipfsPath string, rFlags imgutil.RemoteSnapshotterFlags) (*imgutil.EnsuredImage, error) { +func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter string, scheme string, ref string, mode imgutil.PullMode, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, ipfsPath string, rFlags types.RemoteSnapshotterFlags) (*imgutil.EnsuredImage, error) { switch mode { case "always", "missing", "never": // NOP diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 1a29d7dc67d..5691e27e8d6 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -34,6 +34,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/namespaces" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/lockutil" "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" @@ -225,20 +226,7 @@ type cniNetworkConfig struct { Plugins []CNIPlugin `json:"plugins"` } -type CreateOptions struct { - Name string - Driver string - Options map[string]string - IPAMDriver string - IPAMOptions map[string]string - Subnets []string - Gateway string - IPRange string - Labels []string - IPv6 bool -} - -func (e *CNIEnv) CreateNetwork(opts CreateOptions) (*NetworkConfig, error) { //nolint:revive +func (e *CNIEnv) CreateNetwork(opts types.NetworkCreateOptions) (*NetworkConfig, error) { //nolint:revive var net *NetworkConfig netMap, err := e.NetworkMap() if err != nil { @@ -350,7 +338,7 @@ func (e *CNIEnv) createDefaultNetworkConfig() error { if _, err := os.Stat(filename); err == nil { return fmt.Errorf("already found existing network config at %q, cannot create new network named %q", filename, DefaultNetworkName) } - opts := CreateOptions{ + opts := types.NetworkCreateOptions{ Name: DefaultNetworkName, Driver: DefaultNetworkName, Subnets: []string{DefaultCIDR}, From c1c7e2519b50b328cd26fa8076ea5c93b8f0c71c Mon Sep 17 00:00:00 2001 From: Jin Dong Date: Sun, 24 Mar 2024 14:57:53 -0700 Subject: [PATCH 0383/1066] not check return of rmi in pushImageToIPFS Signed-off-by: Jin Dong --- cmd/nerdctl/ipfs_linux_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nerdctl/ipfs_linux_test.go b/cmd/nerdctl/ipfs_linux_test.go index 981894f9978..c0a31842cad 100644 --- a/cmd/nerdctl/ipfs_linux_test.go +++ b/cmd/nerdctl/ipfs_linux_test.go @@ -159,7 +159,7 @@ func TestIPFSWithLazyPullingCommit(t *testing.T) { func pushImageToIPFS(t *testing.T, base *testutil.Base, name string, opts ...string) string { base.Cmd("pull", name).AssertOK() ipfsCID := cidOf(t, base.Cmd(append([]string{"push"}, append(opts, "ipfs://"+name)...)...).OutLines()) - base.Cmd("rmi", name).AssertOK() + base.Cmd("rmi", name).Run() return ipfsCID } From e7608c8bb5245dbc9e091127ee5eec052878829a Mon Sep 17 00:00:00 2001 From: Jin Dong Date: Sun, 24 Mar 2024 22:42:25 -0700 Subject: [PATCH 0384/1066] deflake TestImageConvertEStargz Signed-off-by: Jin Dong --- cmd/nerdctl/image_convert_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/nerdctl/image_convert_test.go b/cmd/nerdctl/image_convert_test.go index 2984c9a1369..1f308f2bdc0 100644 --- a/cmd/nerdctl/image_convert_test.go +++ b/cmd/nerdctl/image_convert_test.go @@ -28,7 +28,6 @@ func TestImageConvertEStargz(t *testing.T) { t.Skip("no windows support yet") } testutil.DockerIncompatible(t) - t.Parallel() base := testutil.NewBase(t) convertedImage := testutil.Identifier(t) + ":esgz" base.Cmd("rmi", convertedImage).Run() From ea7769fcf20ad2209239ca62d1b80140205aa242 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 07:45:41 +0000 Subject: [PATCH 0385/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.12.0 to 0.12.1 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.12.0 to 0.12.1. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.0...v0.12.1) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ed30d16ed4d..aa4ed44e828 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ 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.12.0 + github.com/Microsoft/hcsshim v0.12.1 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.4 diff --git a/go.sum b/go.sum index deca1c94128..26953d530de 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 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.12.0 h1:rbICA+XZFwrBef2Odk++0LjFvClNCJGRK+fsrP254Ts= -github.com/Microsoft/hcsshim v0.12.0/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= +github.com/Microsoft/hcsshim v0.12.1 h1:ahSMCguNOQMvTV7wWLknLhpieyqA2hUyEb3j6R+6B/c= +github.com/Microsoft/hcsshim v0.12.1/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= 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= From c0d7b734cde2b73a8db0686dafc21bce79cec8a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 17:35:03 +0000 Subject: [PATCH 0386/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.8 to 0.13.11. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.8...v0.13.11) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index aa4ed44e828..d8dbcadb920 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.10 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.8 + github.com/containerd/nydus-snapshotter v0.13.11 github.com/containerd/platforms v0.1.1 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 diff --git a/go.sum b/go.sum index 26953d530de..4c85204ba1b 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,8 @@ github.com/containerd/imgcrypt v1.1.10 h1:vtyGzTna2wC5BSQcqHWgY4xsBLHWFWyecgK0+9 github.com/containerd/imgcrypt v1.1.10/go.mod h1:9eIPG34EQy+j00fr+4r0knul2MkYDKD2uzKkw8548aw= 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.8 h1:ChSXEn4iudHtFkKrRPOpjRkqhajyx8vuFw24r9Wo8cw= -github.com/containerd/nydus-snapshotter v0.13.8/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= +github.com/containerd/nydus-snapshotter v0.13.11 h1:0euz1viJ0/4sZ5P0GP28wKrd+m0YqKRQcM6GZjuSKZk= +github.com/containerd/nydus-snapshotter v0.13.11/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= github.com/containerd/platforms v0.1.1 h1:gp0xXBoY+1CjH54gJDon0kBjIbK2C4XSX1BGwP5ptG0= github.com/containerd/platforms v0.1.1/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= github.com/containerd/stargz-snapshotter v0.15.1 h1:fpsP4kf/Z4n2EYnU0WT8ZCE3eiKDwikDhL6VwxIlgeA= From 3809ec53a93be84ab63bcb557d0b0c72cab73c85 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 26 Mar 2024 02:38:48 +0900 Subject: [PATCH 0387/1066] CI: FreeBSD: use Go 1.22 Signed-off-by: Akihiro Suda --- Vagrantfile.freebsd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Vagrantfile.freebsd b/Vagrantfile.freebsd index 4fe7ef0000d..f3a2e4a4d4a 100644 --- a/Vagrantfile.freebsd +++ b/Vagrantfile.freebsd @@ -36,7 +36,9 @@ Vagrant.configure("2") do |config| sh.inline = <<~SHELL #!/usr/bin/env bash set -eux -o pipefail - pkg install -y go containerd runj + # `pkg install go` still installs Go 1.20 (March 2024) + pkg install -y go122 containerd runj + ln -s go122 /usr/local/bin/go cd /vagrant go install ./cmd/nerdctl SHELL From da2f576f4d2a17e28c8b1b53573a01993db1e3dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 22:10:20 +0000 Subject: [PATCH 0388/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 24.0.7+incompatible to 26.0.0+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v24.0.7...v26.0.0) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: Akihiro Suda --- go.mod | 5 +++-- go.sum | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index d8dbcadb920..ccc4ba13343 100644 --- a/go.mod +++ b/go.mod @@ -28,8 +28,8 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.4 - github.com/docker/cli v24.0.7+incompatible - github.com/docker/docker v24.0.7+incompatible + github.com/docker/cli v26.0.0+incompatible + github.com/docker/docker v26.0.0+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.0 @@ -101,6 +101,7 @@ require ( github.com/miekg/pkcs11 v1.1.1 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/sys/mountinfo v0.7.1 // indirect github.com/moby/sys/sequential v0.5.0 // indirect diff --git a/go.sum b/go.sum index 4c85204ba1b..864d8ad48b4 100644 --- a/go.sum +++ b/go.sum @@ -89,10 +89,10 @@ github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK github.com/distribution/reference v0.5.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= -github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= -github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I= +github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU= +github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -206,6 +206,8 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= +github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= From 6f83a71d2cc0627cbe911887cf25befaf542ab4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Mar 2024 22:27:06 +0000 Subject: [PATCH 0389/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.12.1 to 0.12.2 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.12.1 to 0.12.2. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.1...v0.12.2) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ccc4ba13343..cac80dc7a83 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ 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.12.1 + github.com/Microsoft/hcsshim v0.12.2 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.4 diff --git a/go.sum b/go.sum index 864d8ad48b4..7a4a644131a 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 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.12.1 h1:ahSMCguNOQMvTV7wWLknLhpieyqA2hUyEb3j6R+6B/c= -github.com/Microsoft/hcsshim v0.12.1/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= +github.com/Microsoft/hcsshim v0.12.2 h1:AcXy+yfRvrx20g9v7qYaJv5Rh+8GaHOS6b8G6Wx/nKs= +github.com/Microsoft/hcsshim v0.12.2/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= 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= From 9ba9ddca915241bcf5cd1bd357212308f0552289 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 31 Mar 2024 20:01:01 +0900 Subject: [PATCH 0390/1066] update BuildKit (0.13.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.1 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.1 diff --git a/Dockerfile b/Dockerfile index eb5bf9686f4..b42709b02be 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.12 ARG CNI_PLUGINS_VERSION=v1.4.1 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.13.0 +ARG BUILDKIT_VERSION=v0.13.1 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0 deleted file mode 100644 index 8f1b1c5fc18..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.0 +++ /dev/null @@ -1,2 +0,0 @@ -0893f55180c3da895ad998af25305f32413676a72a36b4372607ff7396f607e8 buildkit-v0.13.0.linux-amd64.tar.gz -265f9756102de5fe3b8f299b7e96a9ef4ff69763805642676129c2713477071d buildkit-v0.13.0.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.1 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.1 new file mode 100644 index 00000000000..df2b9d75ce8 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.1 @@ -0,0 +1,2 @@ +5d4a6ef438851d7a0b22d17c7e806651c24c0982ddd6af8c02117fca84f167ec buildkit-v0.13.1.linux-amd64.tar.gz +9e1478af43ba7ac6635cae30a8dda3ebce4dca70a8def939ac64ee395d03d647 buildkit-v0.13.1.linux-arm64.tar.gz From f42ab2ff7fa0daf356b9fab7dd0ea0657cc65576 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 31 Mar 2024 18:23:27 +0900 Subject: [PATCH 0391/1066] Implement `nerdctl run --annotation` (introduced in Docker v24) An OCI runtime (as well as `nerdctl internal oci-hook`) may consume an annotation and behave differently. e.g., https://github.com/opencontainers/runc/blob/v1.1.12/docs/systemd.md#auxiliary-properties nerdctl v1: - `nerdctl run --annotation` was not implemented. - `nerdctl run --label` is set as a containerd label and an OCI annotation. nerdctl v2: - `nerdctl run --annotation` is only set as an OCI annotation. - `nerdctl run --label` is only set as a containerd label. A label with the `nerdctl/` prefix can no longer be set manually, with an exception for `nerdctl/bypass4netns`. The `nerdctl/bypass4netns` label is still allowed and is propagated to an OCI annotation, for sake of compatibility. Docker v23: - `docker run --annotation` was not implemented. - `docker run --label` is only set as a Docker label. Docker v24 (implemented in docker/cli PR 4156, moby/moby PR 45025): - `docker run --annotation` is only set as an OCI annotation. - `docker run --label` is only set as a Docker label. (In a nutshell, `--annotation` may change the behavior, while `--label` should not.) Signed-off-by: Akihiro Suda --- README.md | 2 +- cmd/nerdctl/compose_up_linux_test.go | 4 +-- cmd/nerdctl/container_create.go | 4 +++ cmd/nerdctl/container_run.go | 7 ++-- docs/command-reference.md | 3 +- docs/rootless.md | 8 +++-- .../rootless/containerd-rootless-setuptool.sh | 2 +- pkg/annotations/annotations.go | 34 +++++++++++++++++++ pkg/api/types/container_types.go | 3 ++ pkg/bypass4netnsutil/bypass4netnsutil.go | 10 +++--- pkg/cmd/container/create.go | 22 ++++++++++-- pkg/cmd/container/run_linux.go | 7 ++-- pkg/composer/serviceparser/serviceparser.go | 9 +++++ pkg/labels/labels.go | 13 +------ 14 files changed, 94 insertions(+), 34 deletions(-) create mode 100644 pkg/annotations/annotations.go diff --git a/README.md b/README.md index 4b5a02aba72..36d9bbe1897 100644 --- a/README.md +++ b/README.md @@ -189,7 +189,7 @@ Major: - [P2P image distribution using IPFS](./docs/ipfs.md): `nerdctl run ipfs://CID` . P2P image distribution (IPFS) is completely optional. Your host is NOT connected to any P2P network, unless you opt in to [install and run IPFS daemon](https://docs.ipfs.io/install/). - [Cosign integration](./docs/cosign.md): `nerdctl pull --verify=cosign` and `nerdctl push --sign=cosign`, and [in Compose](./docs/cosign.md#cosign-in-compose) -- [Accelerated rootless containers using bypass4netns](./docs/rootless.md): `nerdctl run --label nerdctl/bypass4netns=true` +- [Accelerated rootless containers using bypass4netns](./docs/rootless.md): `nerdctl run --annotation nerdctl/bypass4netns=true` Minor: diff --git a/cmd/nerdctl/compose_up_linux_test.go b/cmd/nerdctl/compose_up_linux_test.go index ddbea597ef5..95dc761c54b 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/cmd/nerdctl/compose_up_linux_test.go @@ -523,7 +523,7 @@ services: WORDPRESS_DB_NAME: exampledb volumes: - wordpress:/var/www/html - labels: + annotations: - nerdctl/bypass4netns=1 db: @@ -536,7 +536,7 @@ services: MYSQL_RANDOM_ROOT_PASSWORD: '1' volumes: - db:/var/lib/mysql - labels: + annotations: - nerdctl/bypass4netns=1 volumes: diff --git a/cmd/nerdctl/container_create.go b/cmd/nerdctl/container_create.go index de99a782671..9d94f068d9e 100644 --- a/cmd/nerdctl/container_create.go +++ b/cmd/nerdctl/container_create.go @@ -337,6 +337,10 @@ func processContainerCreateOptions(cmd *cobra.Command) (opt types.ContainerCreat if err != nil { return } + opt.Annotations, err = cmd.Flags().GetStringArray("annotation") + if err != nil { + return + } opt.CidFile, err = cmd.Flags().GetString("cidfile") if err != nil { return diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 077332d447c..036b1f57da6 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -23,6 +23,7 @@ import ( "github.com/containerd/console" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/annotations" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -230,8 +231,10 @@ func setCreateFlags(cmd *cobra.Command) { cmd.Flags().String("name", "", "Assign a name to the container") // label needs to be StringArray, not StringSlice, to prevent "foo=foo1,foo2" from being split to {"foo=foo1", "foo2"} cmd.Flags().StringArrayP("label", "l", nil, "Set metadata on container") - cmd.RegisterFlagCompletionFunc("label", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return labels.ShellCompletions, cobra.ShellCompDirectiveNoFileComp + // annotation needs to be StringArray, not StringSlice, to prevent "foo=foo1,foo2" from being split to {"foo=foo1", "foo2"} + cmd.Flags().StringArray("annotation", nil, "Add an annotation to the container (passed through to the OCI runtime)") + cmd.RegisterFlagCompletionFunc("annotation", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return annotations.ShellCompletions, cobra.ShellCompDirectiveNoFileComp }) // label-file is defined as StringSlice, not StringArray, to allow specifying "--env-file=FILE1,FILE2" (compatible with Podman) diff --git a/docs/command-reference.md b/docs/command-reference.md index dcdde45ec83..3c3371c787c 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -298,8 +298,9 @@ Env flags: Metadata flags: - :whale: :blue_square: `--name`: Assign a name to the container -- :whale: :blue_square: `-l, --label`: Set meta data on a container +- :whale: :blue_square: `-l, --label`: Set meta data on a container (Not passed through the OCI runtime since nerdctl v2.0, with an exception for `nerdctl/bypass4netns`) - :whale: :blue_square: `--label-file`: Read in a line delimited file of labels +- :whale: :blue_square: `--annotation`: Add an annotation to the container (passed through to the OCI runtime) - :whale: :blue_square: `--cidfile`: Write the container ID to the file - :nerd_face: `--pidfile`: file path to write the task's pid. The CLI syntax conforms to Podman convention. diff --git a/docs/rootless.md b/docs/rootless.md index c8c738df06c..5b9333ebabc 100644 --- a/docs/rootless.md +++ b/docs/rootless.md @@ -121,11 +121,15 @@ The performance benchmark with iperf3 on Ubuntu 21.10 on Hyper-V VM is shown bel This benchmark can be reproduced with [https://github.com/rootless-containers/bypass4netns/blob/f009d96139e9e38ce69a2ea8a9a746349bad273c/Vagrantfile](https://github.com/rootless-containers/bypass4netns/blob/f009d96139e9e38ce69a2ea8a9a746349bad273c/Vagrantfile) -Acceleration with bypass4netns is available with `--label nerdctl/bypass4netns=true`. You also need to have `bypass4netnsd` (bypass4netns daemon) to be running. +Acceleration with bypass4netns is available with: +- `--annotation nerdctl/bypass4netns=true` (for nerdctl v2.0 and later) +- `--label nerdctl/bypass4netns=true` (deprecated form, used in nerdctl prior to v2.0). + +You also need to have `bypass4netnsd` (bypass4netns daemon) to be running. Example ```console $ containerd-rootless-setuptool.sh install-bypass4netnsd -$ nerdctl run -it --rm -p 8080:80 --label nerdctl/bypass4netns=true alpine +$ nerdctl run -it --rm -p 8080:80 --annotation nerdctl/bypass4netns=true alpine ``` More detail is available at [https://github.com/rootless-containers/bypass4netns/blob/master/README.md](https://github.com/rootless-containers/bypass4netns/blob/master/README.md) diff --git a/extras/rootless/containerd-rootless-setuptool.sh b/extras/rootless/containerd-rootless-setuptool.sh index 9b31d5efe2c..9b005c7cce0 100755 --- a/extras/rootless/containerd-rootless-setuptool.sh +++ b/extras/rootless/containerd-rootless-setuptool.sh @@ -365,7 +365,7 @@ cmd_entrypoint_install_bypass4netnsd() { [Install] WantedBy=default.target EOT - INFO "To use bypass4netnsd, set the \"nerdctl/bypass4netns=true\" label on containers, e.g., \`nerdctl run --label nerdctl/bypass4netns=true\`" + INFO "To use bypass4netnsd, set the \"nerdctl/bypass4netns=true\" annotation on containers, e.g., \`nerdctl run --annotation nerdctl/bypass4netns=true\`" } # CLI subcommand: "install-fuse-overlayfs" diff --git a/pkg/annotations/annotations.go b/pkg/annotations/annotations.go new file mode 100644 index 00000000000..751d231541f --- /dev/null +++ b/pkg/annotations/annotations.go @@ -0,0 +1,34 @@ +/* + 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 annotations defines OCI annotations +package annotations + +const ( + // Prefix is the common prefix of nerdctl annotations + Prefix = "nerdctl/" + + // Bypass4netns is the flag for acceleration with bypass4netns + // Boolean value which can be parsed with strconv.ParseBool() is required. + // (like "nerdctl/bypass4netns=true" or "nerdctl/bypass4netns=false") + Bypass4netns = Prefix + "bypass4netns" +) + +var ShellCompletions = []string{ + Bypass4netns + "=true", + Bypass4netns + "=false", + // Other annotations should not be set via CLI +} diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index f4c4f6f1b16..60e5da4c373 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -217,9 +217,12 @@ type ContainerCreateOptions struct { // Name assign a name to the container Name string // Label set meta data on a container + // (not passed through to the OCI runtime since nerdctl v2.0, with an exception for "nerdctl/bypass4netns") Label []string // LabelFile read in a line delimited file of labels LabelFile []string + // Annotations set meta data on a container (passed through to the OCI runtime) + Annotations []string // CidFile write the container ID to the file CidFile string // PidFile specifies the file path to write the task's pid. The CLI syntax conforms to Podman convention. diff --git a/pkg/bypass4netnsutil/bypass4netnsutil.go b/pkg/bypass4netnsutil/bypass4netnsutil.go index 133102ae98f..2dd0093a35a 100644 --- a/pkg/bypass4netnsutil/bypass4netnsutil.go +++ b/pkg/bypass4netnsutil/bypass4netnsutil.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" - "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/annotations" "github.com/opencontainers/runtime-spec/specs-go" b4nnoci "github.com/rootless-containers/bypass4netns/pkg/oci" ) @@ -46,8 +46,8 @@ func generateSecurityOpt(listenerPath string) (oci.SpecOpts, error) { return opt, nil } -func GenerateBypass4netnsOpts(securityOptsMaps map[string]string, labelMaps map[string]string, id string) ([]oci.SpecOpts, error) { - b4nn, ok := labelMaps[labels.Bypass4netns] +func GenerateBypass4netnsOpts(securityOptsMaps map[string]string, annotationsMap map[string]string, id string) ([]oci.SpecOpts, error) { + b4nn, ok := annotationsMap[annotations.Bypass4netns] if !ok { return nil, nil } @@ -133,8 +133,8 @@ func GetPidFilePathByID(id string) (string, error) { return socketPath, nil } -func IsBypass4netnsEnabled(annotations map[string]string) (bool, error) { - if b4nn, ok := annotations[labels.Bypass4netns]; ok { +func IsBypass4netnsEnabled(annotationsMap map[string]string) (bool, error) { + if b4nn, ok := annotationsMap[annotations.Bypass4netns]; ok { b4nnEnable, err := strconv.ParseBool(b4nn) if err != nil { return false, err diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 2045b820c44..eb680fd0a6b 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -35,6 +35,7 @@ import ( "github.com/containerd/containerd/oci" gocni "github.com/containerd/go-cni" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/annotations" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -276,13 +277,15 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa } } + // TODO: abolish internal labels and only use annotations ilOpt, err := withInternalLabels(internalLabels) if err != nil { return nil, nil, err } cOpts = append(cOpts, ilOpt) - opts = append(opts, propagateContainerdLabelsToOCIAnnotations()) + opts = append(opts, propagateInternalContainerdLabelsToOCIAnnotations(), + oci.WithAnnotations(strutil.ConvertKVStringsToMap(options.Annotations))) var s specs.Spec spec := containerd.WithSpec(&s, opts...) @@ -506,6 +509,13 @@ func withContainerLabels(label, labelFile []string) ([]containerd.NewContainerOp if err != nil { return nil, err } + for k := range labelMap { + if strings.HasPrefix(k, annotations.Bypass4netns) { + log.L.Warnf("Label %q is deprecated, use an annotation instead", k) + } else if strings.HasPrefix(k, labels.Prefix) { + return nil, fmt.Errorf("internal label %q must not be specified manually", k) + } + } o := containerd.WithAdditionalContainerLabels(labelMap) return []containerd.NewContainerOpts{o}, nil } @@ -704,9 +714,15 @@ func processeds(mountPoints []dockercompat.MountPoint) []*mountutil.Processed { return result } -func propagateContainerdLabelsToOCIAnnotations() oci.SpecOpts { +func propagateInternalContainerdLabelsToOCIAnnotations() oci.SpecOpts { return func(ctx context.Context, oc oci.Client, c *containers.Container, s *oci.Spec) error { - return oci.WithAnnotations(c.Labels)(ctx, oc, c, s) + allowed := make(map[string]string) + for k, v := range c.Labels { + if strings.Contains(k, labels.Prefix) { + allowed[k] = v + } + } + return oci.WithAnnotations(allowed)(ctx, oc, c, s) } } diff --git a/pkg/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index 83773477782..89fdb73cd8d 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -59,10 +59,7 @@ func setPlatformOptions(ctx context.Context, client *containerd.Client, id, uts } opts = append(opts, cgOpts...) - labelsMap, err := readKVStringsMapfFromLabel(options.Label, options.LabelFile) - if err != nil { - return nil, err - } + annotations := strutil.ConvertKVStringsToMap(options.Annotations) capOpts, err := generateCapOpts( strutil.DedupeStrSlice(options.CapAdd), @@ -78,7 +75,7 @@ func setPlatformOptions(ctx context.Context, client *containerd.Client, id, uts } opts = append(opts, secOpts...) - b4nnOpts, err := bypass4netnsutil.GenerateBypass4netnsOpts(securityOptsMaps, labelsMap, id) + b4nnOpts, err := bypass4netnsutil.GenerateBypass4netnsOpts(securityOptsMaps, annotations, id) if err != nil { return nil, err } diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index 60dd5ee8d86..05c829d4212 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -54,6 +54,7 @@ const Separator = "-" func warnUnknownFields(svc types.ServiceConfig) { if unknown := reflectutil.UnknownNonEmptyFields(&svc, "Name", + "Annotations", "Build", "BlkioConfig", "CapAdd", @@ -477,6 +478,14 @@ func newContainer(project *types.Project, parsed *Service, i int) (*Container, e "--pull=never", // because image will be ensured before running replicas with `nerdctl run`. } + for k, v := range svc.Annotations { + if v == "" { + c.RunArgs = append(c.RunArgs, fmt.Sprintf("--annotation=%s", k)) + } else { + c.RunArgs = append(c.RunArgs, fmt.Sprintf("--annotation=%s=%s", k, v)) + } + } + if svc.BlkioConfig != nil && svc.BlkioConfig.Weight != 0 { c.RunArgs = append(c.RunArgs, fmt.Sprintf("--blkio-weight=%d", svc.BlkioConfig.Weight)) } diff --git a/pkg/labels/labels.go b/pkg/labels/labels.go index 40e82971fd4..d88aee02a7d 100644 --- a/pkg/labels/labels.go +++ b/pkg/labels/labels.go @@ -15,7 +15,7 @@ */ // Package labels defines labels that are set to containerd containers as labels. -// The labels are also passed to OCI containers as annotations. +// The labels defined in this package are also passed to OCI containers as annotations. package labels const ( @@ -79,11 +79,6 @@ const ( // Mounts is the mount points for the container. Mounts = Prefix + "mounts" - // Bypass4netns is the flag for acceleration with bypass4netns - // Boolean value which can be parsed with strconv.ParseBool() is required. - // (like "nerdctl/bypass4netns=true" or "nerdctl/bypass4netns=false") - Bypass4netns = Prefix + "bypass4netns" - // StopTimeout is seconds to wait for stop a container. StopTimeout = Prefix + "stop-timeout" @@ -106,9 +101,3 @@ const ( // (like "nerdctl/default-network=true" or "nerdctl/default-network=false") NerdctlDefaultNetwork = Prefix + "default-network" ) - -var ShellCompletions = []string{ - Bypass4netns + "=true", - Bypass4netns + "=false", - // Other labels should not be set via CLI -} From fc4c8e788dd4b05f9ea3111ebe0e5d8515c2decb Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 31 Mar 2024 21:26:13 +0900 Subject: [PATCH 0392/1066] annotations: add `nerdctl/bypass4netns-ignore-subnets` (`[]string`) For experiments of additional `bypass4netns --ignore` Signed-off-by: Akihiro Suda --- pkg/annotations/annotations.go | 6 +++++- pkg/bypass4netnsutil/bypass.go | 20 +++++++++++++++----- pkg/ocihook/ocihook.go | 4 ++-- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/pkg/annotations/annotations.go b/pkg/annotations/annotations.go index 751d231541f..e89648d7abb 100644 --- a/pkg/annotations/annotations.go +++ b/pkg/annotations/annotations.go @@ -25,10 +25,14 @@ const ( // Boolean value which can be parsed with strconv.ParseBool() is required. // (like "nerdctl/bypass4netns=true" or "nerdctl/bypass4netns=false") Bypass4netns = Prefix + "bypass4netns" + + // Bypass4netnsIgnoreSubnets is a JSON of []string that is appended to + // the `bypass4netns --ignore` list. + Bypass4netnsIgnoreSubnets = Bypass4netns + "-ignore-subnets" ) var ShellCompletions = []string{ Bypass4netns + "=true", Bypass4netns + "=false", - // Other annotations should not be set via CLI + Bypass4netnsIgnoreSubnets + "=", } diff --git a/pkg/bypass4netnsutil/bypass.go b/pkg/bypass4netnsutil/bypass.go index 6dfb4db3c86..08853500558 100644 --- a/pkg/bypass4netnsutil/bypass.go +++ b/pkg/bypass4netnsutil/bypass.go @@ -18,31 +18,41 @@ package bypass4netnsutil import ( "context" + "encoding/json" "fmt" "net" "path/filepath" "github.com/containerd/containerd/errdefs" gocni "github.com/containerd/go-cni" + "github.com/containerd/nerdctl/v2/pkg/annotations" b4nnapi "github.com/rootless-containers/bypass4netns/pkg/api" "github.com/rootless-containers/bypass4netns/pkg/api/daemon/client" rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" ) -func NewBypass4netnsCNIBypassManager(client client.Client, rlkClient rlkclient.Client) (*Bypass4netnsCNIBypassManager, error) { +func NewBypass4netnsCNIBypassManager(client client.Client, rlkClient rlkclient.Client, annotationsMap map[string]string) (*Bypass4netnsCNIBypassManager, error) { if client == nil || rlkClient == nil { return nil, errdefs.ErrInvalidArgument } + var ignoreSubnets []string + if v := annotationsMap[annotations.Bypass4netnsIgnoreSubnets]; v != "" { + if err := json.Unmarshal([]byte(v), &ignoreSubnets); err != nil { + return nil, fmt.Errorf("failed to unmarshal annotation %q: %q: %w", annotations.Bypass4netnsIgnoreSubnets, v, err) + } + } pm := &Bypass4netnsCNIBypassManager{ - Client: client, - rlkClient: rlkClient, + Client: client, + rlkClient: rlkClient, + ignoreSubnets: ignoreSubnets, } return pm, nil } type Bypass4netnsCNIBypassManager struct { client.Client - rlkClient rlkclient.Client + rlkClient rlkclient.Client + ignoreSubnets []string } func (b4nnm *Bypass4netnsCNIBypassManager) StartBypass(ctx context.Context, ports []gocni.PortMapping, id, stateDir string) error { @@ -73,7 +83,7 @@ func (b4nnm *Bypass4netnsCNIBypassManager) StartBypass(ctx context.Context, port PidFilePath: pidFilePath, LogFilePath: logFilePath, // "auto" can detect CNI CIDRs automatically - IgnoreSubnets: []string{"127.0.0.0/8", rlkCIDR, "auto"}, + IgnoreSubnets: append([]string{"127.0.0.0/8", rlkCIDR, "auto"}, b4nnm.ignoreSubnets...), } portMap := []b4nnapi.PortSpec{} for _, p := range ports { diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 243d9a9af9a..7ce72386910 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -449,7 +449,7 @@ func applyNetworkSettings(opts *handlerOpts) error { if rootlessutil.IsRootlessChild() { if b4nnEnabled { - bm, err := bypass4netnsutil.NewBypass4netnsCNIBypassManager(opts.bypassClient, opts.rootlessKitClient) + bm, err := bypass4netnsutil.NewBypass4netnsCNIBypassManager(opts.bypassClient, opts.rootlessKitClient, opts.state.Annotations) if err != nil { return err } @@ -493,7 +493,7 @@ func onPostStop(opts *handlerOpts) error { } if rootlessutil.IsRootlessChild() { if b4nnEnabled { - bm, err := bypass4netnsutil.NewBypass4netnsCNIBypassManager(opts.bypassClient, opts.rootlessKitClient) + bm, err := bypass4netnsutil.NewBypass4netnsCNIBypassManager(opts.bypassClient, opts.rootlessKitClient, opts.state.Annotations) if err != nil { return err } From cc495f2a718e93295e26243d1da02da091baad4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Apr 2024 22:18:15 +0000 Subject: [PATCH 0393/1066] build(deps): bump golang.org/x/net from 0.22.0 to 0.23.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.22.0 to 0.23.0. - [Commits](https://github.com/golang/net/compare/v0.22.0...v0.23.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cac80dc7a83..16f1b604020 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 golang.org/x/crypto v0.21.0 - golang.org/x/net v0.22.0 + golang.org/x/net v0.23.0 golang.org/x/sync v0.6.0 golang.org/x/sys v0.18.0 golang.org/x/term v0.18.0 diff --git a/go.sum b/go.sum index 7a4a644131a..a7e0e9a9b0d 100644 --- a/go.sum +++ b/go.sum @@ -388,8 +388,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From af4c470dd9fed6586f630499dab9ef2fe349380e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Apr 2024 23:00:10 +0000 Subject: [PATCH 0394/1066] build(deps): bump golang.org/x/crypto from 0.21.0 to 0.22.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.21.0 to 0.22.0. - [Commits](https://github.com/golang/crypto/compare/v0.21.0...v0.22.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 16f1b604020..d198efe32f0 100644 --- a/go.mod +++ b/go.mod @@ -55,11 +55,11 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.21.0 + golang.org/x/crypto v0.22.0 golang.org/x/net v0.23.0 golang.org/x/sync v0.6.0 - golang.org/x/sys v0.18.0 - golang.org/x/term v0.18.0 + golang.org/x/sys v0.19.0 + golang.org/x/term v0.19.0 golang.org/x/text v0.14.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 diff --git a/go.sum b/go.sum index a7e0e9a9b0d..45a5ab137fe 100644 --- a/go.sum +++ b/go.sum @@ -358,8 +358,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= @@ -430,15 +430,15 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 6b8a1c6374b553a5f5729985acf33bfebe18a419 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Apr 2024 23:54:14 +0000 Subject: [PATCH 0395/1066] build(deps): bump golang.org/x/net from 0.23.0 to 0.24.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.23.0 to 0.24.0. - [Commits](https://github.com/golang/net/compare/v0.23.0...v0.24.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d198efe32f0..cd8cd6a85cf 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 golang.org/x/crypto v0.22.0 - golang.org/x/net v0.23.0 + golang.org/x/net v0.24.0 golang.org/x/sync v0.6.0 golang.org/x/sys v0.19.0 golang.org/x/term v0.19.0 diff --git a/go.sum b/go.sum index 45a5ab137fe..42d380cf1b8 100644 --- a/go.sum +++ b/go.sum @@ -388,8 +388,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 858fa60e36c26b9abab2865383a8b9177d43a5dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 01:04:35 +0000 Subject: [PATCH 0396/1066] build(deps): bump golang.org/x/sync from 0.6.0 to 0.7.0 Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.6.0 to 0.7.0. - [Commits](https://github.com/golang/sync/compare/v0.6.0...v0.7.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cd8cd6a85cf..55f09bd7570 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,7 @@ require ( go.uber.org/mock v0.4.0 golang.org/x/crypto v0.22.0 golang.org/x/net v0.24.0 - golang.org/x/sync v0.6.0 + golang.org/x/sync v0.7.0 golang.org/x/sys v0.19.0 golang.org/x/term v0.19.0 golang.org/x/text v0.14.0 diff --git a/go.sum b/go.sum index 42d380cf1b8..93e1c6c4da1 100644 --- a/go.sum +++ b/go.sum @@ -398,8 +398,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= From a1fd53b728b086ed3c7052d9d6be6cc3aa46eafc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 22:36:59 +0000 Subject: [PATCH 0397/1066] build(deps): bump github.com/containerd/containerd from 1.7.14 to 1.7.15 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.14 to 1.7.15. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.14...v1.7.15) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 55f09bd7570..705c561034f 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.0.4 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd v1.7.14 + github.com/containerd/containerd v1.7.15 github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 @@ -87,7 +87,7 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 93e1c6c4da1..062c28e5662 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ 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.14 h1:H/XLzbnGuenZEGK+v0RkwTdv2u1QFAruMe5N0GNPJwA= -github.com/containerd/containerd v1.7.14/go.mod h1:YMC9Qt5yzNqXx/fO4j/5yYVIHXSRrlB3H7sxkUTvspg= +github.com/containerd/containerd v1.7.15 h1:afEHXdil9iAm03BmhjzKyXnnEBtjaLJefdU7DV0IFes= +github.com/containerd/containerd v1.7.15/go.mod h1:ISzRRTMF8EXNpJlTzyr2XMhN+j9K302C21/+cr3kUnY= 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= @@ -149,8 +149,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= From 2cfff27049d48ffb7a63d26cf0aadbfda564ba55 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 8 Apr 2024 16:58:23 +0900 Subject: [PATCH 0398/1066] update containerd (1.7.15) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 24 ++++++++++++------------ Dockerfile | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 59955e8838f..a17d60ed3d5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,11 +77,11 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.30 + containerd: v1.6.31 - ubuntu: 20.04 - containerd: v1.7.14 + containerd: v1.7.15 - ubuntu: 22.04 - containerd: v1.7.14 + containerd: v1.7.15 - ubuntu: 22.04 containerd: main env: @@ -113,7 +113,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 22.04 - containerd: v1.7.14 + containerd: v1.7.15 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -157,15 +157,15 @@ jobs: # ubuntu-22.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.30 + containerd: v1.6.31 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.14 + containerd: v1.7.15 rootlesskit: v2.0.2 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.14 + containerd: v1.7.15 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 @@ -173,15 +173,15 @@ jobs: rootlesskit: v2.0.2 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.6.30 + containerd: v1.6.31 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.14 + containerd: v1.7.15 rootlesskit: v2.0.2 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.14 + containerd: v1.7.15 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 @@ -275,7 +275,7 @@ jobs: - uses: actions/checkout@v4.1.2 with: repository: containerd/containerd - ref: v1.7.14 + ref: v1.7.15 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -283,7 +283,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.14 + ctrdVersion: 1.7.15 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index b42709b02be..4ff23963c3f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.14 +ARG CONTAINERD_VERSION=v1.7.15 ARG RUNC_VERSION=v1.1.12 ARG CNI_PLUGINS_VERSION=v1.4.1 From 2c446522cb4796129220d369f3021c0cbb3f3170 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 07:59:29 +0000 Subject: [PATCH 0399/1066] build(deps): bump github.com/containerd/accelerated-container-image Bumps [github.com/containerd/accelerated-container-image](https://github.com/containerd/accelerated-container-image) from 1.0.4 to 1.1.2. - [Release notes](https://github.com/containerd/accelerated-container-image/releases) - [Commits](https://github.com/containerd/accelerated-container-image/compare/v1.0.4...v1.1.2) --- updated-dependencies: - dependency-name: github.com/containerd/accelerated-container-image dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 705c561034f..a754b26ef64 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Microsoft/hcsshim v0.12.2 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.4 + 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.15 @@ -76,7 +76,7 @@ require ( github.com/containerd/ttrpc v1.2.3 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect github.com/containers/ocicrypt v1.1.10 // indirect - github.com/distribution/reference v0.5.0 // indirect + github.com/distribution/reference v0.6.0 // indirect 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 diff --git a/go.sum b/go.sum index 062c28e5662..ac36a1a85db 100644 --- a/go.sum +++ b/go.sum @@ -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.4 h1:2WDo44n7ohyDeqkynC1C8BboaZrrIIICGdmunz0jCXs= -github.com/containerd/accelerated-container-image v1.0.4/go.mod h1:iPvBVzJWG0WbfBEGk4Ap+HLWPaUWnx4toLpVkBafIDI= +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/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= @@ -85,8 +85,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 v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I= From f802ba87b47a6275d9ab1b87c39817da7c4d9406 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 8 Apr 2024 17:00:23 +0900 Subject: [PATCH 0400/1066] update bypass4netns (0.4.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4ff23963c3f..8de873343bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,7 +32,7 @@ ARG IMGCRYPT_VERSION=v1.1.10 ARG ROOTLESSKIT_VERSION=v2.0.2 ARG SLIRP4NETNS_VERSION=v1.2.3 # Extra deps: bypass4netns -ARG BYPASS4NETNS_VERSION=v0.4.0 +ARG BYPASS4NETNS_VERSION=v0.4.1 # Extra deps: FUSE-OverlayFS ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 From 62e031c66e0442cff48e232eb73cb8f994632f95 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sat, 6 Apr 2024 06:14:25 +0900 Subject: [PATCH 0401/1066] bypass4netns: allow ignoring bind The bypass for bind can be disabled with the new annotation `nerdctl/bypass4netns-ignore-bind=true`. Depends on rootless-containers/bypass4netns PR 68 Signed-off-by: Akihiro Suda --- pkg/annotations/annotations.go | 6 +++++ pkg/bypass4netnsutil/bypass.go | 30 +++++++++++++++++------- pkg/bypass4netnsutil/bypass4netnsutil.go | 20 ++++++++++------ pkg/ocihook/ocihook.go | 12 ++++++---- 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/pkg/annotations/annotations.go b/pkg/annotations/annotations.go index e89648d7abb..97c1edd56ef 100644 --- a/pkg/annotations/annotations.go +++ b/pkg/annotations/annotations.go @@ -29,10 +29,16 @@ const ( // Bypass4netnsIgnoreSubnets is a JSON of []string that is appended to // the `bypass4netns --ignore` list. Bypass4netnsIgnoreSubnets = Bypass4netns + "-ignore-subnets" + + // Bypass4netnsIgnoreBind disables acceleration for bind. + // Boolean value which can be parsed with strconv.ParseBool() is required. + Bypass4netnsIgnoreBind = Bypass4netns + "-ignore-bind" ) var ShellCompletions = []string{ Bypass4netns + "=true", Bypass4netns + "=false", Bypass4netnsIgnoreSubnets + "=", + Bypass4netnsIgnoreBind + "=true", + Bypass4netnsIgnoreBind + "=false", } diff --git a/pkg/bypass4netnsutil/bypass.go b/pkg/bypass4netnsutil/bypass.go index 08853500558..9e69952b70d 100644 --- a/pkg/bypass4netnsutil/bypass.go +++ b/pkg/bypass4netnsutil/bypass.go @@ -35,6 +35,13 @@ func NewBypass4netnsCNIBypassManager(client client.Client, rlkClient rlkclient.C if client == nil || rlkClient == nil { return nil, errdefs.ErrInvalidArgument } + enabled, bindEnabled, err := IsBypass4netnsEnabled(annotationsMap) + if err != nil { + return nil, err + } + if !enabled { + return nil, errdefs.ErrInvalidArgument + } var ignoreSubnets []string if v := annotationsMap[annotations.Bypass4netnsIgnoreSubnets]; v != "" { if err := json.Unmarshal([]byte(v), &ignoreSubnets); err != nil { @@ -45,6 +52,7 @@ func NewBypass4netnsCNIBypassManager(client client.Client, rlkClient rlkclient.C Client: client, rlkClient: rlkClient, ignoreSubnets: ignoreSubnets, + ignoreBind: !bindEnabled, } return pm, nil } @@ -53,6 +61,7 @@ type Bypass4netnsCNIBypassManager struct { client.Client rlkClient rlkclient.Client ignoreSubnets []string + ignoreBind bool } func (b4nnm *Bypass4netnsCNIBypassManager) StartBypass(ctx context.Context, ports []gocni.PortMapping, id, stateDir string) error { @@ -84,17 +93,20 @@ func (b4nnm *Bypass4netnsCNIBypassManager) StartBypass(ctx context.Context, port LogFilePath: logFilePath, // "auto" can detect CNI CIDRs automatically IgnoreSubnets: append([]string{"127.0.0.0/8", rlkCIDR, "auto"}, b4nnm.ignoreSubnets...), + IgnoreBind: b4nnm.ignoreBind, } - portMap := []b4nnapi.PortSpec{} - for _, p := range ports { - portMap = append(portMap, b4nnapi.PortSpec{ - ParentIP: p.HostIP, - ParentPort: int(p.HostPort), - ChildPort: int(p.ContainerPort), - Protos: []string{p.Protocol}, - }) + if !b4nnm.ignoreBind { + portMap := []b4nnapi.PortSpec{} + for _, p := range ports { + portMap = append(portMap, b4nnapi.PortSpec{ + ParentIP: p.HostIP, + ParentPort: int(p.HostPort), + ChildPort: int(p.ContainerPort), + Protos: []string{p.Protocol}, + }) + } + spec.PortMapping = portMap } - spec.PortMapping = portMap _, err = b4nnm.BypassManager().StartBypass(ctx, spec) if err != nil { return err diff --git a/pkg/bypass4netnsutil/bypass4netnsutil.go b/pkg/bypass4netnsutil/bypass4netnsutil.go index 2dd0093a35a..6ba7c383a79 100644 --- a/pkg/bypass4netnsutil/bypass4netnsutil.go +++ b/pkg/bypass4netnsutil/bypass4netnsutil.go @@ -133,15 +133,21 @@ func GetPidFilePathByID(id string) (string, error) { return socketPath, nil } -func IsBypass4netnsEnabled(annotationsMap map[string]string) (bool, error) { +func IsBypass4netnsEnabled(annotationsMap map[string]string) (enabled, bindEnabled bool, err error) { if b4nn, ok := annotationsMap[annotations.Bypass4netns]; ok { - b4nnEnable, err := strconv.ParseBool(b4nn) + enabled, err = strconv.ParseBool(b4nn) if err != nil { - return false, err + return + } + bindEnabled = enabled + if s, ok := annotationsMap[annotations.Bypass4netnsIgnoreBind]; ok { + var bindDisabled bool + bindDisabled, err = strconv.ParseBool(s) + if err != nil { + return + } + bindEnabled = !bindDisabled } - - return b4nnEnable, nil } - - return false, nil + return } diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 7ce72386910..bed57eefb8c 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -202,7 +202,7 @@ func newHandlerOpts(state *specs.State, dataStore, cniPath, cniNetconfPath strin if err != nil { return nil, err } - b4nnEnabled, err := bypass4netnsutil.IsBypass4netnsEnabled(o.state.Annotations) + b4nnEnabled, _, err := bypass4netnsutil.IsBypass4netnsEnabled(o.state.Annotations) if err != nil { return nil, err } @@ -438,7 +438,7 @@ func applyNetworkSettings(opts *handlerOpts) error { hsMeta.Networks[cniName] = cniResRaw[i] } - b4nnEnabled, err := bypass4netnsutil.IsBypass4netnsEnabled(opts.state.Annotations) + b4nnEnabled, b4nnBindEnabled, err := bypass4netnsutil.IsBypass4netnsEnabled(opts.state.Annotations) if err != nil { return err } @@ -457,7 +457,8 @@ func applyNetworkSettings(opts *handlerOpts) error { if err != nil { return fmt.Errorf("bypass4netnsd not running? (Hint: run `containerd-rootless-setuptool.sh install-bypass4netnsd`): %w", err) } - } else if len(opts.ports) > 0 { + } + if !b4nnBindEnabled && len(opts.ports) > 0 { if err := exposePortsRootless(ctx, opts.rootlessKitClient, opts.ports); err != nil { return fmt.Errorf("failed to expose ports in rootless mode: %s", err) } @@ -487,7 +488,7 @@ func onPostStop(opts *handlerOpts) error { ns := opts.state.Annotations[labels.Namespace] if opts.cni != nil { var err error - b4nnEnabled, err := bypass4netnsutil.IsBypass4netnsEnabled(opts.state.Annotations) + b4nnEnabled, b4nnBindEnabled, err := bypass4netnsutil.IsBypass4netnsEnabled(opts.state.Annotations) if err != nil { return err } @@ -501,7 +502,8 @@ func onPostStop(opts *handlerOpts) error { if err != nil { return err } - } else if len(opts.ports) > 0 { + } + if !b4nnBindEnabled && len(opts.ports) > 0 { if err := unexposePortsRootless(ctx, opts.rootlessKitClient, opts.ports); err != nil { return fmt.Errorf("failed to unexpose ports in rootless mode: %s", err) } From 0d75e34f67ab7cad82800876a6312b20d6e2ad03 Mon Sep 17 00:00:00 2001 From: "Paul \"TBBle\" Hampson" Date: Sat, 21 Oct 2023 18:51:15 +0900 Subject: [PATCH 0402/1066] Remove unused defaults.BuildKitHost Although it was being shown in the help output, the value was ignored in favour of auto-detection by getBuildkitHost, which could give different results anyway. Signed-off-by: Paul "TBBle" Hampson --- cmd/nerdctl/builder.go | 3 +-- cmd/nerdctl/builder_build.go | 3 +-- pkg/defaults/defaults_freebsd.go | 4 ---- pkg/defaults/defaults_linux.go | 12 ------------ pkg/defaults/defaults_windows.go | 5 ----- 5 files changed, 2 insertions(+), 25 deletions(-) diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index 595c068cfc3..71a8b5a42de 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -24,7 +24,6 @@ import ( "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" - "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/spf13/cobra" ) @@ -56,7 +55,7 @@ func newBuilderPruneCommand() *cobra.Command { SilenceErrors: true, } - AddStringFlag(buildPruneCommand, "buildkit-host", nil, defaults.BuildKitHost(), "BUILDKIT_HOST", "BuildKit address") + AddStringFlag(buildPruneCommand, "buildkit-host", nil, "", "BUILDKIT_HOST", "BuildKit address") return buildPruneCommand } diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index 9b060cbbe07..47cc31f7ff1 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -27,7 +27,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/builder" - "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/spf13/cobra" @@ -43,7 +42,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container SilenceUsage: true, SilenceErrors: true, } - AddStringFlag(buildCommand, "buildkit-host", nil, defaults.BuildKitHost(), "BUILDKIT_HOST", "BuildKit address") + AddStringFlag(buildCommand, "buildkit-host", nil, "", "BUILDKIT_HOST", "BuildKit address") buildCommand.Flags().StringArrayP("tag", "t", nil, "Name and optionally a tag in the 'name:tag' format") buildCommand.Flags().StringP("file", "f", "", "Name of the Dockerfile") buildCommand.Flags().String("target", "", "Set the target build stage to build") diff --git a/pkg/defaults/defaults_freebsd.go b/pkg/defaults/defaults_freebsd.go index ec5f3e8421c..8c165353b88 100644 --- a/pkg/defaults/defaults_freebsd.go +++ b/pkg/defaults/defaults_freebsd.go @@ -43,10 +43,6 @@ func CNIRuntimeDir() string { return "/run/cni" } -func BuildKitHost() string { - return "unix:///run/buildkit/buildkitd.sock" -} - func CgroupManager() string { return "" } diff --git a/pkg/defaults/defaults_linux.go b/pkg/defaults/defaults_linux.go index 13dbf9c9dd4..6b30aca67a3 100644 --- a/pkg/defaults/defaults_linux.go +++ b/pkg/defaults/defaults_linux.go @@ -99,18 +99,6 @@ func CNIRuntimeDir() string { return fmt.Sprintf("%s/cni", xdr) } -func BuildKitHost() string { - if !rootlessutil.IsRootless() { - return "unix:///run/buildkit/buildkitd.sock" - } - xdr, err := rootlessutil.XDGRuntimeDir() - if err != nil { - log.L.Warn(err) - xdr = fmt.Sprintf("/run/user/%d", rootlessutil.ParentEUID()) - } - return fmt.Sprintf("unix://%s/buildkit/buildkitd.sock", xdr) -} - func NerdctlTOML() string { if !rootlessutil.IsRootless() { return "/etc/nerdctl/nerdctl.toml" diff --git a/pkg/defaults/defaults_windows.go b/pkg/defaults/defaults_windows.go index 7adcce3fc9c..65d74d2c8bb 100644 --- a/pkg/defaults/defaults_windows.go +++ b/pkg/defaults/defaults_windows.go @@ -17,7 +17,6 @@ package defaults import ( - "fmt" "os" "path/filepath" ) @@ -44,10 +43,6 @@ func CNIRuntimeDir() string { return "" } -func BuildKitHost() string { - return fmt.Sprint("\\\\.\\pipe\\buildkit") -} - func IsSystemdAvailable() bool { return false } From 6e6aa4a9bb57cf79b03eceffbe446c2514b52458 Mon Sep 17 00:00:00 2001 From: "Paul \"TBBle\" Hampson" Date: Sun, 22 Oct 2023 12:12:32 +0900 Subject: [PATCH 0403/1066] Enable building on Windows hosts This of course requires functional BuildKit for Windows. Signed-off-by: Paul "TBBle" Hampson --- pkg/buildkitutil/buildkitutil.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pkg/buildkitutil/buildkitutil.go b/pkg/buildkitutil/buildkitutil.go index 2f72f8c1ff5..431416856b5 100644 --- a/pkg/buildkitutil/buildkitutil.go +++ b/pkg/buildkitutil/buildkitutil.go @@ -34,6 +34,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strings" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" @@ -143,9 +144,21 @@ func PingBKDaemon(buildkitHost string) error { return nil } +// contains open-codes slices.Contains (without generics) from Go 1.21. +// TODO: Replace once Go 1.21 is the minimum supported compiler. +func contains(haystack []string, needle string) bool { + for i := range haystack { + if needle == haystack[i] { + return true + } + } + return false +} + func pingBKDaemon(buildkitHost string) (output string, _ error) { - if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" { - return "", errors.New("only linux and freebsd are supported") + supportedOses := []string{"linux", "freebsd", "windows"} + if !contains(supportedOses, runtime.GOOS) { + return "", fmt.Errorf("only %s are supported", strings.Join(supportedOses, ", ")) } buildctlBinary, err := BuildctlBinary() if err != nil { From 5fac99b3eb32b2812dc034bb0f30170b61765741 Mon Sep 17 00:00:00 2001 From: "Paul \"TBBle\" Hampson" Date: Sun, 22 Oct 2023 12:33:45 +0900 Subject: [PATCH 0404/1066] Implement autodetection of Windows buildkitd socket Buildkit on Windows doesn't support rootless mode, and doesn't put the namespace into the pipe name currently, so the Windows version is near-trivial. This also corrects the autodetection path on FreeBSD to start in /var/run instead of current Linux FHS's /run, and doesn't bother trying to support Rootless mode and related path guessing on FreeBSD. Signed-off-by: Paul "TBBle" Hampson --- pkg/buildkitutil/buildkitutil.go | 28 +++++------------ pkg/buildkitutil/buildkitutil_freebsd.go | 22 +++++++++++++ pkg/buildkitutil/buildkitutil_linux.go | 39 ++++++++++++++++++++++++ pkg/buildkitutil/buildkitutil_unix.go | 39 ++++++++++++++++++++++++ pkg/buildkitutil/buildkitutil_windows.go | 21 +++++++++++++ 5 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 pkg/buildkitutil/buildkitutil_freebsd.go create mode 100644 pkg/buildkitutil/buildkitutil_linux.go create mode 100644 pkg/buildkitutil/buildkitutil_unix.go create mode 100644 pkg/buildkitutil/buildkitutil_windows.go diff --git a/pkg/buildkitutil/buildkitutil.go b/pkg/buildkitutil/buildkitutil.go index 431416856b5..9004892ae85 100644 --- a/pkg/buildkitutil/buildkitutil.go +++ b/pkg/buildkitutil/buildkitutil.go @@ -57,28 +57,14 @@ func BuildctlBaseArgs(buildkitHost string) []string { } func GetBuildkitHost(namespace string) (string, error) { - if namespace == "" { - return "", fmt.Errorf("namespace must be specified") - } - // Try candidate locations of the current containerd namespace. - run := "/run/" - if rootlessutil.IsRootless() { - var err error - run, err = rootlessutil.XDGRuntimeDir() - if err != nil { - log.L.Warn(err) - run = fmt.Sprintf("/run/user/%d", rootlessutil.ParentEUID()) - } - } - var hostRel []string - if namespace != "default" { - hostRel = append(hostRel, fmt.Sprintf("buildkit-%s/buildkitd.sock", namespace)) + paths, err := getBuildkitHostCandidates(namespace) + if err != nil { + return "", err } - hostRel = append(hostRel, "buildkit-default/buildkitd.sock", "buildkit/buildkitd.sock") + var errs []error //nolint:prealloc - for _, p := range hostRel { - log.L.Debugf("Choosing the buildkit host %q, candidates=%v (in %q)", p, hostRel, run) - buildkitHost := "unix://" + filepath.Join(run, p) + for _, buildkitHost := range paths { + log.L.Debugf("Choosing the buildkit host %q, candidates=%v", buildkitHost, paths) _, err := pingBKDaemon(buildkitHost) if err == nil { log.L.Debugf("Chosen buildkit host %q", buildkitHost) @@ -88,7 +74,7 @@ func GetBuildkitHost(namespace string) (string, error) { } allErr := errors.Join(errs...) log.L.WithError(allErr).Error(getHint()) - return "", fmt.Errorf("no buildkit host is available, tried %d candidates: %w", len(hostRel), allErr) + return "", fmt.Errorf("no buildkit host is available, tried %d candidates: %w", len(paths), allErr) } func GetWorkerLabels(buildkitHost string) (labels map[string]string, _ error) { diff --git a/pkg/buildkitutil/buildkitutil_freebsd.go b/pkg/buildkitutil/buildkitutil_freebsd.go new file mode 100644 index 00000000000..adaec5e42ef --- /dev/null +++ b/pkg/buildkitutil/buildkitutil_freebsd.go @@ -0,0 +1,22 @@ +/* + 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 buildkitutil + +func getRuntimeVariableDataDir() string { + // Per hier(7) dated July 6, 2023. + return "/var/run" +} diff --git a/pkg/buildkitutil/buildkitutil_linux.go b/pkg/buildkitutil/buildkitutil_linux.go new file mode 100644 index 00000000000..55740a29af3 --- /dev/null +++ b/pkg/buildkitutil/buildkitutil_linux.go @@ -0,0 +1,39 @@ +/* + 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 buildkitutil + +import ( + "fmt" + + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" +) + +func getRuntimeVariableDataDir() string { + // Per Linux Foundation "Filesystem Hierarchy Standard" version 3.0 section 3.15. + // Under version 2.3, this was "/var/run". + run := "/run" + if rootlessutil.IsRootless() { + var err error + run, err = rootlessutil.XDGRuntimeDir() + if err != nil { + log.L.Warn(err) + run = fmt.Sprintf("/run/user/%d", rootlessutil.ParentEUID()) + } + } + return run +} diff --git a/pkg/buildkitutil/buildkitutil_unix.go b/pkg/buildkitutil/buildkitutil_unix.go new file mode 100644 index 00000000000..521504992d0 --- /dev/null +++ b/pkg/buildkitutil/buildkitutil_unix.go @@ -0,0 +1,39 @@ +//go:build freebsd || linux + +/* + 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 buildkitutil + +import ( + "fmt" + "path/filepath" +) + +func getBuildkitHostCandidates(namespace string) ([]string, error) { + if namespace == "" { + return []string{}, fmt.Errorf("namespace must be specified") + } + // Try candidate locations of the current containerd namespace. + run := getRuntimeVariableDataDir() + var candidates []string + if namespace != "default" { + candidates = append(candidates, "unix://"+filepath.Join(run, fmt.Sprintf("buildkit-%s/buildkitd.sock", namespace))) + } + candidates = append(candidates, "unix://"+filepath.Join(run, "buildkit-default/buildkitd.sock"), "unix://"+filepath.Join(run, "buildkit/buildkitd.sock")) + + return candidates, nil +} diff --git a/pkg/buildkitutil/buildkitutil_windows.go b/pkg/buildkitutil/buildkitutil_windows.go new file mode 100644 index 00000000000..dd38470c068 --- /dev/null +++ b/pkg/buildkitutil/buildkitutil_windows.go @@ -0,0 +1,21 @@ +/* + 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 buildkitutil + +func getBuildkitHostCandidates(namespace string) ([]string, error) { + return []string{"npipe:////./pipe/buildkitd"}, nil +} From b5117a2357829a7ae419753bbf4285c1ee221dc7 Mon Sep 17 00:00:00 2001 From: "Paul \"TBBle\" Hampson" Date: Tue, 27 Feb 2024 20:05:01 +0900 Subject: [PATCH 0405/1066] Rationalise build constraints for Go 1.19 onwards This mostly involves replacing anything that was trying to be "Not Windows" with the new-in-Go-1.19 "unix" build-constraint. Effectively, anything that contained both "linux" and "freebsd" but not "windows", or excluded only "windows", is now "unix". A couple of needless constraints were removed when the filenames already carried the appropriate constraint. A handful of files were renamed, so that now "unix"-suffixed files all use the "unix" constraint, and "other" is used when the constraint is more-complex, for "no specific implementation" cases. Signed-off-by: Paul "TBBle" Hampson --- cmd/nerdctl/container_top_unix_test.go | 2 +- cmd/nerdctl/main_unix.go | 2 +- cmd/nerdctl/network_create_unix.go | 2 +- pkg/buildkitutil/buildkitutil_unix.go | 2 +- pkg/cioutil/container_io_unix.go | 2 +- pkg/cioutil/container_io_windows.go | 2 -- pkg/cmd/container/top_unix.go | 2 +- pkg/cmd/login/login_unix.go | 2 +- pkg/consoleutil/consoleutil_unix.go | 2 +- pkg/containerutil/container_network_manager_other.go | 2 +- pkg/infoutil/infoutil_unix.go | 2 +- pkg/infoutil/infoutil_unix_test.go | 2 +- pkg/ipcutil/ipcutil_linux.go | 2 -- pkg/ipcutil/{ipcutil_unix.go => ipcutil_other.go} | 2 +- pkg/lockutil/lockutil_unix.go | 2 +- pkg/mountutil/{mountutil_other.go => mountutil_unix.go} | 2 +- pkg/mountutil/mountutil_windows.go | 2 -- pkg/netutil/cni_plugin_unix.go | 2 +- pkg/netutil/netutil_linux_test.go | 2 -- pkg/netutil/netutil_unix.go | 2 +- pkg/netutil/netutil_unix_test.go | 2 +- pkg/netutil/netutil_windows_test.go | 2 -- .../{port_allocate_others.go => port_allocate_other.go} | 0 pkg/signalutil/{signals_notlinux.go => signals_other.go} | 0 pkg/systemutil/socket_unix.go | 2 +- 25 files changed, 18 insertions(+), 28 deletions(-) rename pkg/ipcutil/{ipcutil_unix.go => ipcutil_other.go} (97%) rename pkg/mountutil/{mountutil_other.go => mountutil_unix.go} (98%) rename pkg/portutil/{port_allocate_others.go => port_allocate_other.go} (100%) rename pkg/signalutil/{signals_notlinux.go => signals_other.go} (100%) diff --git a/cmd/nerdctl/container_top_unix_test.go b/cmd/nerdctl/container_top_unix_test.go index 45b39f2a64f..3e22f6f11db 100644 --- a/cmd/nerdctl/container_top_unix_test.go +++ b/cmd/nerdctl/container_top_unix_test.go @@ -1,4 +1,4 @@ -//go:build linux || darwin || freebsd || netbsd || openbsd +//go:build unix /* Copyright The containerd Authors. diff --git a/cmd/nerdctl/main_unix.go b/cmd/nerdctl/main_unix.go index eea216ee903..d804550fd19 100644 --- a/cmd/nerdctl/main_unix.go +++ b/cmd/nerdctl/main_unix.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. diff --git a/cmd/nerdctl/network_create_unix.go b/cmd/nerdctl/network_create_unix.go index 298030ba5bc..5abc60accc4 100644 --- a/cmd/nerdctl/network_create_unix.go +++ b/cmd/nerdctl/network_create_unix.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/buildkitutil/buildkitutil_unix.go b/pkg/buildkitutil/buildkitutil_unix.go index 521504992d0..5c5498d3aa9 100644 --- a/pkg/buildkitutil/buildkitutil_unix.go +++ b/pkg/buildkitutil/buildkitutil_unix.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/cioutil/container_io_unix.go b/pkg/cioutil/container_io_unix.go index fd0632c3781..1749a018c98 100644 --- a/pkg/cioutil/container_io_unix.go +++ b/pkg/cioutil/container_io_unix.go @@ -1,4 +1,4 @@ -//go:build !windows +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/cioutil/container_io_windows.go b/pkg/cioutil/container_io_windows.go index ac1c09625bf..6dde42f12a6 100644 --- a/pkg/cioutil/container_io_windows.go +++ b/pkg/cioutil/container_io_windows.go @@ -1,5 +1,3 @@ -//go:build windows - /* Copyright The containerd Authors. diff --git a/pkg/cmd/container/top_unix.go b/pkg/cmd/container/top_unix.go index 6281c23e072..e5f04ef60d1 100644 --- a/pkg/cmd/container/top_unix.go +++ b/pkg/cmd/container/top_unix.go @@ -1,4 +1,4 @@ -//go:build linux || darwin || freebsd || netbsd || openbsd +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/cmd/login/login_unix.go b/pkg/cmd/login/login_unix.go index ee536be1721..c1eec8fdf01 100644 --- a/pkg/cmd/login/login_unix.go +++ b/pkg/cmd/login/login_unix.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/consoleutil/consoleutil_unix.go b/pkg/consoleutil/consoleutil_unix.go index 49cea373bbf..6ffd0cc4dda 100644 --- a/pkg/consoleutil/consoleutil_unix.go +++ b/pkg/consoleutil/consoleutil_unix.go @@ -1,4 +1,4 @@ -//go:build !windows +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/containerutil/container_network_manager_other.go b/pkg/containerutil/container_network_manager_other.go index 914a3553c1a..1dabe5e6428 100644 --- a/pkg/containerutil/container_network_manager_other.go +++ b/pkg/containerutil/container_network_manager_other.go @@ -1,4 +1,4 @@ -//go:build darwin || freebsd || netbsd || openbsd +//go:build !(linux || windows) /* Copyright The containerd Authors. diff --git a/pkg/infoutil/infoutil_unix.go b/pkg/infoutil/infoutil_unix.go index e49f27e5e05..782a17537f0 100644 --- a/pkg/infoutil/infoutil_unix.go +++ b/pkg/infoutil/infoutil_unix.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/infoutil/infoutil_unix_test.go b/pkg/infoutil/infoutil_unix_test.go index 47067a8d1fa..208aedbafd3 100644 --- a/pkg/infoutil/infoutil_unix_test.go +++ b/pkg/infoutil/infoutil_unix_test.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/ipcutil/ipcutil_linux.go b/pkg/ipcutil/ipcutil_linux.go index 1c676abb027..0d1b9f6cbc6 100644 --- a/pkg/ipcutil/ipcutil_linux.go +++ b/pkg/ipcutil/ipcutil_linux.go @@ -1,5 +1,3 @@ -//go:build linux - /* Copyright The containerd Authors. diff --git a/pkg/ipcutil/ipcutil_unix.go b/pkg/ipcutil/ipcutil_other.go similarity index 97% rename from pkg/ipcutil/ipcutil_unix.go rename to pkg/ipcutil/ipcutil_other.go index c5664fc2732..a4c25963cc0 100644 --- a/pkg/ipcutil/ipcutil_unix.go +++ b/pkg/ipcutil/ipcutil_other.go @@ -1,4 +1,4 @@ -//go:build freebsd +//go:build !(linux || windows) /* Copyright The containerd Authors. diff --git a/pkg/lockutil/lockutil_unix.go b/pkg/lockutil/lockutil_unix.go index dbabcbc9b0f..64e9867b044 100644 --- a/pkg/lockutil/lockutil_unix.go +++ b/pkg/lockutil/lockutil_unix.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/mountutil/mountutil_other.go b/pkg/mountutil/mountutil_unix.go similarity index 98% rename from pkg/mountutil/mountutil_other.go rename to pkg/mountutil/mountutil_unix.go index eed4431382a..5bf7e4d2420 100644 --- a/pkg/mountutil/mountutil_other.go +++ b/pkg/mountutil/mountutil_unix.go @@ -1,4 +1,4 @@ -//go:build !windows +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/mountutil/mountutil_windows.go b/pkg/mountutil/mountutil_windows.go index eee76ba40b6..7d9ff965349 100644 --- a/pkg/mountutil/mountutil_windows.go +++ b/pkg/mountutil/mountutil_windows.go @@ -1,5 +1,3 @@ -//go:build windows - /* Copyright The containerd Authors. diff --git a/pkg/netutil/cni_plugin_unix.go b/pkg/netutil/cni_plugin_unix.go index 2a0233860f3..cdbb0221b8d 100644 --- a/pkg/netutil/cni_plugin_unix.go +++ b/pkg/netutil/cni_plugin_unix.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/netutil/netutil_linux_test.go b/pkg/netutil/netutil_linux_test.go index 1f64dbbd5af..4e370baba9b 100644 --- a/pkg/netutil/netutil_linux_test.go +++ b/pkg/netutil/netutil_linux_test.go @@ -1,5 +1,3 @@ -//go:build linux - /* Copyright The containerd Authors. diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index 12c39df982a..f5315028f04 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/netutil/netutil_unix_test.go b/pkg/netutil/netutil_unix_test.go index 4d9acc7cb91..5a2d66d4451 100644 --- a/pkg/netutil/netutil_unix_test.go +++ b/pkg/netutil/netutil_unix_test.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. diff --git a/pkg/netutil/netutil_windows_test.go b/pkg/netutil/netutil_windows_test.go index 7545230848f..eb26eef9449 100644 --- a/pkg/netutil/netutil_windows_test.go +++ b/pkg/netutil/netutil_windows_test.go @@ -1,5 +1,3 @@ -//go:build windows - /* Copyright The containerd Authors. diff --git a/pkg/portutil/port_allocate_others.go b/pkg/portutil/port_allocate_other.go similarity index 100% rename from pkg/portutil/port_allocate_others.go rename to pkg/portutil/port_allocate_other.go diff --git a/pkg/signalutil/signals_notlinux.go b/pkg/signalutil/signals_other.go similarity index 100% rename from pkg/signalutil/signals_notlinux.go rename to pkg/signalutil/signals_other.go diff --git a/pkg/systemutil/socket_unix.go b/pkg/systemutil/socket_unix.go index b8e2f1e6904..6d41bab69b3 100644 --- a/pkg/systemutil/socket_unix.go +++ b/pkg/systemutil/socket_unix.go @@ -1,4 +1,4 @@ -//go:build freebsd || linux +//go:build unix /* Copyright The containerd Authors. From 46acf060e17e052e67ce620a15efd3447f7181db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 12:11:55 +0000 Subject: [PATCH 0406/1066] build(deps): bump github.com/rootless-containers/bypass4netns Bumps [github.com/rootless-containers/bypass4netns](https://github.com/rootless-containers/bypass4netns) from 0.4.0 to 0.4.1. - [Commits](https://github.com/rootless-containers/bypass4netns/compare/v0.4.0...v0.4.1) --- updated-dependencies: - dependency-name: github.com/rootless-containers/bypass4netns dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a754b26ef64..84e8ee8926b 100644 --- a/go.mod +++ b/go.mod @@ -46,7 +46,7 @@ require ( github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/runtime-spec v1.2.0 github.com/pelletier/go-toml/v2 v2.2.0 - github.com/rootless-containers/bypass4netns v0.4.0 + github.com/rootless-containers/bypass4netns v0.4.1 github.com/rootless-containers/rootlesskit/v2 v2.0.2 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index ac36a1a85db..73c392f2549 100644 --- a/go.sum +++ b/go.sum @@ -279,8 +279,8 @@ github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwa github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rootless-containers/bypass4netns v0.4.0 h1:7pcI4XWnOMQkgCsPKMXxMzQKhZUjaQ8J1n+eIYiHS0Y= -github.com/rootless-containers/bypass4netns v0.4.0/go.mod h1:RPNWMSRT951DMtq9Xv72IZoJPWFeJL6Wg5pF79Lkano= +github.com/rootless-containers/bypass4netns v0.4.1 h1:zyYM1uSG7/prAphD2vlJvx/MEKK91EjD2XaefGx5PKA= +github.com/rootless-containers/bypass4netns v0.4.1/go.mod h1:slu3ygwy1x6ey78oBTNs7lpymyEimLBYoXOG76b+Q+Y= github.com/rootless-containers/rootlesskit/v2 v2.0.2 h1:wztWcDYFlk+EVAUuPJwlNMFXZIk1G14T45lv47WWGuA= github.com/rootless-containers/rootlesskit/v2 v2.0.2/go.mod h1:hE+ztevrQxNi+tdZyPKumzDk7VKDAf0E4seOzlOyBsY= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= From 27b8dd842a87f1ff8f01a14633def47beb705053 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 22:41:42 +0000 Subject: [PATCH 0407/1066] build(deps): bump github.com/klauspost/compress from 1.17.7 to 1.17.8 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.7 to 1.17.8. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.7...v1.17.8) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 84e8ee8926b..0bfacebd717 100644 --- a/go.mod +++ b/go.mod @@ -94,7 +94,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.7 + github.com/klauspost/compress v1.17.8 github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect diff --git a/go.sum b/go.sum index 73c392f2549..42bc5cf8556 100644 --- a/go.sum +++ b/go.sum @@ -182,8 +182,8 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= From a3fdaafa8ff9bc3f996361a618cd0db663f8935d Mon Sep 17 00:00:00 2001 From: baijia Date: Wed, 10 Apr 2024 15:10:00 +0800 Subject: [PATCH 0408/1066] fix: cleanup volume dir if create volume failed Volume path should be cleaned up if create volume failed. Otherwise, the same volume will be created failed again next time with a 'file exists' error on os.Mkdir. Signed-off-by: baijia --- pkg/mountutil/volumestore/volumestore.go | 27 ++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index 48fbbfa5397..430791223be 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -24,6 +24,7 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/lockutil" "github.com/containerd/nerdctl/v2/pkg/strutil" @@ -83,13 +84,24 @@ func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, err } volPath := filepath.Join(vs.dir, name) volDataPath := filepath.Join(volPath, DataDirName) - fn := func() error { + volFilePath := filepath.Join(volPath, volumeJSONFileName) + fn := func() (err error) { if err := os.Mkdir(volPath, 0700); err != nil { return err } + defer func() { + if err != nil { + os.Remove(volPath) + } + }() if err := os.Mkdir(volDataPath, 0755); err != nil { return err } + defer func() { + if err != nil { + os.Remove(volDataPath) + } + }() type volumeOpts struct { Labels map[string]string `json:"labels"` @@ -106,7 +118,16 @@ func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, err return err } - volFilePath := filepath.Join(volPath, volumeJSONFileName) + defer func() { + if err != nil { + if _, statErr := os.Stat(volFilePath); statErr != nil && !os.IsNotExist(statErr) { + log.L.Warnf("failed to stat volume file: %v", statErr) + return + } else if statErr == nil { + os.Remove(volFilePath) + } + } + }() return os.WriteFile(volFilePath, labelsJSON, 0644) } @@ -114,6 +135,8 @@ func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, err return nil, err } + // If other new actions that might fail are added below, we should move the cleanup function out of fn. + vol := &native.Volume{ Name: name, Mountpoint: volDataPath, From 9b8e1dd38cbd9b3b28d415435ad079252332bce3 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 9 Apr 2024 10:21:02 +0000 Subject: [PATCH 0409/1066] fix follow tail of rotate log Co-authored-by: fahed dorgaa Signed-off-by: Kay Yan --- cmd/nerdctl/container_logs_test.go | 28 +++++++++++++++++++++ pkg/logging/json_logger.go | 39 +++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/container_logs_test.go b/cmd/nerdctl/container_logs_test.go index b14824f84ad..01fb2ab2790 100644 --- a/cmd/nerdctl/container_logs_test.go +++ b/cmd/nerdctl/container_logs_test.go @@ -24,6 +24,7 @@ import ( "time" "github.com/containerd/nerdctl/v2/pkg/testutil" + "gotest.tools/v3/assert" ) func TestLogs(t *testing.T) { @@ -206,3 +207,30 @@ func TestLogsWithForegroundContainers(t *testing.T) { }(t) } } + +func TestTailFollowRotateLogs(t *testing.T) { + t.Parallel() + if runtime.GOOS == "windows" { + t.Skip("tail log is not supported on Windows") + } + base := testutil.NewBase(t) + containerName := testutil.Identifier(t) + + const sampleJSONLog = `{"log":"A\n","stream":"stdout","time":"2024-04-11T12:01:09.800288974Z"}` + const linesPerFile = 100 + + defer base.Cmd("rm", "-f", containerName).Run() + base.Cmd("run", "-d", "--log-driver", "json-file", + "--log-opt", fmt.Sprintf("max-size=%d", len(sampleJSONLog)*linesPerFile), + "--log-opt", "max-file=10", + "--name", containerName, testutil.CommonImage, + "sh", "-euc", "while true; do echo A; done").AssertOK() + + tailLogCmd := base.Cmd("logs", "-f", containerName) + tailLogCmd.Timeout = 100 * time.Millisecond + tailLogs := strings.Split(strings.TrimSpace(tailLogCmd.Run().Combined()), "\n") + for _, line := range tailLogs { + assert.Equal(t, "A", line) + } + assert.Equal(t, true, len(tailLogs) > linesPerFile) +} diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index f30511897d2..6383eb3b768 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -17,6 +17,7 @@ package logging import ( + "bufio" "errors" "fmt" "io" @@ -24,6 +25,7 @@ import ( "os/exec" "path/filepath" "strconv" + "strings" "time" "github.com/containerd/containerd/runtime/v2/logging" @@ -208,19 +210,29 @@ func viewLogsJSONFileThroughTailExec(lvopts LogViewOptions, jsonLogFilePath stri } if lvopts.Follow { - args = append(args, "-f") + // using the `-F` to follow the file name instead of descriptor and retry if inaccessible + args = append(args, "-F") } args = append(args, jsonLogFilePath) cmd := exec.Command("tail", args...) - cmd.Stderr = os.Stderr - r, err := cmd.StdoutPipe() + + cmdStdout, err := cmd.StdoutPipe() + if err != nil { + return err + } + + cmdStderr, err := cmd.StderrPipe() if err != nil { return err } + if err := cmd.Start(); err != nil { return err } + // filter the unwanted error message of the tail + go filterTailStderr(cmdStderr) + // Setup killing goroutine: go func() { <-stopChannel @@ -228,5 +240,24 @@ func viewLogsJSONFileThroughTailExec(lvopts LogViewOptions, jsonLogFilePath stri cmd.Process.Kill() }() - return jsonfile.Decode(stdout, stderr, r, lvopts.Timestamps, lvopts.Since, lvopts.Until, 0) + return jsonfile.Decode(stdout, stderr, cmdStdout, lvopts.Timestamps, lvopts.Since, lvopts.Until, 0) +} + +func filterTailStderr(reader io.Reader) error { + scanner := bufio.NewScanner(reader) + for scanner.Scan() { + line := scanner.Text() + if strings.HasSuffix(line, "has appeared; following new file") || + strings.HasSuffix(line, "has become inaccessible: No such file or directory") || + strings.HasSuffix(line, "has been replaced; following new file") || + strings.HasSuffix(line, ": No such file or directory") { + continue + } + fmt.Fprintln(os.Stderr, line) + } + + if err := scanner.Err(); err != nil { + return err + } + return nil } From d42571702cdcc0abbb76f0f0e32c5c67c204c6ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 22:50:19 +0000 Subject: [PATCH 0410/1066] build(deps): bump github.com/containerd/accelerated-container-image Bumps [github.com/containerd/accelerated-container-image](https://github.com/containerd/accelerated-container-image) from 1.1.2 to 1.1.3. - [Release notes](https://github.com/containerd/accelerated-container-image/releases) - [Commits](https://github.com/containerd/accelerated-container-image/compare/v1.1.2...v1.1.3) --- updated-dependencies: - dependency-name: github.com/containerd/accelerated-container-image dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0bfacebd717..bf319e1e378 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/Microsoft/hcsshim v0.12.2 github.com/awslabs/soci-snapshotter v0.4.1 github.com/compose-spec/compose-go v1.20.2 - github.com/containerd/accelerated-container-image v1.1.2 + github.com/containerd/accelerated-container-image v1.1.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd v1.7.15 diff --git a/go.sum b/go.sum index 42bc5cf8556..4858744f686 100644 --- a/go.sum +++ b/go.sum @@ -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.1.2 h1:Gk+1aqi6DpMVPCFAFWAUZgeKzSQ8fEu+GiBLnS42rc4= -github.com/containerd/accelerated-container-image v1.1.2/go.mod h1:NcMeDHjzY1cH5E96knLx0QaGYHeUxe0z3zA2/8qh1IE= +github.com/containerd/accelerated-container-image v1.1.3 h1:4fw0FsGB3YPHzth8H8WalJxnVuUU566+UCTXnoIZRCQ= +github.com/containerd/accelerated-container-image v1.1.3/go.mod h1:9mpTpL4W4yAsq2giHgo4B7wTFJgE59qCPh7dZTSpGCA= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= From dc42456f8867481123e257f36fbca2c4ae1785dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 22:50:35 +0000 Subject: [PATCH 0411/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.0.0+incompatible to 26.0.1+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v26.0.0...v26.0.1) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0bfacebd717..253fa44103f 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.4 github.com/docker/cli v26.0.0+incompatible - github.com/docker/docker v26.0.0+incompatible + github.com/docker/docker v26.0.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.0 diff --git a/go.sum b/go.sum index 42bc5cf8556..c0e20a11d1b 100644 --- a/go.sum +++ b/go.sum @@ -91,8 +91,8 @@ 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 v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I= github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU= -github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.0.1+incompatible h1:t39Hm6lpXuXtgkF0dm1t9a5HkbUfdGy6XbWexmGr+hA= +github.com/docker/docker v26.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 6ffb5466ed9d903f14736dea3939457ed4c05065 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 02:18:34 +0000 Subject: [PATCH 0412/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 26.0.0+incompatible to 26.0.1+incompatible. - [Commits](https://github.com/docker/cli/compare/v26.0.0...v26.0.1) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 253fa44103f..29080fbe6c4 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.4 - github.com/docker/cli v26.0.0+incompatible + github.com/docker/cli v26.0.1+incompatible github.com/docker/docker v26.0.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index c0e20a11d1b..40308f0b705 100644 --- a/go.sum +++ b/go.sum @@ -89,8 +89,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr 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 v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUyzJVPxD30I= -github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v26.0.1+incompatible h1:eZDuplk2jYqgUkNLDYwTBxqmY9cM3yHnmN6OIUEjL3U= +github.com/docker/cli v26.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v26.0.1+incompatible h1:t39Hm6lpXuXtgkF0dm1t9a5HkbUfdGy6XbWexmGr+hA= github.com/docker/docker v26.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= From c1c0fc93b17801511523c91b89b9a5b71c6e2137 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 22:46:55 +0000 Subject: [PATCH 0413/1066] build(deps): bump github.com/fahedouch/go-logrotate from 0.2.0 to 0.2.1 Bumps [github.com/fahedouch/go-logrotate](https://github.com/fahedouch/go-logrotate) from 0.2.0 to 0.2.1. - [Release notes](https://github.com/fahedouch/go-logrotate/releases) - [Commits](https://github.com/fahedouch/go-logrotate/compare/v0.2.0...v0.2.1) --- updated-dependencies: - dependency-name: github.com/fahedouch/go-logrotate dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 29080fbe6c4..f540489c9fb 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/docker/docker v26.0.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 - github.com/fahedouch/go-logrotate v0.2.0 + github.com/fahedouch/go-logrotate v0.2.1 github.com/fatih/color v1.16.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/ipfs/go-cid v0.4.1 @@ -77,7 +77,7 @@ require ( github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect github.com/containers/ocicrypt v1.1.10 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/djherbis/times v1.5.0 // indirect + github.com/djherbis/times v1.6.0 // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/felixge/httpsnoop v1.0.3 // indirect diff --git a/go.sum b/go.sum index 40308f0b705..34d0372bd51 100644 --- a/go.sum +++ b/go.sum @@ -87,8 +87,8 @@ 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.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/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= +github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/docker/cli v26.0.1+incompatible h1:eZDuplk2jYqgUkNLDYwTBxqmY9cM3yHnmN6OIUEjL3U= github.com/docker/cli v26.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v26.0.1+incompatible h1:t39Hm6lpXuXtgkF0dm1t9a5HkbUfdGy6XbWexmGr+hA= @@ -105,8 +105,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fahedouch/go-logrotate v0.2.0 h1:UR9Fv8MDVfWwnkirmFHck+tRSWzqOwRjVRLMpQgSxaI= -github.com/fahedouch/go-logrotate v0.2.0/go.mod h1:1RL/yr7LntS4zadAC6FT6yB/C1CQt3V6eHAZzymfwzE= +github.com/fahedouch/go-logrotate v0.2.1 h1:Q0Hk9Kp/Y4iwy9uR9e/60fEoxGhvfk8MG7WwtL9aarM= +github.com/fahedouch/go-logrotate v0.2.1/go.mod h1:Mmyex1f9fGXBNnhS9uHsbnO9BGvADF4VGqVnqAJalgc= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= @@ -421,6 +421,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 47f272d2c6202ba7cf539f9987a0e68df6520dc4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 22:47:04 +0000 Subject: [PATCH 0414/1066] build(deps): bump github.com/pelletier/go-toml/v2 from 2.2.0 to 2.2.1 Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.2.0 to 2.2.1. - [Release notes](https://github.com/pelletier/go-toml/releases) - [Changelog](https://github.com/pelletier/go-toml/blob/v2/.goreleaser.yaml) - [Commits](https://github.com/pelletier/go-toml/compare/v2.2.0...v2.2.1) --- updated-dependencies: - dependency-name: github.com/pelletier/go-toml/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 29080fbe6c4..2607e39de50 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/runtime-spec v1.2.0 - github.com/pelletier/go-toml/v2 v2.2.0 + github.com/pelletier/go-toml/v2 v2.2.1 github.com/rootless-containers/bypass4netns v0.4.1 github.com/rootless-containers/rootlesskit/v2 v2.0.2 github.com/spf13/cobra v1.8.0 diff --git a/go.sum b/go.sum index 40308f0b705..b84d027d157 100644 --- a/go.sum +++ b/go.sum @@ -266,8 +266,8 @@ github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaL github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= -github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg= +github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= From 03fd3c768a648ebfb115d284b9f05ab064a27484 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Apr 2024 01:37:44 +0000 Subject: [PATCH 0415/1066] build(deps): bump github.com/awslabs/soci-snapshotter Bumps [github.com/awslabs/soci-snapshotter](https://github.com/awslabs/soci-snapshotter) from 0.4.1 to 0.6.0. - [Release notes](https://github.com/awslabs/soci-snapshotter/releases) - [Changelog](https://github.com/awslabs/soci-snapshotter/blob/main/RELEASES.md) - [Commits](https://github.com/awslabs/soci-snapshotter/compare/v0.4.1...v0.6.0) --- updated-dependencies: - dependency-name: github.com/awslabs/soci-snapshotter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index b09f6137d9f..d9f45db048d 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.1 github.com/Microsoft/hcsshim v0.12.2 - github.com/awslabs/soci-snapshotter v0.4.1 + github.com/awslabs/soci-snapshotter v0.6.0 github.com/compose-spec/compose-go v1.20.2 github.com/containerd/accelerated-container-image v1.1.3 github.com/containerd/cgroups/v3 v3.0.3 diff --git a/go.sum b/go.sum index fbbbda7b75e..915985c781a 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.12.2 h1:AcXy+yfRvrx20g9v7qYaJv5Rh+8GaHOS6b8G6Wx/nKs= github.com/Microsoft/hcsshim v0.12.2/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= -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/awslabs/soci-snapshotter v0.6.0 h1:OUu0nco912cKxvy3Qvgpv/WoUyyWuyl27wkaj8REmYA= +github.com/awslabs/soci-snapshotter v0.6.0/go.mod h1:EOjvD4czW3repJ5+4We/+dOCknmV2Ba0ywdUzSwm/gw= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -275,8 +275,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rootless-containers/bypass4netns v0.4.1 h1:zyYM1uSG7/prAphD2vlJvx/MEKK91EjD2XaefGx5PKA= From a40d98d230cfa9fbcd69d9a8751bbb38bee62f43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 22:37:16 +0000 Subject: [PATCH 0416/1066] build(deps): bump github.com/containernetworking/cni from 1.1.2 to 1.2.0 Bumps [github.com/containernetworking/cni](https://github.com/containernetworking/cni) from 1.1.2 to 1.2.0. - [Release notes](https://github.com/containernetworking/cni/releases) - [Commits](https://github.com/containernetworking/cni/compare/v1.1.2...v1.2.0) --- updated-dependencies: - dependency-name: github.com/containernetworking/cni dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 53 ++++++----------------------------------------------- 2 files changed, 7 insertions(+), 48 deletions(-) diff --git a/go.mod b/go.mod index 08b2e21870b..cfc0347d2df 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/containerd/stargz-snapshotter/estargz v0.15.1 github.com/containerd/stargz-snapshotter/ipfs v0.15.1 github.com/containerd/typeurl/v2 v2.1.1 - github.com/containernetworking/cni v1.1.2 + github.com/containernetworking/cni v1.2.0 github.com/containernetworking/plugins v1.4.1 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 diff --git a/go.sum b/go.sum index 049df8f7815..76aea2d666d 100644 --- a/go.sum +++ b/go.sum @@ -19,9 +19,6 @@ github.com/awslabs/soci-snapshotter v0.6.0/go.mod h1:EOjvD4czW3repJ5+4We/+dOCknm github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y= github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -67,8 +64,8 @@ github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 h1:rQvjv7gRi6 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= github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= -github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ= -github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= +github.com/containernetworking/cni v1.2.0 h1:fEjhlfWwWAXEvlcMQu/i6z8DA0Kbu7EcmR5+zb6cm5I= +github.com/containernetworking/cni v1.2.0/go.mod h1:/r+vA/7vrynNfbvSP9g8tIKEoy6win7sALJAw4ZiJks= github.com/containernetworking/plugins v1.4.1 h1:+sJRRv8PKhLkXIl6tH1D7RMi+CbbHutDGU+ErLBORWA= github.com/containernetworking/plugins v1.4.1/go.mod h1:n6FFGKcaY4o2o5msgu/UImtoC+fpQXM3076VHfHbj60= github.com/containers/ocicrypt v1.1.10 h1:r7UR6o8+lyhkEywetubUUgcKFjOWOaWz8cEBrCPX0ic= @@ -115,8 +112,6 @@ github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/ml github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -124,7 +119,6 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -145,10 +139,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -161,7 +153,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 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= @@ -172,8 +163,6 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -241,20 +230,10 @@ github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM= -github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= -github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= +github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= +github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= +github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= +github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= 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 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -302,7 +281,6 @@ github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -374,17 +352,14 @@ golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.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= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= @@ -401,22 +376,14 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -442,7 +409,6 @@ golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= @@ -456,7 +422,6 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= @@ -492,17 +457,11 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 79897c8b20c0497b6b6db5179d931f4b794b0fff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 22:56:27 +0000 Subject: [PATCH 0417/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 26.0.1+incompatible to 26.0.2+incompatible. - [Commits](https://github.com/docker/cli/compare/v26.0.1...v26.0.2) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cfc0347d2df..f930572acd1 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.4 - github.com/docker/cli v26.0.1+incompatible + github.com/docker/cli v26.0.2+incompatible github.com/docker/docker v26.0.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 76aea2d666d..3a172ee0a5a 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v26.0.1+incompatible h1:eZDuplk2jYqgUkNLDYwTBxqmY9cM3yHnmN6OIUEjL3U= -github.com/docker/cli v26.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v26.0.2+incompatible h1:4C4U8ZqrlNDe/R1U1zFFX+YsCFiVUicJqo4WVdInJas= +github.com/docker/cli v26.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v26.0.1+incompatible h1:t39Hm6lpXuXtgkF0dm1t9a5HkbUfdGy6XbWexmGr+hA= github.com/docker/docker v26.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= From 199edf1aa7b7c85340e69697dc60b6c705cf9ad6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:42:38 +0000 Subject: [PATCH 0418/1066] build(deps): bump github.com/Microsoft/go-winio from 0.6.1 to 0.6.2 Bumps [github.com/Microsoft/go-winio](https://github.com/Microsoft/go-winio) from 0.6.1 to 0.6.2. - [Release notes](https://github.com/Microsoft/go-winio/releases) - [Commits](https://github.com/Microsoft/go-winio/compare/v0.6.1...v0.6.2) --- updated-dependencies: - dependency-name: github.com/Microsoft/go-winio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 +--- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index cfc0347d2df..8223de3f58a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/Masterminds/semver/v3 v3.2.1 - github.com/Microsoft/go-winio v0.6.1 + github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.2 github.com/awslabs/soci-snapshotter v0.6.0 github.com/compose-spec/compose-go v1.20.2 @@ -135,8 +135,6 @@ require ( go.opentelemetry.io/otel/metric v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/tools v0.17.0 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/grpc v1.62.0 // indirect diff --git a/go.sum b/go.sum index 76aea2d666d..ae5fe0d1969 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ 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/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.2 h1:AcXy+yfRvrx20g9v7qYaJv5Rh+8GaHOS6b8G6Wx/nKs= github.com/Microsoft/hcsshim v0.12.2/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= github.com/awslabs/soci-snapshotter v0.6.0 h1:OUu0nco912cKxvy3Qvgpv/WoUyyWuyl27wkaj8REmYA= @@ -348,8 +348,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.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From 0439917f13420c919a29a3bca4baa6ea7a037162 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:57:36 +0000 Subject: [PATCH 0419/1066] build(deps): bump actions/checkout from 4.1.2 to 4.1.3 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.2...v4.1.3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 91b21f4d474..b8f35ed66e6 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index de2c9162b32..1841c2ba2a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 - uses: actions/setup-go@v5 with: go-version: 1.21.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a17d60ed3d5..e5baba3e10a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -88,7 +88,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -118,7 +118,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: fetch-depth: 1 - name: Enable ipv4 and ipv6 forwarding @@ -194,7 +194,7 @@ jobs: ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -211,7 +211,7 @@ jobs: matrix: go-version: ["1.21.x", "1.22.x"] steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -226,7 +226,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 30 steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -263,7 +263,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -272,7 +272,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: repository: containerd/containerd ref: v1.7.15 @@ -295,7 +295,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 - uses: actions/cache@v4 with: path: /root/.vagrant.d From 6b047d2499b00bf4a216fbcb9b7ab52b6256fe40 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 18:54:57 +0000 Subject: [PATCH 0420/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.12.2 to 0.12.3 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.12.2 to 0.12.3. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.2...v0.12.3) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8223de3f58a..6103d693cd0 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.2 - github.com/Microsoft/hcsshim v0.12.2 + github.com/Microsoft/hcsshim v0.12.3 github.com/awslabs/soci-snapshotter v0.6.0 github.com/compose-spec/compose-go v1.20.2 github.com/containerd/accelerated-container-image v1.1.3 diff --git a/go.sum b/go.sum index ae5fe0d1969..27d194f6c63 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= 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.12.2 h1:AcXy+yfRvrx20g9v7qYaJv5Rh+8GaHOS6b8G6Wx/nKs= -github.com/Microsoft/hcsshim v0.12.2/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g= +github.com/Microsoft/hcsshim v0.12.3 h1:LS9NXqXhMoqNCplK1ApmVSfB4UnVLRDWRapB6EIlxE0= +github.com/Microsoft/hcsshim v0.12.3/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ= github.com/awslabs/soci-snapshotter v0.6.0 h1:OUu0nco912cKxvy3Qvgpv/WoUyyWuyl27wkaj8REmYA= github.com/awslabs/soci-snapshotter v0.6.0/go.mod h1:EOjvD4czW3repJ5+4We/+dOCknmV2Ba0ywdUzSwm/gw= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= From 8765df236a3ed27df913e6900882cdf6e48ed37e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 22:33:06 +0000 Subject: [PATCH 0421/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.0.1+incompatible to 26.1.0+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v26.0.1...v26.1.0) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2bf6796cb92..91c7d3b0380 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.4 github.com/docker/cli v26.0.2+incompatible - github.com/docker/docker v26.0.1+incompatible + github.com/docker/docker v26.1.0+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 36c8801a940..0c8aea5ae70 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/docker/cli v26.0.2+incompatible h1:4C4U8ZqrlNDe/R1U1zFFX+YsCFiVUicJqo4WVdInJas= github.com/docker/cli v26.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v26.0.1+incompatible h1:t39Hm6lpXuXtgkF0dm1t9a5HkbUfdGy6XbWexmGr+hA= -github.com/docker/docker v26.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.1.0+incompatible h1:W1G9MPNbskA6VZWL7b3ZljTh0pXI68FpINx0GKaOdaM= +github.com/docker/docker v26.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 4f46cf94b1319e66ab164fb4e1ef50db4ad90c4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 23:20:32 +0000 Subject: [PATCH 0422/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 26.0.2+incompatible to 26.1.0+incompatible. - [Commits](https://github.com/docker/cli/compare/v26.0.2...v26.1.0) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 91c7d3b0380..8ddd0a6b7ef 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.4 - github.com/docker/cli v26.0.2+incompatible + github.com/docker/cli v26.1.0+incompatible github.com/docker/docker v26.1.0+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 0c8aea5ae70..d7a8613fbd5 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v26.0.2+incompatible h1:4C4U8ZqrlNDe/R1U1zFFX+YsCFiVUicJqo4WVdInJas= -github.com/docker/cli v26.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v26.1.0+incompatible h1:+nwRy8Ocd8cYNQ60mozDDICICD8aoFGtlPXifX/UQ3Y= +github.com/docker/cli v26.1.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v26.1.0+incompatible h1:W1G9MPNbskA6VZWL7b3ZljTh0pXI68FpINx0GKaOdaM= github.com/docker/docker v26.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= From a279dfabb6296af586f0d30feac9292b97b1c535 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Apr 2024 22:14:44 +0000 Subject: [PATCH 0423/1066] build(deps): bump actions/checkout from 4.1.3 to 4.1.4 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.3 to 4.1.4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.3...v4.1.4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index b8f35ed66e6..6adf02841c9 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1841c2ba2a2..c07c0321624 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 - uses: actions/setup-go@v5 with: go-version: 1.21.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e5baba3e10a..c70e8add474 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -88,7 +88,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -118,7 +118,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: fetch-depth: 1 - name: Enable ipv4 and ipv6 forwarding @@ -194,7 +194,7 @@ jobs: ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -211,7 +211,7 @@ jobs: matrix: go-version: ["1.21.x", "1.22.x"] steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -226,7 +226,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 30 steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -263,7 +263,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -272,7 +272,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: repository: containerd/containerd ref: v1.7.15 @@ -295,7 +295,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 - uses: actions/cache@v4 with: path: /root/.vagrant.d From 93f404c7762d765e161669009d8726323aeb9e75 Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Thu, 25 Apr 2024 21:23:45 +0800 Subject: [PATCH 0424/1066] fix: error check in the ensureFile func Signed-off-by: guoguangwu --- pkg/dnsutil/hostsstore/hostsstore.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkg/dnsutil/hostsstore/hostsstore.go b/pkg/dnsutil/hostsstore/hostsstore.go index 1edb5256331..1efe3002f37 100644 --- a/pkg/dnsutil/hostsstore/hostsstore.go +++ b/pkg/dnsutil/hostsstore/hostsstore.go @@ -55,11 +55,7 @@ func ensureFile(path string) error { if err := os.MkdirAll(dir, 0700); err != nil { return err } - f, err := os.OpenFile(path, os.O_CREATE, 0644) - if err != nil { - f.Close() - } - return err + return os.WriteFile(path, []byte{}, 0644) } // AllocHostsFile is used for creating mount-bindable /etc/hosts file. From bd7fdb37726e4cb049053c3e006591af53dc6f31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 17:53:43 +0000 Subject: [PATCH 0425/1066] build(deps): bump github.com/containerd/containerd from 1.7.15 to 1.7.16 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.15 to 1.7.16. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.15...v1.7.16) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5fecf60258e..8cccfffbe91 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.1.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd v1.7.15 + github.com/containerd/containerd v1.7.16 github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 diff --git a/go.sum b/go.sum index efcf931f579..69e1e922b7a 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ 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.15 h1:afEHXdil9iAm03BmhjzKyXnnEBtjaLJefdU7DV0IFes= -github.com/containerd/containerd v1.7.15/go.mod h1:ISzRRTMF8EXNpJlTzyr2XMhN+j9K302C21/+cr3kUnY= +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/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= From a4f2ed07bf0d95921f7d70dbebd8989a77ce774b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 22:14:50 +0000 Subject: [PATCH 0426/1066] build(deps): bump golangci/golangci-lint-action from 4.0.0 to 5.0.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 4.0.0 to 5.0.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v4.0.0...v5.0.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c70e8add474..e1c25684fba 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,7 +46,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v4.0.0 + uses: golangci/golangci-lint-action@v5.0.0 with: version: v1.55.2 args: --verbose From 47053926b8493d068253a4c5833cd7883dd7b858 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 26 Apr 2024 10:33:51 +0900 Subject: [PATCH 0427/1066] update containerd (1.7.16) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 18 +++++++++--------- Dockerfile | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e1c25684fba..28d9ce471a0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,9 +79,9 @@ jobs: - ubuntu: 20.04 containerd: v1.6.31 - ubuntu: 20.04 - containerd: v1.7.15 + containerd: v1.7.16 - ubuntu: 22.04 - containerd: v1.7.15 + containerd: v1.7.16 - ubuntu: 22.04 containerd: main env: @@ -113,7 +113,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 22.04 - containerd: v1.7.15 + containerd: v1.7.16 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -161,11 +161,11 @@ jobs: rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.15 + containerd: v1.7.16 rootlesskit: v2.0.2 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.15 + containerd: v1.7.16 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 @@ -177,11 +177,11 @@ jobs: rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.15 + containerd: v1.7.16 rootlesskit: v2.0.2 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.15 + containerd: v1.7.16 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 @@ -275,7 +275,7 @@ jobs: - uses: actions/checkout@v4.1.4 with: repository: containerd/containerd - ref: v1.7.15 + ref: v1.7.16 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -283,7 +283,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.15 + ctrdVersion: 1.7.16 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index 8de873343bf..4217a13f708 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.15 +ARG CONTAINERD_VERSION=v1.7.16 ARG RUNC_VERSION=v1.1.12 ARG CNI_PLUGINS_VERSION=v1.4.1 From e9535e52165a9edf0d4d8fd0666dc11b8bf242d4 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 26 Apr 2024 10:35:05 +0900 Subject: [PATCH 0428/1066] update BuildKit (0.13.2) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.1 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.2 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.2 diff --git a/Dockerfile b/Dockerfile index 4217a13f708..c5779289451 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.12 ARG CNI_PLUGINS_VERSION=v1.4.1 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.13.1 +ARG BUILDKIT_VERSION=v0.13.2 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.1 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.1 deleted file mode 100644 index df2b9d75ce8..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.1 +++ /dev/null @@ -1,2 +0,0 @@ -5d4a6ef438851d7a0b22d17c7e806651c24c0982ddd6af8c02117fca84f167ec buildkit-v0.13.1.linux-amd64.tar.gz -9e1478af43ba7ac6635cae30a8dda3ebce4dca70a8def939ac64ee395d03d647 buildkit-v0.13.1.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.2 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.2 new file mode 100644 index 00000000000..cd252075f04 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.2 @@ -0,0 +1,2 @@ +9cd121931b015f05d7e4337f08272e36a83f69724c40141947eb11246ca0bb9d buildkit-v0.13.2.linux-amd64.tar.gz +bcc4cb4fec79847682fbb2ce8f612e5e854636ae6c262cee4b657d2b5c2fd46c buildkit-v0.13.2.linux-arm64.tar.gz From f34b02adf50b7acf6fb6898eb38888c3b64d6c74 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 26 Apr 2024 10:26:07 +0900 Subject: [PATCH 0429/1066] update slirp4netns (1.3.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.3 | 7 ------- Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.0 | 7 +++++++ 3 files changed, 8 insertions(+), 8 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.3 create mode 100644 Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.0 diff --git a/Dockerfile b/Dockerfile index c5779289451..59f5b3e49d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 ARG IMGCRYPT_VERSION=v1.1.10 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v2.0.2 -ARG SLIRP4NETNS_VERSION=v1.2.3 +ARG SLIRP4NETNS_VERSION=v1.3.0 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.4.1 # Extra deps: FUSE-OverlayFS diff --git a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.3 b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.3 deleted file mode 100644 index a2ac3e552f6..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.2.3 +++ /dev/null @@ -1,7 +0,0 @@ -5ccf6a6cabc312d33332709486ea90110f4608b8371954d6dc2a1ed865457f92 SOURCE_DATE_EPOCH -289b0838f849da0d6d5de596e6c5010fbb134a2912d3cc32a0e2e2b759543278 slirp4netns-aarch64 -43db5430758edb8d095a0923dcbf2757a2fded9f22aa851d18aad9b82c245fb6 slirp4netns-armv7l -fe565401ffefa1c4f1e6c141788405825ae5513e0bb1122bdfe6acdd00be9e71 slirp4netns-ppc64le -cb9f92d496541b9ee2163bd64d522bf82a4136ccbbb01e3883be078a5e65af6f slirp4netns-riscv64 -09e68bd9707fdab67884256bea5ca09ae9057a4ebf3f8382e369602c7ae21734 slirp4netns-s390x -2051ae25baba59c96f42bf2b7b7efa2eabb022e497b6c4b692b1428d2b2d1f5b slirp4netns-x86_64 diff --git a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.0 b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.0 new file mode 100644 index 00000000000..2436371bfaf --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.0 @@ -0,0 +1,7 @@ +c9e31a24ef0860d95b1325c279bc5c5c6282202f3e5dc831e77c1f899e5cb712 SOURCE_DATE_EPOCH +1c1088a05a325f6f33186bab581544c4c06b76ccf7fb816c8cf655a682400a4e slirp4netns-aarch64 +45f465349619f802488e8b429af67a640cb01c77e595163a886c14836a0ebbb2 slirp4netns-armv7l +39711aecf50e4dc23380eda6380b8640f5cd3417a2c2dfa1ca4bf549387b185c slirp4netns-ppc64le +c07219d84640a1da3846a279199c4fda36437185709d4344e605dc98a37b30b6 slirp4netns-riscv64 +49165a25cb89fd08f2fd748884ec6fb7a016dc20c1c2cf22ee039c0d3c2e870d slirp4netns-s390x +bb4da29ad800d0f63ccac6dc5ca92d20d796f25fa2ba0c0be08c629b400f837e slirp4netns-x86_64 From bb6f9e6694dd6073fb9ce0f883eb7deab13d9489 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 26 Apr 2024 10:33:02 +0900 Subject: [PATCH 0430/1066] update RootlessKit (2.1.0) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 8 ++++---- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.2 | 6 ------ Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.1.0 | 6 ++++++ 4 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.2 create mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.1.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 28d9ce471a0..c30b0662fe1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -162,7 +162,7 @@ jobs: target: test-integration-rootless - ubuntu: 20.04 containerd: v1.7.16 - rootlesskit: v2.0.2 + rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 22.04 containerd: v1.7.16 @@ -170,7 +170,7 @@ jobs: target: test-integration-rootless - ubuntu: 22.04 containerd: main - rootlesskit: v2.0.2 + rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 20.04 containerd: v1.6.31 @@ -178,7 +178,7 @@ jobs: target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 containerd: v1.7.16 - rootlesskit: v2.0.2 + rootlesskit: v2.1.0 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: v1.7.16 @@ -186,7 +186,7 @@ jobs: target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 containerd: main - rootlesskit: v2.0.2 + rootlesskit: v2.1.0 target: test-integration-rootless-port-slirp4netns env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" diff --git a/Dockerfile b/Dockerfile index 59f5b3e49d1..cd87106a152 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption ARG IMGCRYPT_VERSION=v1.1.10 # Extra deps: Rootless -ARG ROOTLESSKIT_VERSION=v2.0.2 +ARG ROOTLESSKIT_VERSION=v2.1.0 ARG SLIRP4NETNS_VERSION=v1.3.0 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.4.1 diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.2 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.2 deleted file mode 100644 index 4e284401a0e..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.0.2 +++ /dev/null @@ -1,6 +0,0 @@ -4dafc86e1cbee2fbedac6822bf46e459d54ec998803d273f535b67a6e62edb30 rootlesskit-aarch64.tar.gz -c633c5e7f84d3390c4ebe8102af0cd8bdecd1f10e9fc007036636ef94d95b449 rootlesskit-armv7l.tar.gz -598a2c685cd383ba1abd3bf20a5c1bd55c283ceea1b3a9479c76f0fb96df75d5 rootlesskit-ppc64le.tar.gz -af9bbb79de33b0b3f901b3848341ae4b05ca4e0838f103044f082aab91f3b7f5 rootlesskit-riscv64.tar.gz -b1539a7f8059150f8dfdfc4de3a2714a199c09fdfe9c7670ce69824b8fdad7b9 rootlesskit-s390x.tar.gz -a218beb65d243183d13024a8b18fc08543e238ef38d306166e8375bde0efd57c rootlesskit-x86_64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.1.0 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.1.0 new file mode 100644 index 00000000000..c60be289879 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.1.0 @@ -0,0 +1,6 @@ +b3a9b14b66f54351a2b9f8c0917062bfeab2dc89e9e7cb15f4cf0684a4a7281f rootlesskit-aarch64.tar.gz +6fd0be2aa10d7533e41f4013ee8f7e2779c16c6091a02d150d7998da16b6292a rootlesskit-armv7l.tar.gz +43c6fa763d61c3cb49216821009b1b7e6dcd5ba97a57ef8c2762a7ffbd317556 rootlesskit-ppc64le.tar.gz +914cdfb02a207a68b038a64871849dc0586242dd2cd3775de58e6a7c661f3c60 rootlesskit-riscv64.tar.gz +185c86ef5758ded11c685d725642f2bcb6fc27dbb450ed2fbd857347fb5d301b rootlesskit-s390x.tar.gz +1e4609a3d0ca67c4fc99fe9121870cf5ca46a438f43b151e9b54456d166f4b10 rootlesskit-x86_64.tar.gz From ff6c1c497c8853a5fb00368b902558f3c9673cbf Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 26 Apr 2024 10:36:06 +0900 Subject: [PATCH 0431/1066] skip Kubo 0.28.0 Kubo >= 0.28 needs Go 1.22, but runc is still incompatible with Go 1.22 Signed-off-by: Akihiro Suda --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index cd87106a152..4b21ff1dc0d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,6 +37,8 @@ ARG BYPASS4NETNS_VERSION=v0.4.1 ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 # Extra deps: IPFS +# Kubo >= 0.28 needs Go 1.22, but runc is still incompatible with Go 1.22 +# https://github.com/opencontainers/runc/issues/4233 ARG KUBO_VERSION=v0.27.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 From 54b2956415ffce6b1172bdf0dbf571f9486721a1 Mon Sep 17 00:00:00 2001 From: baijia Date: Fri, 26 Apr 2024 19:17:52 +0800 Subject: [PATCH 0432/1066] fix: set mountpoint RW and Propagation in internal mount label Signed-off-by: baijia --- cmd/nerdctl/container_inspect_linux_test.go | 20 +++++++++++++++++++ pkg/cmd/container/create.go | 1 + pkg/inspecttypes/dockercompat/dockercompat.go | 11 ++-------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/cmd/nerdctl/container_inspect_linux_test.go b/cmd/nerdctl/container_inspect_linux_test.go index 7c1cc721543..58ceb359d74 100644 --- a/cmd/nerdctl/container_inspect_linux_test.go +++ b/cmd/nerdctl/container_inspect_linux_test.go @@ -22,6 +22,7 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/docker/go-connections/nat" "gotest.tools/v3/assert" @@ -156,6 +157,25 @@ func TestContainerInspectContainsLabel(t *testing.T) { assert.Equal(base.T, "bar", lbs["bar"]) } +func TestContainerInspectContainsInternalLabel(t *testing.T) { + testutil.DockerIncompatible(t) + t.Parallel() + testContainer := testutil.Identifier(t) + + base := testutil.NewBase(t) + defer base.Cmd("rm", "-f", testContainer).Run() + + base.Cmd("run", "-d", "--name", testContainer, "--mount", "type=bind,src=/tmp,dst=/app,readonly=false,bind-propagation=rprivate", testutil.NginxAlpineImage).AssertOK() + base.EnsureContainerStarted(testContainer) + inspect := base.InspectContainer(testContainer) + lbs := inspect.Config.Labels + + // TODO: add more internal labels testcases + labelMount := lbs[labels.Mounts] + expectedLabelMount := "[{\"Type\":\"bind\",\"Source\":\"/tmp\",\"Destination\":\"/app\",\"Mode\":\"rprivate,rbind\",\"RW\":true,\"Propagation\":\"rprivate\"}]" + assert.Equal(base.T, expectedLabelMount, labelMount) +} + func TestContainerInspectState(t *testing.T) { t.Parallel() testContainer := testutil.Identifier(t) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index eb680fd0a6b..3b7e6ff7c70 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -683,6 +683,7 @@ func dockercompatMounts(mountPoints []*mountutil.Processed) []dockercompat.Mount Driver: "", Mode: mp.Mode, } + result[i].RW, result[i].Propagation = dockercompat.ParseMountProperties(strings.Split(mp.Mode, ",")) // it's an anonymous volume if mp.AnonymousVolume != "" { diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index a344a2e9ec3..032856173e2 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -32,7 +32,6 @@ import ( "path/filepath" "runtime" "strconv" - "strings" "time" "github.com/containerd/containerd" @@ -485,18 +484,12 @@ func parseMounts(nerdctlMounts string) ([]MountPoint, error) { return nil, err } - for i := range mounts { - rw, propagation := parseMountProperties(mounts[i].Mode) - mounts[i].RW = rw - mounts[i].Propagation = propagation - } - return mounts, nil } -func parseMountProperties(option string) (rw bool, propagation string) { +func ParseMountProperties(option []string) (rw bool, propagation string) { rw = true - for _, opt := range strings.Split(option, ",") { + for _, opt := range option { switch opt { case "ro", "rro": rw = false From 2c1d745b0cb92862f3b04c3087631a8c1fe780ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Apr 2024 22:42:30 +0000 Subject: [PATCH 0433/1066] build(deps): bump github.com/rootless-containers/rootlesskit/v2 Bumps [github.com/rootless-containers/rootlesskit/v2](https://github.com/rootless-containers/rootlesskit) from 2.0.2 to 2.1.0. - [Release notes](https://github.com/rootless-containers/rootlesskit/releases) - [Commits](https://github.com/rootless-containers/rootlesskit/compare/v2.0.2...v2.1.0) --- updated-dependencies: - dependency-name: github.com/rootless-containers/rootlesskit/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8cccfffbe91..e224d26eba6 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/opencontainers/runtime-spec v1.2.0 github.com/pelletier/go-toml/v2 v2.2.1 github.com/rootless-containers/bypass4netns v0.4.1 - github.com/rootless-containers/rootlesskit/v2 v2.0.2 + github.com/rootless-containers/rootlesskit/v2 v2.1.0 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/tidwall/gjson v1.17.1 diff --git a/go.sum b/go.sum index 69e1e922b7a..376c0963e16 100644 --- a/go.sum +++ b/go.sum @@ -260,8 +260,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rootless-containers/bypass4netns v0.4.1 h1:zyYM1uSG7/prAphD2vlJvx/MEKK91EjD2XaefGx5PKA= github.com/rootless-containers/bypass4netns v0.4.1/go.mod h1:slu3ygwy1x6ey78oBTNs7lpymyEimLBYoXOG76b+Q+Y= -github.com/rootless-containers/rootlesskit/v2 v2.0.2 h1:wztWcDYFlk+EVAUuPJwlNMFXZIk1G14T45lv47WWGuA= -github.com/rootless-containers/rootlesskit/v2 v2.0.2/go.mod h1:hE+ztevrQxNi+tdZyPKumzDk7VKDAf0E4seOzlOyBsY= +github.com/rootless-containers/rootlesskit/v2 v2.1.0 h1:dKqduSlzo5TlTv7tTIoTct2cRUNQf+soqcs+6b1ynvE= +github.com/rootless-containers/rootlesskit/v2 v2.1.0/go.mod h1:W+5NaXv3l2sD4LiPxRWLOlY+p9H0+Ev71zel/zFRnLo= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= From ad6073623f60b18185c47dbb7fb402785c53b6db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Apr 2024 22:42:35 +0000 Subject: [PATCH 0434/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.11 to 0.13.12. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.11...v0.13.12) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8cccfffbe91..0fd4d49a5a1 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.10 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.11 + github.com/containerd/nydus-snapshotter v0.13.12 github.com/containerd/platforms v0.1.1 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 diff --git a/go.sum b/go.sum index 69e1e922b7a..57b887a7ff0 100644 --- a/go.sum +++ b/go.sum @@ -48,8 +48,8 @@ github.com/containerd/imgcrypt v1.1.10 h1:vtyGzTna2wC5BSQcqHWgY4xsBLHWFWyecgK0+9 github.com/containerd/imgcrypt v1.1.10/go.mod h1:9eIPG34EQy+j00fr+4r0knul2MkYDKD2uzKkw8548aw= 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.11 h1:0euz1viJ0/4sZ5P0GP28wKrd+m0YqKRQcM6GZjuSKZk= -github.com/containerd/nydus-snapshotter v0.13.11/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= +github.com/containerd/nydus-snapshotter v0.13.12 h1:xShPWHz7rCi8AG4Z5Q3EzyEgFqW/y8h5tczYAwK0r24= +github.com/containerd/nydus-snapshotter v0.13.12/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= github.com/containerd/platforms v0.1.1 h1:gp0xXBoY+1CjH54gJDon0kBjIbK2C4XSX1BGwP5ptG0= github.com/containerd/platforms v0.1.1/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= github.com/containerd/stargz-snapshotter v0.15.1 h1:fpsP4kf/Z4n2EYnU0WT8ZCE3eiKDwikDhL6VwxIlgeA= From 49993c5bff0970c45e5681df08d9eec13db141b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 22:02:54 +0000 Subject: [PATCH 0435/1066] build(deps): bump golangci/golangci-lint-action from 5.0.0 to 5.1.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 5.0.0 to 5.1.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v5.0.0...v5.1.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c30b0662fe1..b06a7e0b20e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,7 +46,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v5.0.0 + uses: golangci/golangci-lint-action@v5.1.0 with: version: v1.55.2 args: --verbose From 4e615922c484817898c81f4c70cbf6abeb8a89f9 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sat, 4 May 2024 13:14:14 +0900 Subject: [PATCH 0436/1066] CI: use Go 1.22 The main branch of containerd now depends on Go 1.22, so we have to upgrade the CI to Go 1.22. The runc binary is still built with Go 1.21 due to opencontainers/runc issue 4233. Signed-off-by: Akihiro Suda --- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 2 +- Dockerfile | 20 ++++++++++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c07c0321624..0d4a72fa802 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v4.1.4 - uses: actions/setup-go@v5 with: - go-version: 1.21.x + go-version: 1.22.x - name: "Compile binaries" run: make artifacts - name: "SHA256SUMS" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b06a7e0b20e..d16f1fdab55 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ on: pull_request: env: - GO_VERSION: 1.21.x + GO_VERSION: 1.22.x jobs: project: diff --git a/Dockerfile b/Dockerfile index 4b21ff1dc0d..b523bae90bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,8 +37,6 @@ ARG BYPASS4NETNS_VERSION=v0.4.1 ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 # Extra deps: IPFS -# Kubo >= 0.28 needs Go 1.22, but runc is still incompatible with Go 1.22 -# https://github.com/opencontainers/runc/issues/4233 ARG KUBO_VERSION=v0.27.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 @@ -46,7 +44,7 @@ ARG TINI_VERSION=v0.19.0 ARG BUILDG_VERSION=v0.4.1 # Test deps -ARG GO_VERSION=1.21 +ARG GO_VERSION=1.22 ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.11.0 @@ -67,6 +65,18 @@ ARG TARGETARCH RUN xx-apt-get update && \ xx-apt-get install -y binutils gcc libc6-dev libbtrfs-dev libseccomp-dev +# runc still requires Go 1.21 +# https://github.com/opencontainers/runc/issues/4233 +FROM --platform=$BUILDPLATFORM golang:1.21-bullseye AS build-base-debian-go121 +COPY --from=xx / / +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && \ + apt-get install -y git pkg-config dpkg-dev +ARG TARGETARCH +# libseccomp: for runc +RUN xx-apt-get update && \ + xx-apt-get install -y binutils gcc libc6-dev libseccomp-dev + FROM build-base-debian AS build-containerd ARG TARGETARCH ARG CONTAINERD_VERSION @@ -78,7 +88,9 @@ RUN git checkout ${CONTAINERD_VERSION} && \ RUN GO=xx-go make STATIC=1 && \ cp -a bin/containerd bin/containerd-shim-runc-v2 bin/ctr /out/$TARGETARCH -FROM build-base-debian AS build-runc +# runc still requires Go 1.21 +# https://github.com/opencontainers/runc/issues/4233 +FROM build-base-debian-go121 AS build-runc ARG RUNC_VERSION ARG TARGETARCH RUN git clone https://github.com/opencontainers/runc.git /go/src/github.com/opencontainers/runc From 618639b33167b447d575f6ea5c743451cdf27387 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 May 2024 11:53:05 +0000 Subject: [PATCH 0437/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.2.4 to 0.2.5. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.2.4...v0.2.5) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 72f171b2c23..6a3393c0de4 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/containernetworking/plugins v1.4.1 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.2.4 + github.com/cyphar/filepath-securejoin v0.2.5 github.com/docker/cli v26.1.0+incompatible github.com/docker/docker v26.1.0+incompatible github.com/docker/go-connections v0.5.0 diff --git a/go.sum b/go.sum index dbca7320682..aca7e5b3d41 100644 --- a/go.sum +++ b/go.sum @@ -77,8 +77,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= +github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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= From c6c4a7bde855f59d77a07addad6a5301350c2271 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 May 2024 11:53:23 +0000 Subject: [PATCH 0438/1066] build(deps): bump github.com/pelletier/go-toml/v2 from 2.2.1 to 2.2.2 Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.2.1 to 2.2.2. - [Release notes](https://github.com/pelletier/go-toml/releases) - [Changelog](https://github.com/pelletier/go-toml/blob/v2/.goreleaser.yaml) - [Commits](https://github.com/pelletier/go-toml/compare/v2.2.1...v2.2.2) --- updated-dependencies: - dependency-name: github.com/pelletier/go-toml/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 72f171b2c23..1ed7566bbca 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/runtime-spec v1.2.0 - github.com/pelletier/go-toml/v2 v2.2.1 + github.com/pelletier/go-toml/v2 v2.2.2 github.com/rootless-containers/bypass4netns v0.4.1 github.com/rootless-containers/rootlesskit/v2 v2.1.0 github.com/spf13/cobra v1.8.0 diff --git a/go.sum b/go.sum index dbca7320682..57f384953bb 100644 --- a/go.sum +++ b/go.sum @@ -245,8 +245,8 @@ github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaL github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg= -github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= From 227505cea75a68fa72f9e419b0e5988149f53293 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 May 2024 18:57:13 +0000 Subject: [PATCH 0439/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.1.0+incompatible to 26.1.1+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v26.1.0...v26.1.1) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index df85ad6a473..efa316acbc5 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 github.com/docker/cli v26.1.0+incompatible - github.com/docker/docker v26.1.0+incompatible + github.com/docker/docker v26.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index bb99ef49b25..6cc634d88a5 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/docker/cli v26.1.0+incompatible h1:+nwRy8Ocd8cYNQ60mozDDICICD8aoFGtlPXifX/UQ3Y= github.com/docker/cli v26.1.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v26.1.0+incompatible h1:W1G9MPNbskA6VZWL7b3ZljTh0pXI68FpINx0GKaOdaM= -github.com/docker/docker v26.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.1.1+incompatible h1:oI+4kkAgIwwb54b9OC7Xc3hSgu1RlJA/Lln/DF72djQ= +github.com/docker/docker v26.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From d197e5b78b38b56de68dbde6dcb7d2454eae2121 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 May 2024 09:23:33 +0000 Subject: [PATCH 0440/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 26.1.0+incompatible to 26.1.1+incompatible. - [Commits](https://github.com/docker/cli/compare/v26.1.0...v26.1.1) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index efa316acbc5..9a123207a46 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 - github.com/docker/cli v26.1.0+incompatible + github.com/docker/cli v26.1.1+incompatible github.com/docker/docker v26.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 6cc634d88a5..421c4dd98b5 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v26.1.0+incompatible h1:+nwRy8Ocd8cYNQ60mozDDICICD8aoFGtlPXifX/UQ3Y= -github.com/docker/cli v26.1.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v26.1.1+incompatible h1:bE1/uE2tCa08fMv+7ikLR/RDPoCqytwrLtkIkSzxLvw= +github.com/docker/cli v26.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v26.1.1+incompatible h1:oI+4kkAgIwwb54b9OC7Xc3hSgu1RlJA/Lln/DF72djQ= github.com/docker/docker v26.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= From 4b9de97da767e9eb8df07ae5c76805a31d8295f4 Mon Sep 17 00:00:00 2001 From: baijia Date: Mon, 6 May 2024 14:05:37 +0800 Subject: [PATCH 0441/1066] inspect: show mounts info from CRI/ctr containers Fix #2934 Containers created by CRI or ctr with bind mounts don't have label "nerdct/mounts". However, 'inspect' with dockercompat mode only parses mounts from label "nerdct/mounts". After this patch, 'inspect' with dockercompat mode can show CRI and ctr container bind mounts. ResolvConfPath, HostnamePath and Hostname are taken to the same consideration. Signed-off-by: baijia --- pkg/inspecttypes/dockercompat/dockercompat.go | 51 +++- .../dockercompat/dockercompat_test.go | 236 ++++++++++++++++++ 2 files changed, 279 insertions(+), 8 deletions(-) create mode 100644 pkg/inspecttypes/dockercompat/dockercompat_test.go diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index 032856173e2..da9f714c9df 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -32,6 +32,7 @@ import ( "path/filepath" "runtime" "strconv" + "strings" "time" "github.com/containerd/containerd" @@ -210,6 +211,7 @@ type NetworkEndpointSettings struct { // ContainerFromNative instantiates a Docker-compatible Container from containerd-native Container. func ContainerFromNative(n *native.Container) (*Container, error) { + var hostname string c := &Container{ ID: n.ID, Created: n.CreatedAt.Format(time.RFC3339Nano), @@ -231,15 +233,24 @@ func ContainerFromNative(n *native.Container) (*Container, error) { } c.AppArmorProfile = p.ApparmorProfile } + c.Mounts = mountsFromNative(sp.Mounts) + for _, mount := range c.Mounts { + if mount.Destination == "/etc/resolv.conf" { + c.ResolvConfPath = mount.Source + } else if mount.Destination == "/etc/hostname" { + c.HostnamePath = mount.Source + } + } + hostname = sp.Hostname } if nerdctlStateDir := n.Labels[labels.StateDir]; nerdctlStateDir != "" { - c.ResolvConfPath = filepath.Join(nerdctlStateDir, "resolv.conf") - if _, err := os.Stat(c.ResolvConfPath); err != nil { - c.ResolvConfPath = "" + resolvConfPath := filepath.Join(nerdctlStateDir, "resolv.conf") + if _, err := os.Stat(resolvConfPath); err == nil { + c.ResolvConfPath = resolvConfPath } - c.HostnamePath = filepath.Join(nerdctlStateDir, "hostname") - if _, err := os.Stat(c.HostnamePath); err != nil { - c.HostnamePath = "" + hostnamePath := filepath.Join(nerdctlStateDir, "hostname") + if _, err := os.Stat(hostnamePath); err == nil { + c.HostnamePath = hostnamePath } c.LogPath = filepath.Join(nerdctlStateDir, n.ID+"-json.log") if _, err := os.Stat(c.LogPath); err != nil { @@ -273,9 +284,12 @@ func ContainerFromNative(n *native.Container) (*Container, error) { } c.State = cs c.Config = &Config{ - Hostname: n.Labels[labels.Hostname], - Labels: n.Labels, + Labels: n.Labels, + } + if n.Labels[labels.Hostname] != "" { + hostname = n.Labels[labels.Hostname] } + c.Config.Hostname = hostname return c, nil } @@ -323,6 +337,27 @@ func ImageFromNative(n *native.Image) (*Image, error) { i.Size = n.Size return i, nil } + +// mountsFromNative only filters bind mount to transform from native container. +// Because native container shows all types of mounts, such as tmpfs, proc, sysfs. +func mountsFromNative(spMounts []specs.Mount) []MountPoint { + mountpoints := make([]MountPoint, 0, len(spMounts)) + for _, m := range spMounts { + var mp MountPoint + if m.Type != "bind" { + continue + } + mp.Type = m.Type + mp.Source = m.Source + mp.Destination = m.Destination + mp.Mode = strings.Join(m.Options, ",") + mp.RW, mp.Propagation = ParseMountProperties(m.Options) + mountpoints = append(mountpoints, mp) + } + + return mountpoints +} + func statusFromNative(x containerd.Status, labels map[string]string) string { switch s := x.Status; s { case containerd.Stopped: diff --git a/pkg/inspecttypes/dockercompat/dockercompat_test.go b/pkg/inspecttypes/dockercompat/dockercompat_test.go new file mode 100644 index 00000000000..1c772c4daa3 --- /dev/null +++ b/pkg/inspecttypes/dockercompat/dockercompat_test.go @@ -0,0 +1,236 @@ +/* + 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 ( + "os" + "path/filepath" + "runtime" + "testing" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/containers" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + + "github.com/opencontainers/runtime-spec/specs-go" + "gotest.tools/v3/assert" +) + +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", + }, + }, + }, + // 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: "/mock-sandbox-dir/resolv.conf", + HostnamePath: "/mock-sandbox-dir/hostname", + State: &ContainerState{ + Status: "running", + Running: true, + Pid: 10000, + FinishedAt: "0001-01-01T00:00:00Z", + }, + Mounts: []MountPoint{ + { + Type: "bind", + Source: "/mock-sandbox-dir/resolv.conf", + Destination: "/etc/resolv.conf", + Mode: "rbind,rprivate,rw", + RW: true, + Propagation: "rprivate", + }, + { + Type: "bind", + Source: "/mock-sandbox-dir/hostname", + Destination: "/etc/hostname", + Mode: "rbind,rprivate,rw", + RW: true, + Propagation: "rprivate", + }, + { + Type: "bind", + Source: "/mnt/foo", + Destination: "/mnt/foo", + Mode: "rbind,rslave,rw", + RW: true, + Propagation: "rslave", + }, + // ignore sysfs mountpoint + }, + Config: &Config{}, + }, + }, + // 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: "host1", + 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", + }, + Mounts: []MountPoint{ + { + Type: "bind", + Source: "/mnt/foo", + Destination: "/mnt/foo", + Mode: "rbind,rslave,rw", + RW: true, + Propagation: "rslave", + }, + // ignore sysfs mountpoint + }, + Config: &Config{ + Hostname: "host1", + }, + }, + }, + } + + for _, tc := range testcase { + d, _ := ContainerFromNative(tc.n) + assert.DeepEqual(t, d, tc.expected) + } +} From 83382d5bcc9d4c61e7a4dfad6b4f6744343e502a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 22:45:03 +0000 Subject: [PATCH 0442/1066] build(deps): bump golang.org/x/net from 0.24.0 to 0.25.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.24.0 to 0.25.0. - [Commits](https://github.com/golang/net/compare/v0.24.0...v0.25.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 10 +++++----- go.sum | 19 ++++++++++--------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 9a123207a46..e87f33d88b3 100644 --- a/go.mod +++ b/go.mod @@ -55,12 +55,12 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.22.0 - golang.org/x/net v0.24.0 + golang.org/x/crypto v0.23.0 + golang.org/x/net v0.25.0 golang.org/x/sync v0.7.0 - golang.org/x/sys v0.19.0 - golang.org/x/term v0.19.0 - golang.org/x/text v0.14.0 + golang.org/x/sys v0.20.0 + golang.org/x/term v0.20.0 + golang.org/x/text v0.15.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) diff --git a/go.sum b/go.sum index 421c4dd98b5..851ed1fa027 100644 --- a/go.sum +++ b/go.sum @@ -336,8 +336,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= @@ -361,8 +361,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -396,22 +396,23 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From c17badbc6170e5c982b8ba9b7089db5dc49f7d5d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 22:17:16 +0000 Subject: [PATCH 0443/1066] build(deps): bump golangci/golangci-lint-action from 5.1.0 to 6.0.1 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 5.1.0 to 6.0.1. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v5.1.0...v6.0.1) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d16f1fdab55..8d119b8e6dc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,7 +46,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v5.1.0 + uses: golangci/golangci-lint-action@v6.0.1 with: version: v1.55.2 args: --verbose From 516503a0a2c5cff2a6b3c6d803ec9e07e598df1f Mon Sep 17 00:00:00 2001 From: Florian Wilhelm <52838694+fwilhe2@users.noreply.github.com> Date: Thu, 9 May 2024 00:54:40 +0200 Subject: [PATCH 0444/1066] Fix markdown link Just a tiny fix for markdown syntax to render a link correctly Signed-off-by: Florian Wilhelm <52838694+fwilhe2@users.noreply.github.com> --- docs/rootless.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rootless.md b/docs/rootless.md index 5b9333ebabc..2c0ee7cab5b 100644 --- a/docs/rootless.md +++ b/docs/rootless.md @@ -109,7 +109,7 @@ See https://github.com/containerd/stargz-snapshotter/blob/main/docs/pre-converte |-------------------|-----------------| -[bypass4netns(https://github.com/rootless-containers/bypass4netns)](https://github.com/rootless-containers/bypass4netns) is an accelerator for rootless networking. +[bypass4netns](https://github.com/rootless-containers/bypass4netns) is an accelerator for rootless networking. This improves **outgoing or incoming (with --publish option) networking performance.** From 41bf4414c36da6a27dcc4aade69cb25617654174 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 22:52:38 +0000 Subject: [PATCH 0445/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.1.1+incompatible to 26.1.2+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v26.1.1...v26.1.2) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e87f33d88b3..3308c73d754 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 github.com/docker/cli v26.1.1+incompatible - github.com/docker/docker v26.1.1+incompatible + github.com/docker/docker v26.1.2+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 851ed1fa027..827c18217de 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/docker/cli v26.1.1+incompatible h1:bE1/uE2tCa08fMv+7ikLR/RDPoCqytwrLtkIkSzxLvw= github.com/docker/cli v26.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v26.1.1+incompatible h1:oI+4kkAgIwwb54b9OC7Xc3hSgu1RlJA/Lln/DF72djQ= -github.com/docker/docker v26.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.1.2+incompatible h1:UVX5ZOrrfTGZZYEP+ZDq3Xn9PdHNXaSYMFPDumMqG2k= +github.com/docker/docker v26.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 926b88f37f4437012e49015984648e7f016a1c4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 22:52:51 +0000 Subject: [PATCH 0446/1066] build(deps): bump github.com/containerd/platforms from 0.1.1 to 0.2.0 Bumps [github.com/containerd/platforms](https://github.com/containerd/platforms) from 0.1.1 to 0.2.0. - [Release notes](https://github.com/containerd/platforms/releases) - [Commits](https://github.com/containerd/platforms/compare/v0.1.1...v0.2.0) --- updated-dependencies: - dependency-name: github.com/containerd/platforms dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e87f33d88b3..cfc4a906821 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/imgcrypt v1.1.10 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.13.12 - github.com/containerd/platforms v0.1.1 + github.com/containerd/platforms v0.2.0 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 github.com/containerd/stargz-snapshotter/ipfs v0.15.1 diff --git a/go.sum b/go.sum index 851ed1fa027..725a0a5ed01 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,8 @@ 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.12 h1:xShPWHz7rCi8AG4Z5Q3EzyEgFqW/y8h5tczYAwK0r24= github.com/containerd/nydus-snapshotter v0.13.12/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= -github.com/containerd/platforms v0.1.1 h1:gp0xXBoY+1CjH54gJDon0kBjIbK2C4XSX1BGwP5ptG0= -github.com/containerd/platforms v0.1.1/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= +github.com/containerd/platforms v0.2.0 h1:clGNvVIcY3k39VJSYdFGohI1b3bP/eeBUVR5+XA28oo= +github.com/containerd/platforms v0.2.0/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= 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= From 762fe91c68027059ca8c14a79ab0a76998cf04f8 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 10 May 2024 15:24:41 -0700 Subject: [PATCH 0447/1066] Fix some /etc/ file permissions (see #2684) Signed-off-by: apostasie --- pkg/containerutil/container_network_manager.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index ae24bc15f54..1f746c2d4bb 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -398,6 +398,8 @@ func withDedupMounts(mountPath string, defaultSpec oci.SpecOpts) oci.SpecOpts { } } +// copyFileContent copies a file and sets world readable permissions on it, regardless of umask. +// This is used solely for /etc/resolv.conf and /etc/hosts func copyFileContent(src string, dst string) error { data, err := os.ReadFile(src) if err != nil { @@ -407,6 +409,10 @@ func copyFileContent(src string, dst string) error { if err != nil { return err } + err = os.Chmod(dst, 0644) + if err != nil { + return err + } return nil } @@ -539,6 +545,7 @@ func validateUtsSettings(netOpts types.NetworkOptions) error { // Nerdctl-managed datastore and returns the oci.SpecOpts required in the container // spec for the file to be mounted under /etc/hostname in the new container. // If the hostname is empty, the leading 12 characters of the containerID +// This sets world readable permissions on /etc/hostname, ignoring umask func writeEtcHostnameForContainer(globalOptions types.GlobalCommandOptions, hostname string, containerID string) ([]oci.SpecOpts, error) { if containerID == "" { return nil, fmt.Errorf("container ID is required for setting up hostname file") @@ -559,6 +566,11 @@ func writeEtcHostnameForContainer(globalOptions types.GlobalCommandOptions, host return nil, err } + err = os.Chmod(hostnamePath, 0644) + if err != nil { + return nil, err + } + return []oci.SpecOpts{oci.WithHostname(hostname), withCustomEtcHostname(hostnamePath)}, nil } From c5d1b532c6837e0c8aa696c826b38f002eccc634 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 10 May 2024 22:30:27 -0700 Subject: [PATCH 0448/1066] Allow directories for --device and in-container path Signed-off-by: apostasie --- .../container_run_cgroup_linux_test.go | 46 +++++++++++-------- pkg/cmd/container/run_cgroup_linux.go | 21 ++++----- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/cmd/nerdctl/container_run_cgroup_linux_test.go b/cmd/nerdctl/container_run_cgroup_linux_test.go index 16e0b0acdbf..8174336b8a3 100644 --- a/cmd/nerdctl/container_run_cgroup_linux_test.go +++ b/cmd/nerdctl/container_run_cgroup_linux_test.go @@ -212,39 +212,46 @@ func TestRunDevice(t *testing.T) { func TestParseDevice(t *testing.T) { t.Parallel() type testCase struct { - s string - expectedDevPath string - expectedMode string - err string + s string + expectedDevPath string + expectedContainerPath string + expectedMode string + err string } testCases := []testCase{ { - s: "/dev/sda1", - expectedDevPath: "/dev/sda1", - expectedMode: "rwm", + s: "/dev/sda1", + expectedDevPath: "/dev/sda1", + expectedContainerPath: "/dev/sda1", + expectedMode: "rwm", }, { - s: "/dev/sda2:r", - expectedDevPath: "/dev/sda2", - expectedMode: "r", + s: "/dev/sda2:r", + expectedDevPath: "/dev/sda2", + expectedContainerPath: "/dev/sda2", + expectedMode: "r", }, { - s: "/dev/sda3:rw", - expectedDevPath: "/dev/sda3", - expectedMode: "rw", + s: "/dev/sda3:rw", + expectedDevPath: "/dev/sda3", + expectedContainerPath: "/dev/sda3", + expectedMode: "rw", }, { s: "sda4", err: "not an absolute path", }, { - s: "/dev/sda5:/dev/sda5", - expectedDevPath: "/dev/sda5", - expectedMode: "rwm", + s: "/dev/sda5:/dev/sda5", + expectedDevPath: "/dev/sda5", + expectedContainerPath: "/dev/sda5", + expectedMode: "rwm", }, { - s: "/dev/sda6:/dev/foo6", - err: "not supported yet", + s: "/dev/sda6:/dev/foo6", + expectedDevPath: "/dev/sda6", + expectedContainerPath: "/dev/foo6", + expectedMode: "rwm", }, { s: "/dev/sda7:/dev/sda7:rwmx", @@ -254,10 +261,11 @@ func TestParseDevice(t *testing.T) { for _, tc := range testCases { t.Log(tc.s) - devPath, mode, err := container.ParseDevice(tc.s) + devPath, containerPath, mode, err := container.ParseDevice(tc.s) if tc.err == "" { assert.NilError(t, err) assert.Equal(t, tc.expectedDevPath, devPath) + assert.Equal(t, tc.expectedContainerPath, containerPath) assert.Equal(t, tc.expectedMode, mode) } else { assert.ErrorContains(t, err, tc.err) diff --git a/pkg/cmd/container/run_cgroup_linux.go b/pkg/cmd/container/run_cgroup_linux.go index d7e6b4e4bc2..b81b3c3c382 100644 --- a/pkg/cmd/container/run_cgroup_linux.go +++ b/pkg/cmd/container/run_cgroup_linux.go @@ -199,12 +199,13 @@ func generateCgroupOpts(id string, options types.ContainerCreateOptions) ([]oci. } for _, f := range options.Device { - devPath, mode, err := ParseDevice(f) + devPath, conPath, mode, err := ParseDevice(f) if err != nil { return nil, fmt.Errorf("failed to parse device %q: %w", f, err) } - opts = append(opts, oci.WithLinuxDevice(devPath, mode)) + opts = append(opts, oci.WithDevices(devPath, conPath, mode)) } + return opts, nil } @@ -246,8 +247,8 @@ func generateCgroupPath(id, cgroupManager, cgroupParent string) (string, error) return path, nil } -// ParseDevice parses the give device string into hostDevPath and mode(defaults: "rwm"). -func ParseDevice(s string) (hostDevPath string, mode string, err error) { +// ParseDevice parses the give device string into hostDevPath, containerPath and mode(defaults: "rwm"). +func ParseDevice(s string) (hostDevPath string, containerPath string, mode string, err error) { mode = "rwm" split := strings.Split(s, ":") var containerDevPath string @@ -268,21 +269,17 @@ func ParseDevice(s string) (hostDevPath string, mode string, err error) { containerDevPath = split[1] mode = split[2] default: - return "", "", errors.New("too many `:` symbols") - } - - if containerDevPath != hostDevPath { - return "", "", errors.New("changing the path inside the container is not supported yet") + return "", "", "", errors.New("too many `:` symbols") } if !filepath.IsAbs(hostDevPath) { - return "", "", fmt.Errorf("%q is not an absolute path", hostDevPath) + return "", "", "", fmt.Errorf("%q is not an absolute path", hostDevPath) } if err := validateDeviceMode(mode); err != nil { - return "", "", err + return "", "", "", err } - return hostDevPath, mode, nil + return hostDevPath, containerDevPath, mode, nil } func validateDeviceMode(mode string) error { From fac3d35e20e7cd165c939497322e79bafe58d80c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 May 2024 16:15:59 +0000 Subject: [PATCH 0449/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 26.1.1+incompatible to 26.1.2+incompatible. - [Commits](https://github.com/docker/cli/compare/v26.1.1...v26.1.2) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 12864517025..e7aadbbf2bb 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 - github.com/docker/cli v26.1.1+incompatible + github.com/docker/cli v26.1.2+incompatible github.com/docker/docker v26.1.2+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 5be8c869f16..b0ace4409bc 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v26.1.1+incompatible h1:bE1/uE2tCa08fMv+7ikLR/RDPoCqytwrLtkIkSzxLvw= -github.com/docker/cli v26.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v26.1.2+incompatible h1:/MWZpUMMlr1hCGyquL8QNbL1hbivQ1kLuT3Z9s1Tlpg= +github.com/docker/cli v26.1.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v26.1.2+incompatible h1:UVX5ZOrrfTGZZYEP+ZDq3Xn9PdHNXaSYMFPDumMqG2k= github.com/docker/docker v26.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= From c60adf29a0a81526ff8d04697df9a14b60d4a6b4 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 11 May 2024 16:17:02 -0700 Subject: [PATCH 0450/1066] Add missing alias for container rm/remove Signed-off-by: apostasie --- cmd/nerdctl/container_remove.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/nerdctl/container_remove.go b/cmd/nerdctl/container_remove.go index 05a7e059e38..20588a32408 100644 --- a/cmd/nerdctl/container_remove.go +++ b/cmd/nerdctl/container_remove.go @@ -33,6 +33,7 @@ func newRmCommand() *cobra.Command { SilenceUsage: true, SilenceErrors: true, } + rmCommand.Aliases = []string{"remove"} rmCommand.Flags().BoolP("force", "f", false, "Force the removal of a running|paused|unknown container (uses SIGKILL)") rmCommand.Flags().BoolP("volumes", "v", false, "Remove volumes associated with the container") return rmCommand From 6b10870c1a2a934d70a36fcab55a5b96a704dd1c Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 13 May 2024 00:26:08 -0700 Subject: [PATCH 0451/1066] Re-acquire name in onStartContainer (see #2992) Signed-off-by: apostasie --- pkg/ocihook/ocihook.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index bed57eefb8c..a3936b48462 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -477,6 +477,15 @@ func onCreateRuntime(opts *handlerOpts) error { } func onStartContainer(opts *handlerOpts) error { + name := opts.state.Annotations[labels.Name] + ns := opts.state.Annotations[labels.Namespace] + namst, err := namestore.New(opts.dataStore, ns) + if err != nil { + log.L.WithError(err).Error("failed opening the namestore in onStartContainer") + } else if err := namst.Acquire(name, opts.state.ID); err != nil { + log.L.WithError(err).Error("failed re-acquiring name - see https://github.com/containerd/nerdctl/issues/2992") + } + if opts.cni != nil { return applyNetworkSettings(opts) } From b24582bc2b1f74e603e39aa03c658c7e6874f376 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 22:34:38 +0000 Subject: [PATCH 0452/1066] build(deps): bump github.com/fatih/color from 1.16.0 to 1.17.0 Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.16.0 to 1.17.0. - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.16.0...v1.17.0) --- updated-dependencies: - dependency-name: github.com/fatih/color dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e7aadbbf2bb..9d7c20c1e6a 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 - github.com/fatih/color v1.16.0 + github.com/fatih/color v1.17.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/ipfs/go-cid v0.4.1 github.com/mattn/go-isatty v0.0.20 diff --git a/go.sum b/go.sum index b0ace4409bc..0f3401e6a8e 100644 --- a/go.sum +++ b/go.sum @@ -104,8 +104,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fahedouch/go-logrotate v0.2.1 h1:Q0Hk9Kp/Y4iwy9uR9e/60fEoxGhvfk8MG7WwtL9aarM= github.com/fahedouch/go-logrotate v0.2.1/go.mod h1:Mmyex1f9fGXBNnhS9uHsbnO9BGvADF4VGqVnqAJalgc= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= From cc60f5d5d4426e87865128fe4626db00ba742858 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 13:00:24 +0000 Subject: [PATCH 0453/1066] build(deps): bump actions/checkout from 4.1.4 to 4.1.5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.4 to 4.1.5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.4...v4.1.5) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 6adf02841c9..55fcf22826c 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0d4a72fa802..cef3291e117 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 - uses: actions/setup-go@v5 with: go-version: 1.22.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8d119b8e6dc..25a2024112f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -88,7 +88,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -118,7 +118,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: fetch-depth: 1 - name: Enable ipv4 and ipv6 forwarding @@ -194,7 +194,7 @@ jobs: ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -211,7 +211,7 @@ jobs: matrix: go-version: ["1.21.x", "1.22.x"] steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -226,7 +226,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 30 steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -263,7 +263,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -272,7 +272,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: repository: containerd/containerd ref: v1.7.16 @@ -295,7 +295,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 - uses: actions/cache@v4 with: path: /root/.vagrant.d From 274b8a6ec8f84abea1241a3687402a17126b318e Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 15 May 2024 11:58:26 -0700 Subject: [PATCH 0454/1066] Fix cni plugins sha after spurious 1.4.1 re-release Signed-off-by: apostasie --- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 index 0baa626f8ab..36d5953641c 100644 --- a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 +++ b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 @@ -1,2 +1,2 @@ -1511f6c003ace805eafeb1132727791326283cff88a923d76329e1892bba7a10 cni-plugins-linux-amd64-v1.4.1.tgz -72644e13557cda8a5b39baf97fc5e93d23fdf7baba7700000e7e9efd8bdf9234 cni-plugins-linux-arm64-v1.4.1.tgz +2a0ea7072d1806b8526489bcd3b4847a06ab010ee32ba3c3d4e5a3235d3eb138 cni-plugins-linux-amd64-v1.4.1.tgz +56fe62d73942cffd8f119d2b8ecb6a062e85f529a3dbfc7aa5cd83c2c01929a7 cni-plugins-linux-arm64-v1.4.1.tgz \ No newline at end of file From 480eb6eeeb0470d25a59e70c00a4f7e6b1547491 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 14 May 2024 00:34:30 -0700 Subject: [PATCH 0455/1066] Support DHCP IPAM opts and set the hostname Signed-off-by: apostasie --- docs/cni.md | 23 +++++++++++++++++++++++ pkg/netutil/cni_plugin_unix.go | 21 ++++++++++++++++++--- pkg/netutil/netutil_unix.go | 32 +++++++++++++++++++++++++++++++- pkg/ocihook/ocihook.go | 6 ++++++ 4 files changed, 78 insertions(+), 4 deletions(-) diff --git a/docs/cni.md b/docs/cni.md index 50dfde8043e..02ec79f1cce 100644 --- a/docs/cni.md +++ b/docs/cni.md @@ -90,6 +90,29 @@ an easier way is to use DHCP to assign the IP: Using `--driver ipvlan` can create `ipvlan` network, the default mode for IPvlan is `l2`. +## DHCP host-name and other DHCP options + +Nerdctl automatically sets the DHCP host-name option to the hostname value of the container. + +Furthermore, on network creation, nerdctl supports the ability to set other DHCP options through `--ipam-options`. + +Currently, the following options are supported by the DHCP plugin: +``` +dhcp-client-identifier +subnet-mask +routers +user-class +vendor-class-identifier +``` + +For example: +``` +# nerdctl network create --driver macvlan \ + --ipam-driver dhcp \ + --ipam-opt 'vendor-class-identifier={"type": "provide", "value": "Hey! Its me!"}' \ + my-dhcp-net +``` + ## Custom networks You can also customize your CNI network by providing configuration files. diff --git a/pkg/netutil/cni_plugin_unix.go b/pkg/netutil/cni_plugin_unix.go index cdbb0221b8d..8d863d3be93 100644 --- a/pkg/netutil/cni_plugin_unix.go +++ b/pkg/netutil/cni_plugin_unix.go @@ -144,10 +144,25 @@ func newHostLocalIPAMConfig() *hostLocalIPAMConfig { } } -// https://github.com/containernetworking/plugins/blob/v1.1.0/plugins/ipam/dhcp/main.go#L43-L54 +// https://github.com/containernetworking/plugins/blob/v1.4.1/plugins/ipam/dhcp/main.go#L43-L54 type dhcpIPAMConfig struct { - Type string `json:"type"` - DaemonSocketPath string `json:"daemonSocketPath,omitempty"` + Type string `json:"type"` + DaemonSocketPath string `json:"daemonSocketPath"` + ProvideOptions []provideOption `json:"provide,omitempty"` + RequestOptions []requestOption `json:"request,omitempty"` +} + +type provideOption struct { + Option string `json:"option"` + + Value string `json:"value"` + ValueFromCNIArg string `json:"fromArg"` +} + +type requestOption struct { + SkipDefault bool `json:"skipDefault"` + + Option string `json:"option"` } func newDHCPIPAMConfig() *dhcpIPAMConfig { diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index f5315028f04..5c846b703b6 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -205,10 +205,40 @@ func (e *CNIEnv) generateIPAM(driver string, subnets []string, gatewayStr, ipRan case "dhcp": ipamConf := newDHCPIPAMConfig() ipamConf.DaemonSocketPath = filepath.Join(defaults.CNIRuntimeDir(), "dhcp.sock") - // TODO: support IPAM options for dhcp if err := systemutil.IsSocketAccessible(ipamConf.DaemonSocketPath); err != nil { log.L.Warnf("cannot access dhcp socket %q (hint: try running with `dhcp daemon --socketpath=%s &` in CNI_PATH to launch the dhcp daemon)", ipamConf.DaemonSocketPath, ipamConf.DaemonSocketPath) } + + // Set the host-name option to the value of passed argument NERDCTL_CNI_DHCP_HOSTNAME + opts["host-name"] = `{"type": "provide", "fromArg": "NERDCTL_CNI_DHCP_HOSTNAME"}` + + // Convert all user-defined ipam-options into serializable options + for optName, optValue := range opts { + parsed := &struct { + Type string `json:"type"` + Value string `json:"value"` + ValueFromCNIArg string `json:"fromArg"` + SkipDefault bool `json:"skipDefault"` + }{} + if err := json.Unmarshal([]byte(optValue), parsed); err != nil { + return nil, fmt.Errorf("unparsable ipam option %s %q", optName, optValue) + } + if parsed.Type == "provide" { + ipamConf.ProvideOptions = append(ipamConf.ProvideOptions, provideOption{ + Option: optName, + Value: parsed.Value, + ValueFromCNIArg: parsed.ValueFromCNIArg, + }) + } else if parsed.Type == "request" { + ipamConf.RequestOptions = append(ipamConf.RequestOptions, requestOption{ + Option: optName, + SkipDefault: parsed.SkipDefault, + }) + } else { + return nil, fmt.Errorf("ipam option must have a type (provide or request)") + } + } + ipamConfig = ipamConf default: return nil, fmt.Errorf("unsupported ipam driver %q", driver) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index a3936b48462..09133170a81 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -421,6 +421,12 @@ func applyNetworkSettings(opts *handlerOpts) error { namespaceOpts = append(namespaceOpts, ipAddressOpts...) namespaceOpts = append(namespaceOpts, macAddressOpts...) namespaceOpts = append(namespaceOpts, ip6AddressOpts...) + namespaceOpts = append(namespaceOpts, + gocni.WithLabels(map[string]string{ + "IgnoreUnknown": "1", + }), + gocni.WithArgs("NERDCTL_CNI_DHCP_HOSTNAME", opts.state.Annotations[labels.Hostname]), + ) hsMeta := hostsstore.Meta{ Namespace: opts.state.Annotations[labels.Namespace], ID: opts.state.ID, From 64af5a6d6317196944817f219122f5a168cb2312 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 22:15:24 +0000 Subject: [PATCH 0456/1066] build(deps): bump github.com/containerd/containerd from 1.7.16 to 1.7.17 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.16 to 1.7.17. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.16...v1.7.17) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 9d7c20c1e6a..c48a20a4c2a 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.1.3 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.17 github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 @@ -73,7 +73,7 @@ require ( github.com/cilium/ebpf v0.11.0 // indirect github.com/containerd/errdefs v0.1.0 // indirect github.com/containerd/go-runc v1.0.0 // indirect - github.com/containerd/ttrpc v1.2.3 // indirect + github.com/containerd/ttrpc v1.2.4 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect github.com/containers/ocicrypt v1.1.10 // indirect github.com/distribution/reference v0.6.0 // indirect @@ -120,7 +120,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 diff --git a/go.sum b/go.sum index 0f3401e6a8e..9be98954b53 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ 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.17 h1:KjNnn0+tAVQHAoaWRjmdak9WlvnFR/8rU1CHHy8Rm2A= +github.com/containerd/containerd v1.7.17/go.mod h1:vK+hhT4TIv2uejlcDlbVIc8+h/BqtKLIyNrtCZol8lI= 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= @@ -58,8 +58,8 @@ github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G 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.4 h1:eQCQK4h9dxDmpOb9QOOMh2NHTfzroH1IkmHiKZi05Oo= +github.com/containerd/ttrpc v1.2.4/go.mod h1:ojvb8SJBSch0XkqNO0L0YX/5NxR3UnVk2LzFKBK0upc= 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= @@ -272,8 +272,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/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= From 35a90ef6a47b339d8f93162070bac7d93ea471e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 22:15:39 +0000 Subject: [PATCH 0457/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.1.2+incompatible to 26.1.3+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v26.1.2...v26.1.3) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9d7c20c1e6a..fad90dab6f5 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 github.com/docker/cli v26.1.2+incompatible - github.com/docker/docker v26.1.2+incompatible + github.com/docker/docker v26.1.3+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 0f3401e6a8e..6241d9d5cff 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/docker/cli v26.1.2+incompatible h1:/MWZpUMMlr1hCGyquL8QNbL1hbivQ1kLuT3Z9s1Tlpg= github.com/docker/cli v26.1.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v26.1.2+incompatible h1:UVX5ZOrrfTGZZYEP+ZDq3Xn9PdHNXaSYMFPDumMqG2k= -github.com/docker/docker v26.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.1.3+incompatible h1:lLCzRbrVZrljpVNobJu1J2FHk8V0s4BawoZippkc+xo= +github.com/docker/docker v26.1.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 80bc6835c4afbbcba4db15e6c4687916e8edd76e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 22:43:36 +0000 Subject: [PATCH 0458/1066] build(deps): bump actions/checkout from 4.1.5 to 4.1.6 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.5 to 4.1.6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.5...v4.1.6) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 55fcf22826c..4b4ac862124 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cef3291e117..65209734b4a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - uses: actions/setup-go@v5 with: go-version: 1.22.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 25a2024112f..90fc372d426 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -88,7 +88,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -118,7 +118,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: fetch-depth: 1 - name: Enable ipv4 and ipv6 forwarding @@ -194,7 +194,7 @@ jobs: ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -211,7 +211,7 @@ jobs: matrix: go-version: ["1.21.x", "1.22.x"] steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -226,7 +226,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 30 steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -263,7 +263,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -272,7 +272,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: repository: containerd/containerd ref: v1.7.16 @@ -295,7 +295,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - uses: actions/cache@v4 with: path: /root/.vagrant.d From 5f8c0c9d81d94ba9fa22270c532161db84086d21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 18 May 2024 11:25:12 +0000 Subject: [PATCH 0459/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 26.1.2+incompatible to 26.1.3+incompatible. - [Commits](https://github.com/docker/cli/compare/v26.1.2...v26.1.3) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 137d4c75675..57e07ef4947 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 - github.com/docker/cli v26.1.2+incompatible + github.com/docker/cli v26.1.3+incompatible github.com/docker/docker v26.1.3+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 51656a7cd1d..0bc2d35bc66 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v26.1.2+incompatible h1:/MWZpUMMlr1hCGyquL8QNbL1hbivQ1kLuT3Z9s1Tlpg= -github.com/docker/cli v26.1.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v26.1.3+incompatible h1:bUpXT/N0kDE3VUHI2r5VMsYQgi38kYuoC0oL9yt3lqc= +github.com/docker/cli v26.1.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v26.1.3+incompatible h1:lLCzRbrVZrljpVNobJu1J2FHk8V0s4BawoZippkc+xo= github.com/docker/docker v26.1.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= From 93b138179d9035af2cbc4b3a8807ebd146d3de2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 18 May 2024 11:55:42 +0000 Subject: [PATCH 0460/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.12 to 0.13.13. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.12...v0.13.13) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 57e07ef4947..210bdfe8449 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/go-cni v1.1.9 github.com/containerd/imgcrypt v1.1.10 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.12 + github.com/containerd/nydus-snapshotter v0.13.13 github.com/containerd/platforms v0.2.0 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 diff --git a/go.sum b/go.sum index 0bc2d35bc66..b6f763129f8 100644 --- a/go.sum +++ b/go.sum @@ -48,8 +48,8 @@ github.com/containerd/imgcrypt v1.1.10 h1:vtyGzTna2wC5BSQcqHWgY4xsBLHWFWyecgK0+9 github.com/containerd/imgcrypt v1.1.10/go.mod h1:9eIPG34EQy+j00fr+4r0knul2MkYDKD2uzKkw8548aw= 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.12 h1:xShPWHz7rCi8AG4Z5Q3EzyEgFqW/y8h5tczYAwK0r24= -github.com/containerd/nydus-snapshotter v0.13.12/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= +github.com/containerd/nydus-snapshotter v0.13.13 h1:4eCKSNjmozLQ038G2a3X8DEwmrsHsRPMdVGX+zjcaTc= +github.com/containerd/nydus-snapshotter v0.13.13/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= github.com/containerd/platforms v0.2.0 h1:clGNvVIcY3k39VJSYdFGohI1b3bP/eeBUVR5+XA28oo= github.com/containerd/platforms v0.2.0/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= github.com/containerd/stargz-snapshotter v0.15.1 h1:fpsP4kf/Z4n2EYnU0WT8ZCE3eiKDwikDhL6VwxIlgeA= From 0d470e7ebb6606649467f621fdb05644131c1703 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 14 May 2024 16:36:15 -0700 Subject: [PATCH 0461/1066] Implementing StartedAt for containers Signed-off-by: apostasie --- docs/dir.md | 1 + pkg/inspecttypes/dockercompat/dockercompat.go | 32 ++++--- .../dockercompat/dockercompat_test.go | 6 +- pkg/ocihook/ocihook.go | 20 ++++- pkg/ocihook/state/state.go | 90 +++++++++++++++++++ 5 files changed, 133 insertions(+), 16 deletions(-) create mode 100644 pkg/ocihook/state/state.go diff --git a/docs/dir.md b/docs/dir.md index f0084f0b23d..7bf5418a1e0 100644 --- a/docs/dir.md +++ b/docs/dir.md @@ -34,6 +34,7 @@ Files: - `log-config.json`: used for storing the `--log-opts` map of `nerdctl run` - `-json.log`: used by `nerdctl logs` - `oci-hook.*.log`: logs of the OCI hook +- `lifecycle.json`: used to store stateful information about the container that can only be retrieved through OCI hooks ### `//names/` e.g. `/var/lib/nerdctl/1935db59/names/default` diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index da9f714c9df..76ca4d62f07 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -42,6 +42,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/ocihook/state" "github.com/docker/go-connections/nat" "github.com/opencontainers/runtime-spec/specs-go" "github.com/tidwall/gjson" @@ -164,10 +165,10 @@ type ContainerState struct { Restarting bool // TODO: OOMKilled bool // TODO: Dead bool - Pid int - ExitCode int - Error string - // TODO: StartedAt string + Pid int + ExitCode int + Error string + StartedAt string FinishedAt string // TODO: Health *Health `json:",omitempty"` } @@ -213,17 +214,20 @@ type NetworkEndpointSettings struct { func ContainerFromNative(n *native.Container) (*Container, error) { var hostname string c := &Container{ - ID: n.ID, - Created: n.CreatedAt.Format(time.RFC3339Nano), - Image: n.Image, - Name: n.Labels[labels.Name], - Driver: n.Snapshotter, + ID: n.ID, + Created: n.CreatedAt.Format(time.RFC3339Nano), + Image: n.Image, + Name: n.Labels[labels.Name], + Driver: n.Snapshotter, + // XXX is this always right? what if the container OS is NOT the same as the host OS? Platform: runtime.GOOS, // for Docker compatibility, this Platform string does NOT contain arch like "/amd64" } if n.Labels[restart.StatusLabel] == string(containerd.Running) { c.RestartCount, _ = strconv.Atoi(n.Labels[restart.CountLabel]) } + containerAnnotations := make(map[string]string) if sp, ok := n.Spec.(*specs.Spec); ok { + containerAnnotations = sp.Annotations if p := sp.Process; p != nil { if len(p.Args) > 0 { c.Path = p.Args[0] @@ -275,7 +279,15 @@ func ContainerFromNative(n *native.Container) (*Container, error) { cs.Paused = n.Process.Status.Status == containerd.Paused cs.Pid = n.Process.Pid cs.ExitCode = int(n.Process.Status.ExitStatus) - cs.FinishedAt = n.Process.Status.ExitTime.Format(time.RFC3339Nano) + if containerAnnotations[labels.StateDir] != "" { + lf := state.NewLifecycleState(containerAnnotations[labels.StateDir]) + if err := lf.WithLock(lf.Load); err == nil && !time.Time.IsZero(lf.StartedAt) { + cs.StartedAt = lf.StartedAt.UTC().Format(time.RFC3339Nano) + } + } + if !n.Process.Status.ExitTime.IsZero() { + cs.FinishedAt = n.Process.Status.ExitTime.Format(time.RFC3339Nano) + } nSettings, err := networkSettingsFromNative(n.Process.NetNS, n.Spec.(*specs.Spec)) if err != nil { return nil, err diff --git a/pkg/inspecttypes/dockercompat/dockercompat_test.go b/pkg/inspecttypes/dockercompat/dockercompat_test.go index 1c772c4daa3..38dbb6835b3 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat_test.go +++ b/pkg/inspecttypes/dockercompat/dockercompat_test.go @@ -70,7 +70,7 @@ func TestContainerFromNative(t *testing.T) { Status: "running", Running: true, Pid: 10000, - FinishedAt: "0001-01-01T00:00:00Z", + FinishedAt: "", }, Mounts: []MountPoint{ { @@ -141,7 +141,7 @@ func TestContainerFromNative(t *testing.T) { Status: "running", Running: true, Pid: 10000, - FinishedAt: "0001-01-01T00:00:00Z", + FinishedAt: "", }, Mounts: []MountPoint{ { @@ -209,7 +209,7 @@ func TestContainerFromNative(t *testing.T) { Status: "running", Running: true, Pid: 10000, - FinishedAt: "0001-01-01T00:00:00Z", + FinishedAt: "", }, Mounts: []MountPoint{ { diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index a3936b48462..9aa1e46bcdc 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -26,6 +26,7 @@ import ( "os" "path/filepath" "strings" + "time" gocni "github.com/containerd/go-cni" "github.com/containerd/log" @@ -35,6 +36,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/namestore" "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" + "github.com/containerd/nerdctl/v2/pkg/ocihook/state" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" types100 "github.com/containernetworking/cni/pkg/types/100" "github.com/opencontainers/runtime-spec/specs-go" @@ -284,7 +286,7 @@ func getNetNSPath(state *specs.State) (string, error) { return netNsPath, nil } - if state.Pid == 0 && !netNsFound { + if state.Pid == 0 { return "", errors.New("both state.Pid and the netNs annotation are unset") } @@ -487,9 +489,21 @@ func onStartContainer(opts *handlerOpts) error { } if opts.cni != nil { - return applyNetworkSettings(opts) + if err = applyNetworkSettings(opts); err != nil { + return err + } } - return nil + + // Set StartedAt + lf := state.NewLifecycleState(opts.state.Annotations[labels.StateDir]) + return lf.WithLock(func() error { + err := lf.Load() + if err != nil { + return err + } + lf.StartedAt = time.Now() + return lf.Save() + }) } func onPostStop(opts *handlerOpts) error { diff --git a/pkg/ocihook/state/state.go b/pkg/ocihook/state/state.go new file mode 100644 index 00000000000..0c0295cdd83 --- /dev/null +++ b/pkg/ocihook/state/state.go @@ -0,0 +1,90 @@ +/* + 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 state + +import ( + "encoding/json" + "errors" + "fmt" + "os" + "path/filepath" + "time" + + "github.com/containerd/nerdctl/v2/pkg/lockutil" +) + +// This is meant to store stateful informations about containers that we receive from ocihooks +// We are storing them inside the container statedir +// Note that you MUST use WithLock to perform any operation (like Read or Write). +// Typically: +// lf.WithLock(func ()error { +// lf.Load() +// // Modify something on the object +// lf.StartedAt = ... +// lf.Save() +// }) + +const ( + lifecycleFile = "lifecycle.json" +) + +func NewLifecycleState(stateDir string) *LifecycleState { + return &LifecycleState{ + stateDir: stateDir, + } +} + +type LifecycleState struct { + stateDir string + StartedAt time.Time `json:"started_at"` +} + +func (lf *LifecycleState) WithLock(fun func() error) error { + err := lockutil.WithDirLock(lf.stateDir, fun) + if err != nil { + return fmt.Errorf("failed to lock state dir: %w", err) + } + + return nil +} + +func (lf *LifecycleState) Load() error { + data, err := os.ReadFile(filepath.Join(lf.stateDir, lifecycleFile)) + if err != nil { + if !errors.Is(err, os.ErrNotExist) { + return fmt.Errorf("unable to read lifecycle file: %w", err) + } + } else { + err = json.Unmarshal(data, lf) + if err != nil { + return fmt.Errorf("unable to unmarshall lifecycle data: %w", err) + } + } + return nil +} + +func (lf *LifecycleState) Save() error { + data, err := json.Marshal(lf) + if err != nil { + return fmt.Errorf("unable to marshall lifecycle data: %w", err) + } + err = os.WriteFile(filepath.Join(lf.stateDir, lifecycleFile), data, 0600) + if err != nil { + return fmt.Errorf("unable to write lifecycle file: %w", err) + } + return nil +} From 8b34abdf5b0238f003305de375e8333f0a7c0e14 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 17 May 2024 22:22:44 -0700 Subject: [PATCH 0462/1066] Implement container inspect --size, SizeRootFs and SizeRw Signed-off-by: apostasie --- cmd/nerdctl/container_inspect.go | 8 +++ cmd/nerdctl/inspect.go | 2 + docs/command-reference.md | 1 + pkg/api/types/container_types.go | 2 + pkg/cmd/container/inspect.go | 53 +++++++++++++++++-- pkg/inspecttypes/dockercompat/dockercompat.go | 4 +- 6 files changed, 65 insertions(+), 5 deletions(-) diff --git a/cmd/nerdctl/container_inspect.go b/cmd/nerdctl/container_inspect.go index 7fe6dd4435c..cd3c01871df 100644 --- a/cmd/nerdctl/container_inspect.go +++ b/cmd/nerdctl/container_inspect.go @@ -38,6 +38,8 @@ func newContainerInspectCommand() *cobra.Command { SilenceErrors: true, } containerInspectCommand.Flags().String("mode", "dockercompat", `Inspect mode, "dockercompat" for Docker-compatible output, "native" for containerd-native output`) + containerInspectCommand.Flags().BoolP("size", "s", false, "Display total file sizes") + containerInspectCommand.RegisterFlagCompletionFunc("mode", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"dockercompat", "native"}, cobra.ShellCompDirectiveNoFileComp }) @@ -71,10 +73,16 @@ func processContainerInspectOptions(cmd *cobra.Command) (opt types.ContainerInsp return } + size, err := cmd.Flags().GetBool("size") + if err != nil { + return + } + return types.ContainerInspectOptions{ GOptions: globalOptions, Format: format, Mode: mode, + Size: size, Stdout: cmd.OutOrStdout(), }, nil } diff --git a/cmd/nerdctl/inspect.go b/cmd/nerdctl/inspect.go index 2cea1d97cc7..fa74d587786 100644 --- a/cmd/nerdctl/inspect.go +++ b/cmd/nerdctl/inspect.go @@ -52,6 +52,8 @@ var validInspectType = map[string]bool{ } func addInspectFlags(cmd *cobra.Command) { + cmd.Flags().BoolP("size", "s", false, "Display total file sizes (for containers)") + cmd.Flags().StringP("format", "f", "", "Format the output using the given Go template, e.g, '{{json .}}'") cmd.RegisterFlagCompletionFunc("format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"json"}, cobra.ShellCompDirectiveNoFileComp diff --git a/docs/command-reference.md b/docs/command-reference.md index 3c3371c787c..40457da177f 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -494,6 +494,7 @@ Flags: - :nerd_face: `--mode=(dockercompat|native)`: Inspection mode. "native" produces more information. - :whale: `--format`: Format the output using the given Go template, e.g, `{{json .}}` - :whale: `--type`: Return JSON for specified type +- :whale: `--size`: Display total file sizes if the type is container Unimplemented `docker inspect` flags: `--size` diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index 60e5da4c373..4759eb29678 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -330,6 +330,8 @@ type ContainerInspectOptions struct { GOptions GlobalCommandOptions // Format of the output Format string + // Whether to report the size + Size bool // Inspect mode, either dockercompat or native Mode string } diff --git a/pkg/cmd/container/inspect.go b/pkg/cmd/container/inspect.go index 4cdad9faf27..ee238a7f4d2 100644 --- a/pkg/cmd/container/inspect.go +++ b/pkg/cmd/container/inspect.go @@ -22,6 +22,7 @@ import ( "time" "github.com/containerd/containerd" + "github.com/containerd/containerd/snapshots" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerinspector" @@ -33,7 +34,9 @@ import ( // Inspect prints detailed information for each container in `containers`. func Inspect(ctx context.Context, client *containerd.Client, containers []string, options types.ContainerInspectOptions) error { f := &containerInspector{ - mode: options.Mode, + mode: options.Mode, + size: options.Size, + snapshotter: client.SnapshotService(options.GOptions.Snapshotter), } walker := &containerwalker.ContainerWalker{ @@ -47,12 +50,48 @@ func Inspect(ctx context.Context, client *containerd.Client, containers []string log.L.Error(formatErr) } } + return err } type containerInspector struct { - mode string - entries []interface{} + mode string + size bool + snapshotter snapshots.Snapshotter + entries []interface{} +} + +// resourceTotal will return: +// - the Usage value of the resource referenced by ID +// - the cumulative Usage value of the resource, and all parents, recursively +// Typically, for a running container, this will equal the size of the read-write layer, plus the sum of the size of all layers in the base image +func resourceTotal(ctx context.Context, snapshotter snapshots.Snapshotter, resourceID string) (snapshots.Usage, snapshots.Usage, error) { + var first snapshots.Usage + var total snapshots.Usage + var info snapshots.Info + + for next := resourceID; next != ""; next = info.Parent { + // Get the resource usage info + usage, err := snapshotter.Usage(ctx, next) + if err != nil { + return first, total, err + } + // In case that's the first one, store that + if next == resourceID { + first = usage + } + // And increment totals + total.Size += usage.Size + total.Inodes += usage.Inodes + + // Now, get the parent, if any and iterate + info, err = snapshotter.Stat(ctx, next) + if err != nil { + return first, total, err + } + } + + return first, total, nil } func (x *containerInspector) Handler(ctx context.Context, found containerwalker.Found) error { @@ -71,7 +110,15 @@ func (x *containerInspector) Handler(ctx context.Context, found containerwalker. if err != nil { return err } + if x.size { + resourceUsage, allResourceUsage, err := resourceTotal(ctx, x.snapshotter, d.ID) + if err == nil { + d.SizeRw = &resourceUsage.Size + d.SizeRootFs = &allResourceUsage.Size + } + } x.entries = append(x.entries, d) + return err default: return fmt.Errorf("unknown mode %q", x.mode) } diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index da9f714c9df..33df73860f9 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -105,8 +105,8 @@ type Container struct { // TODO: ExecIDs []string // TODO: HostConfig *container.HostConfig // TODO: GraphDriver GraphDriverData - // TODO: SizeRw *int64 `json:",omitempty"` - // TODO: SizeRootFs *int64 `json:",omitempty"` + SizeRw *int64 `json:",omitempty"` + SizeRootFs *int64 `json:",omitempty"` Mounts []MountPoint Config *Config From 0988c9b819847c4afc361c2700d1db60a15fe135 Mon Sep 17 00:00:00 2001 From: qianxi0410 <894871277@qq.com> Date: Sun, 19 May 2024 19:42:51 +0800 Subject: [PATCH 0463/1066] chore: remove impossible error check Signed-off-by: qianxi0410 <894871277@qq.com> --- pkg/rootlessutil/parent_linux.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/rootlessutil/parent_linux.go b/pkg/rootlessutil/parent_linux.go index 8066f24c7e2..38ace232d91 100644 --- a/pkg/rootlessutil/parent_linux.go +++ b/pkg/rootlessutil/parent_linux.go @@ -83,9 +83,6 @@ func ParentMain(hostGatewayIP string) error { } detachNetNSMode := detachedNetNSPath != "" log.L.Debugf("RootlessKit detach-netns mode: %v", detachNetNSMode) - if err != nil { - return err - } wd, err := os.Getwd() if err != nil { From cf5073b432365bfdd81b0b6445c0df90c48f16bf Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Mon, 20 May 2024 11:20:32 +0000 Subject: [PATCH 0464/1066] support image label Signed-off-by: Kay Yan --- cmd/nerdctl/container_create_linux_test.go | 13 +++++++++++++ pkg/cmd/container/create.go | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/container_create_linux_test.go b/cmd/nerdctl/container_create_linux_test.go index 8a66c781c4a..ba70bda420b 100644 --- a/cmd/nerdctl/container_create_linux_test.go +++ b/cmd/nerdctl/container_create_linux_test.go @@ -38,6 +38,19 @@ func TestCreate(t *testing.T) { base.Cmd("logs", tID).AssertOutContains("foo") } +func TestCreateWithLabel(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + tID := testutil.Identifier(t) + + base.Cmd("create", "--name", tID, "--label", "foo=bar", testutil.NginxAlpineImage, "echo", "foo").AssertOK() + defer base.Cmd("rm", "-f", tID).Run() + inspect := base.InspectContainer(tID) + assert.Equal(base.T, "bar", inspect.Config.Labels["foo"]) + // the label `maintainer`` is defined by image + assert.Equal(base.T, "NGINX Docker Maintainers ", inspect.Config.Labels["maintainer"]) +} + func TestCreateWithMACAddress(t *testing.T) { base := testutil.NewBase(t) tID := testutil.Identifier(t) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 3b7e6ff7c70..081f5da88b5 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -234,7 +234,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa } cOpts = append(cOpts, rtCOpts...) - lCOpts, err := withContainerLabels(options.Label, options.LabelFile) + lCOpts, err := withContainerLabels(options.Label, options.LabelFile, ensuredImage) if err != nil { return nil, nil, err } @@ -504,7 +504,15 @@ func withNerdctlOCIHook(cmd string, args []string) (oci.SpecOpts, error) { }, nil } -func withContainerLabels(label, labelFile []string) ([]containerd.NewContainerOpts, error) { +func withContainerLabels(label, labelFile []string, ensuredImage *imgutil.EnsuredImage) ([]containerd.NewContainerOpts, error) { + var opts []containerd.NewContainerOpts + + // add labels defined by image + if ensuredImage != nil { + imageLabelOpts := containerd.WithAdditionalContainerLabels(ensuredImage.ImageConfig.Labels) + opts = append(opts, imageLabelOpts) + } + labelMap, err := readKVStringsMapfFromLabel(label, labelFile) if err != nil { return nil, err @@ -517,7 +525,9 @@ func withContainerLabels(label, labelFile []string) ([]containerd.NewContainerOp } } o := containerd.WithAdditionalContainerLabels(labelMap) - return []containerd.NewContainerOpts{o}, nil + opts = append(opts, o) + + return opts, nil } func readKVStringsMapfFromLabel(label, labelFile []string) (map[string]string, error) { From 713851de9962a92014b8b1613a041fcfc07fd4a3 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Mon, 20 May 2024 12:14:28 +0000 Subject: [PATCH 0465/1066] add retry on test Signed-off-by: Kay Yan --- .github/workflows/test.yml | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 90fc372d426..d214c124cbc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -102,7 +102,12 @@ jobs: - name: "Register QEMU (tonistiigi/binfmt)" run: docker run --privileged --rm tonistiigi/binfmt --install all - name: "Run integration tests" - run: docker run -t --rm --privileged test-integration + uses: nick-fields/retry@v3 + with: + timeout_minutes: 30 + max_attempts: 2 + retry_on: error + command: docker run -t --rm --privileged test-integration test-integration-ipv6: runs-on: "ubuntu-${{ matrix.ubuntu }}" @@ -146,7 +151,12 @@ jobs: # On the other side, using the host network is easier at configuration. # Besides, each job is running on a different instance, which means using host network here # is safe and has no side effects on others. - run: docker run --network host -t --rm --privileged test-integration-ipv6 + uses: nick-fields/retry@v3 + with: + timeout_minutes: 30 + max_attempts: 2 + retry_on: error + command: docker run --network host -t --rm --privileged test-integration-ipv6 test-integration-rootless: runs-on: "ubuntu-${{ matrix.ubuntu }}" @@ -202,7 +212,12 @@ jobs: - name: "Prepare (network driver=slirp4netns, port driver=builtin)" run: DOCKER_BUILDKIT=1 docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} --build-arg ROOTLESSKIT_VERSION=${ROOTLESSKIT_VERSION} . - name: "Test (network driver=slirp4netns, port driver=builtin)" - run: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=1 ${TEST_TARGET} + uses: nick-fields/retry@v3 + with: + timeout_minutes: 30 + max_attempts: 2 + retry_on: error + command: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=1 ${TEST_TARGET} cross: runs-on: ubuntu-22.04 @@ -224,7 +239,7 @@ jobs: test-integration-docker-compatibility: runs-on: ubuntu-22.04 - timeout-minutes: 30 + timeout-minutes: 45 steps: - uses: actions/checkout@v4.1.6 with: @@ -252,9 +267,19 @@ jobs: run: | sudo apt-get install -y expect - name: "Ensure that the integration test suite is compatible with Docker" - run: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon + uses: nick-fields/retry@v3 + with: + timeout_minutes: 30 + max_attempts: 2 + retry_on: error + command: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon - name: "Ensure that the IPv6 integration test suite is compatible with Docker" - run: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon -test.ipv6 + uses: nick-fields/retry@v3 + with: + timeout_minutes: 30 + max_attempts: 2 + retry_on: error + command: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon -test.ipv6 test-integration-windows: runs-on: windows-2022 From 11fcb6b038dd963b48f8793e7d21072896f50ad7 Mon Sep 17 00:00:00 2001 From: Kebe Date: Thu, 23 May 2024 11:55:58 +0800 Subject: [PATCH 0466/1066] Do not obtain task info when it is not necessary in commit command Signed-off-by: Kebe --- pkg/imgutil/commit/commit.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index 45cd03241f4..982ce2a846a 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -94,12 +94,12 @@ func Commit(ctx context.Context, client *containerd.Client, container containerd return emptyDigest, err } - task, err := container.Task(ctx, cio.Load) - if err != nil { - return emptyDigest, err - } - if opts.Pause { + task, err := container.Task(ctx, cio.Load) + if err != nil { + return emptyDigest, err + } + status, err := task.Status(ctx) if err != nil { return emptyDigest, err From 949dc8aae79347adcded87495b3609e3848103f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 May 2024 22:25:03 +0000 Subject: [PATCH 0467/1066] build(deps): bump github.com/awslabs/soci-snapshotter Bumps [github.com/awslabs/soci-snapshotter](https://github.com/awslabs/soci-snapshotter) from 0.6.0 to 0.6.1. - [Release notes](https://github.com/awslabs/soci-snapshotter/releases) - [Changelog](https://github.com/awslabs/soci-snapshotter/blob/main/RELEASES.md) - [Commits](https://github.com/awslabs/soci-snapshotter/compare/v0.6.0...v0.6.1) --- updated-dependencies: - dependency-name: github.com/awslabs/soci-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 210bdfe8449..efcdfc773c7 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.3 - github.com/awslabs/soci-snapshotter v0.6.0 + github.com/awslabs/soci-snapshotter v0.6.1 github.com/compose-spec/compose-go v1.20.2 github.com/containerd/accelerated-container-image v1.1.3 github.com/containerd/cgroups/v3 v3.0.3 diff --git a/go.sum b/go.sum index b6f763129f8..dacd4c09c79 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.3 h1:LS9NXqXhMoqNCplK1ApmVSfB4UnVLRDWRapB6EIlxE0= github.com/Microsoft/hcsshim v0.12.3/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ= -github.com/awslabs/soci-snapshotter v0.6.0 h1:OUu0nco912cKxvy3Qvgpv/WoUyyWuyl27wkaj8REmYA= -github.com/awslabs/soci-snapshotter v0.6.0/go.mod h1:EOjvD4czW3repJ5+4We/+dOCknmV2Ba0ywdUzSwm/gw= +github.com/awslabs/soci-snapshotter v0.6.1 h1:ggiuiCPReSNvfUL084Ujyp0glRNiCsZiaCh2rE580HA= +github.com/awslabs/soci-snapshotter v0.6.1/go.mod h1:o9NuuMmvmcpc+jRSoJlQqSqrWCjMO1x67C65wmCme7E= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= From 4b0b69d3cf93517fa74d52596f4af9394537bdc2 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 27 May 2024 10:45:37 +0900 Subject: [PATCH 0468/1066] go.mod: github.com/containernetworking/plugins v1.5.0 Signed-off-by: Akihiro Suda --- go.mod | 2 +- go.sum | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index efcdfc773c7..b16a753ce9c 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/containerd/stargz-snapshotter/ipfs v0.15.1 github.com/containerd/typeurl/v2 v2.1.1 github.com/containernetworking/cni v1.2.0 - github.com/containernetworking/plugins v1.4.1 + github.com/containernetworking/plugins v1.5.0 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 diff --git a/go.sum b/go.sum index dacd4c09c79..82d62601144 100644 --- a/go.sum +++ b/go.sum @@ -66,8 +66,8 @@ github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9Fqctt github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= github.com/containernetworking/cni v1.2.0 h1:fEjhlfWwWAXEvlcMQu/i6z8DA0Kbu7EcmR5+zb6cm5I= github.com/containernetworking/cni v1.2.0/go.mod h1:/r+vA/7vrynNfbvSP9g8tIKEoy6win7sALJAw4ZiJks= -github.com/containernetworking/plugins v1.4.1 h1:+sJRRv8PKhLkXIl6tH1D7RMi+CbbHutDGU+ErLBORWA= -github.com/containernetworking/plugins v1.4.1/go.mod h1:n6FFGKcaY4o2o5msgu/UImtoC+fpQXM3076VHfHbj60= +github.com/containernetworking/plugins v1.5.0 h1:P09DMlfvvsLSskDoftnuwXY7lwa7IAhTGznZxA5E8fk= +github.com/containernetworking/plugins v1.5.0/go.mod h1:bcXMvG9gWGc6jVXeodmMzuXmXqpqMguZm6Zu/oIr7AA= 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= @@ -120,7 +120,8 @@ github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -153,8 +154,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -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/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -230,10 +231,10 @@ github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= -github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= -github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= -github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= +github.com/onsi/ginkgo/v2 v2.17.3 h1:oJcvKpIb7/8uLpDDtnQuf18xVnwKp8DTD7DQ6gTd/MU= +github.com/onsi/ginkgo/v2 v2.17.3/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= 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 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -424,8 +425,8 @@ golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 03bee846e69af1837552fc2ade4beca79020b3ff Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 27 May 2024 10:54:28 +0900 Subject: [PATCH 0469/1066] update CNI plugins (1.5.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 | 2 -- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.0 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.0 diff --git a/Dockerfile b/Dockerfile index b523bae90bc..7dffb929c0f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ # Basic deps ARG CONTAINERD_VERSION=v1.7.16 ARG RUNC_VERSION=v1.1.12 -ARG CNI_PLUGINS_VERSION=v1.4.1 +ARG CNI_PLUGINS_VERSION=v1.5.0 # Extra deps: Build ARG BUILDKIT_VERSION=v0.13.2 diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 deleted file mode 100644 index 36d5953641c..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.4.1 +++ /dev/null @@ -1,2 +0,0 @@ -2a0ea7072d1806b8526489bcd3b4847a06ab010ee32ba3c3d4e5a3235d3eb138 cni-plugins-linux-amd64-v1.4.1.tgz -56fe62d73942cffd8f119d2b8ecb6a062e85f529a3dbfc7aa5cd83c2c01929a7 cni-plugins-linux-arm64-v1.4.1.tgz \ No newline at end of file diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.0 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.0 new file mode 100644 index 00000000000..729e73a90fb --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.0 @@ -0,0 +1,2 @@ +57a18478422cb321370e30a5ee6ce026321289cd9c94353ca697dddd7714f1a5 cni-plugins-linux-amd64-v1.5.0.tgz +ab38507efe50c34bc2242a25c5783c19fdfe0376c65a2a91d48174d4f39f1fc2 cni-plugins-linux-arm64-v1.5.0.tgz From 1ec6764f83ad25e1b6ed577a4cb294c2a9564b3c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 27 May 2024 11:00:05 +0900 Subject: [PATCH 0470/1066] update containerd (1.7.17) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 24 ++++++++++++------------ Dockerfile | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d214c124cbc..032cf892af8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,11 +77,11 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.31 + containerd: v1.6.32 - ubuntu: 20.04 - containerd: v1.7.16 + containerd: v1.7.17 - ubuntu: 22.04 - containerd: v1.7.16 + containerd: v1.7.17 - ubuntu: 22.04 containerd: main env: @@ -118,7 +118,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 22.04 - containerd: v1.7.16 + containerd: v1.7.17 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -167,15 +167,15 @@ jobs: # ubuntu-22.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.31 + containerd: v1.6.32 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.16 + containerd: v1.7.17 rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.16 + containerd: v1.7.17 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 @@ -183,15 +183,15 @@ jobs: rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.6.31 + containerd: v1.6.32 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.16 + containerd: v1.7.17 rootlesskit: v2.1.0 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.16 + containerd: v1.7.17 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 @@ -300,7 +300,7 @@ jobs: - uses: actions/checkout@v4.1.6 with: repository: containerd/containerd - ref: v1.7.16 + ref: v1.7.17 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -308,7 +308,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.16 + ctrdVersion: 1.7.17 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index 7dffb929c0f..9a4f952acd2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.16 +ARG CONTAINERD_VERSION=v1.7.17 ARG RUNC_VERSION=v1.1.12 ARG CNI_PLUGINS_VERSION=v1.5.0 From eb5d44267a0fc2712b7bf8502019ce94b9d87bd3 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 27 May 2024 11:01:35 +0900 Subject: [PATCH 0471/1066] update slirp4netns (1.3.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.0 | 7 ------- Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.1 | 6 ++++++ 3 files changed, 7 insertions(+), 8 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.1 diff --git a/Dockerfile b/Dockerfile index 9a4f952acd2..52126ebf292 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 ARG IMGCRYPT_VERSION=v1.1.10 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v2.1.0 -ARG SLIRP4NETNS_VERSION=v1.3.0 +ARG SLIRP4NETNS_VERSION=v1.3.1 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.4.1 # Extra deps: FUSE-OverlayFS diff --git a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.0 b/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.0 deleted file mode 100644 index 2436371bfaf..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/slirp4netns-v1.3.0 +++ /dev/null @@ -1,7 +0,0 @@ -c9e31a24ef0860d95b1325c279bc5c5c6282202f3e5dc831e77c1f899e5cb712 SOURCE_DATE_EPOCH -1c1088a05a325f6f33186bab581544c4c06b76ccf7fb816c8cf655a682400a4e slirp4netns-aarch64 -45f465349619f802488e8b429af67a640cb01c77e595163a886c14836a0ebbb2 slirp4netns-armv7l -39711aecf50e4dc23380eda6380b8640f5cd3417a2c2dfa1ca4bf549387b185c slirp4netns-ppc64le -c07219d84640a1da3846a279199c4fda36437185709d4344e605dc98a37b30b6 slirp4netns-riscv64 -49165a25cb89fd08f2fd748884ec6fb7a016dc20c1c2cf22ee039c0d3c2e870d slirp4netns-s390x -bb4da29ad800d0f63ccac6dc5ca92d20d796f25fa2ba0c0be08c629b400f837e slirp4netns-x86_64 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 From 838d5a11cd57eace9b038fac23e776f2414fdd12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 22:29:37 +0000 Subject: [PATCH 0472/1066] build(deps): bump github.com/containerd/imgcrypt from 1.1.10 to 1.1.11 Bumps [github.com/containerd/imgcrypt](https://github.com/containerd/imgcrypt) from 1.1.10 to 1.1.11. - [Release notes](https://github.com/containerd/imgcrypt/releases) - [Changelog](https://github.com/containerd/imgcrypt/blob/main/CHANGES) - [Commits](https://github.com/containerd/imgcrypt/compare/v1.1.10...v1.1.11) --- updated-dependencies: - dependency-name: github.com/containerd/imgcrypt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b16a753ce9c..bfce2fb142e 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 - github.com/containerd/imgcrypt v1.1.10 + github.com/containerd/imgcrypt v1.1.11 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.13.13 github.com/containerd/platforms v0.2.0 diff --git a/go.sum b/go.sum index 82d62601144..7634cc21c31 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9 github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0= github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.1.10 h1:vtyGzTna2wC5BSQcqHWgY4xsBLHWFWyecgK0+9Np8aE= -github.com/containerd/imgcrypt v1.1.10/go.mod h1:9eIPG34EQy+j00fr+4r0knul2MkYDKD2uzKkw8548aw= +github.com/containerd/imgcrypt v1.1.11 h1:3RULIeLouE7B5l9NzMq0HdPWG0DP5deEVxB5UKxyUoU= +github.com/containerd/imgcrypt v1.1.11/go.mod h1:nXL4jp1GrtO758b16DVsxaHHzu9PravAsKARYmyHR58= 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.13 h1:4eCKSNjmozLQ038G2a3X8DEwmrsHsRPMdVGX+zjcaTc= From 3d875395e7437acfa149a41eae6ec424567ff9ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 22:52:26 +0000 Subject: [PATCH 0473/1066] build(deps): bump docker/login-action from 3.1.0 to 3.2.0 Bumps [docker/login-action](https://github.com/docker/login-action) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v3.1.0...v3.2.0) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 4b4ac862124..d98aad58e8a 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -42,7 +42,7 @@ jobs: # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} if: github.event_name != 'pull_request' - uses: docker/login-action@v3.1.0 + uses: docker/login-action@v3.2.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} From 099ef7bd957145707679ea4d30d84b90c16e5661 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 17 May 2024 18:54:18 -0700 Subject: [PATCH 0474/1066] Image history enhancements Signed-off-by: apostasie --- cmd/nerdctl/image_history.go | 70 +++++++++---- cmd/nerdctl/image_history_test.go | 164 ++++++++++++++++++++++++++++++ docs/command-reference.md | 1 + pkg/imgutil/imgutil.go | 3 + 4 files changed, 216 insertions(+), 22 deletions(-) create mode 100644 cmd/nerdctl/image_history_test.go diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index d6024f9c17c..b420e53b447 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -23,17 +23,18 @@ import ( "fmt" "io" "os" + "strconv" "text/tabwriter" "text/template" "time" "github.com/containerd/containerd" - "github.com/containerd/containerd/pkg/progress" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/docker/go-units" "github.com/opencontainers/image-spec/identity" "github.com/spf13/cobra" ) @@ -58,11 +59,16 @@ func addHistoryFlags(cmd *cobra.Command) { return []string{"json"}, cobra.ShellCompDirectiveNoFileComp }) cmd.Flags().BoolP("quiet", "q", false, "Only show numeric IDs") + cmd.Flags().BoolP("human", "H", true, "Print sizes and dates in human readable format (default true)") cmd.Flags().Bool("no-trunc", false, "Don't truncate output") } type historyPrintable struct { + creationTime *time.Time + size int64 + Snapshot string + CreatedAt string CreatedSince string CreatedBy string Size string @@ -101,7 +107,7 @@ func historyAction(cmd *cobra.Command, args []string) error { } var historys []historyPrintable for _, h := range configHistories { - var size string + var size int64 var snapshotName string if !h.EmptyLayer { if len(diffIDs) <= layerCounter { @@ -119,18 +125,18 @@ func historyAction(cmd *cobra.Command, args []string) error { if err != nil { return fmt.Errorf("failed to get usage: %w", err) } - size = progress.Bytes(use.Size).String() + size = use.Size snapshotName = stat.Name layerCounter++ } else { - size = progress.Bytes(0).String() + size = 0 snapshotName = "" } history := historyPrintable{ + creationTime: h.Created, + size: size, Snapshot: snapshotName, - CreatedSince: formatter.TimeSinceInHuman(*h.Created), CreatedBy: h.CreatedBy, - Size: size, Comment: h.Comment, } historys = append(historys, history) @@ -147,9 +153,9 @@ func historyAction(cmd *cobra.Command, args []string) error { } type historyPrinter struct { - w io.Writer - quiet, noTrunc bool - tmpl *template.Template + w io.Writer + quiet, noTrunc, human bool + tmpl *template.Template } func printHistory(cmd *cobra.Command, historys []historyPrintable) error { @@ -161,6 +167,11 @@ func printHistory(cmd *cobra.Command, historys []historyPrintable) error { if err != nil { return err } + human, err := cmd.Flags().GetBool("human") + if err != nil { + return err + } + var w io.Writer w = os.Stdout @@ -179,9 +190,7 @@ func printHistory(cmd *cobra.Command, historys []historyPrintable) error { case "raw": return errors.New("unsupported format: \"raw\"") default: - if quiet { - return errors.New("format and quiet must not be specified together") - } + quiet = false var err error tmpl, err = formatter.ParseTemplate(format) if err != nil { @@ -193,6 +202,7 @@ func printHistory(cmd *cobra.Command, historys []historyPrintable) error { w: w, quiet: quiet, noTrunc: noTrunc, + human: human, tmpl: tmpl, } @@ -208,31 +218,47 @@ func printHistory(cmd *cobra.Command, historys []historyPrintable) error { return nil } -func (x *historyPrinter) printHistory(p historyPrintable) error { +func (x *historyPrinter) printHistory(printable historyPrintable) error { + // Truncate long values unless --no-trunc is passed if !x.noTrunc { - if len(p.CreatedBy) > 45 { - p.CreatedBy = p.CreatedBy[0:44] + "…" + if len(printable.CreatedBy) > 45 { + printable.CreatedBy = printable.CreatedBy[0:44] + "…" + } + // Do not truncate snapshot id if quiet is being passed + if !x.quiet && len(printable.Snapshot) > 45 { + printable.Snapshot = printable.Snapshot[0:44] + "…" } } + + // Format date and size for display based on --human preference + printable.CreatedAt = printable.creationTime.Local().Format(time.RFC3339) + if x.human { + printable.CreatedSince = formatter.TimeSinceInHuman(*printable.creationTime) + printable.Size = units.HumanSize(float64(printable.size)) + } else { + printable.CreatedSince = printable.CreatedAt + printable.Size = strconv.FormatInt(printable.size, 10) + } + if x.tmpl != nil { var b bytes.Buffer - if err := x.tmpl.Execute(&b, p); err != nil { + if err := x.tmpl.Execute(&b, printable); err != nil { return err } if _, err := fmt.Fprintln(x.w, b.String()); err != nil { return err } } else if x.quiet { - if _, err := fmt.Fprintln(x.w, p.Snapshot); err != nil { + if _, err := fmt.Fprintln(x.w, printable.Snapshot); err != nil { return err } } else { if _, err := fmt.Fprintf(x.w, "%s\t%s\t%s\t%s\t%s\n", - p.Snapshot, - p.CreatedSince, - p.CreatedBy, - p.Size, - p.Comment, + printable.Snapshot, + printable.CreatedSince, + printable.CreatedBy, + printable.Size, + printable.Comment, ); err != nil { return err } diff --git a/cmd/nerdctl/image_history_test.go b/cmd/nerdctl/image_history_test.go new file mode 100644 index 00000000000..93b1d942a03 --- /dev/null +++ b/cmd/nerdctl/image_history_test.go @@ -0,0 +1,164 @@ +/* + 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 ( + "encoding/json" + "fmt" + "io" + "runtime" + "strings" + "testing" + "time" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "gotest.tools/v3/assert" +) + +type historyObj struct { + Snapshot string + CreatedAt string + CreatedSince string + CreatedBy string + Size string + Comment string +} + +func imageHistoryJSONHelper(base *testutil.Base, reference string, noTrunc bool, quiet bool, human bool) []historyObj { + cmd := []string{"image", "history"} + if noTrunc { + cmd = append(cmd, "--no-trunc") + } + if quiet { + cmd = append(cmd, "--quiet") + } + cmd = append(cmd, fmt.Sprintf("--human=%t", human)) + cmd = append(cmd, "--format", "json") + cmd = append(cmd, reference) + + cmdResult := base.Cmd(cmd...).Run() + assert.Equal(base.T, cmdResult.ExitCode, 0, cmdResult.Stdout()) + + fmt.Println(cmdResult.Stderr()) + + dec := json.NewDecoder(strings.NewReader(cmdResult.Stdout())) + object := []historyObj{} + for { + var v historyObj + if err := dec.Decode(&v); err == io.EOF { + break + } else if err != nil { + base.T.Fatal(err) + } + object = append(object, v) + } + + return object +} + +func imageHistoryRawHelper(base *testutil.Base, reference string, noTrunc bool, quiet bool, human bool) string { + cmd := []string{"image", "history"} + if noTrunc { + cmd = append(cmd, "--no-trunc") + } + if quiet { + cmd = append(cmd, "--quiet") + } + cmd = append(cmd, fmt.Sprintf("--human=%t", human)) + cmd = append(cmd, reference) + + cmdResult := base.Cmd(cmd...).Run() + assert.Equal(base.T, cmdResult.ExitCode, 0, cmdResult.Stdout()) + + return cmdResult.Stdout() +} + +func TestImageHistory(t *testing.T) { + // Here are the current issues with regard to docker true compatibility: + // - we have a different definition of what a layer id is (snapshot vs. id) + // this will require indepth convergence when moby will handle multi-platform images + // - our definition of size is different + // this requires some investigation to figure out why it differs + // possibly one is unpacked on the filessystem while the other is the tar file size? + // - we do not truncate ids when --quiet has been provided + // this is a conscious decision here - truncating with --quiet does not make much sense + testutil.DockerIncompatible(t) + + base := testutil.NewBase(t) + + // XXX the results here are obviously platform dependent - and it seems like windows cannot pull a linux image? + // Disabling for now + if runtime.GOOS == "windows" { + t.Skip("Windows is not supported for this test right now") + } + + // XXX Currently, history does not work on non-native platform, so, we cannot test reliably on other platforms + if runtime.GOARCH != "arm64" { + t.Skip("Windows is not supported for this test right now") + } + + base.Cmd("pull", "--platform", "linux/arm64", testutil.CommonImage).AssertOK() + + localTimeL1, _ := time.Parse(time.RFC3339, "2021-03-31T10:21:23-07:00") + localTimeL2, _ := time.Parse(time.RFC3339, "2021-03-31T10:21:21-07:00") + + // Human, no quiet, truncate + history := imageHistoryJSONHelper(base, testutil.CommonImage, false, false, true) + compTime1, _ := time.Parse(time.RFC3339, history[0].CreatedAt) + compTime2, _ := time.Parse(time.RFC3339, history[1].CreatedAt) + + // Two layers + assert.Equal(base.T, len(history), 2) + // First layer is a comment - zero size, no snap, + assert.Equal(base.T, history[0].Size, "0B") + assert.Equal(base.T, history[0].CreatedSince, "3 years ago") + assert.Equal(base.T, history[0].Snapshot, "") + assert.Equal(base.T, history[0].Comment, "") + + assert.Equal(base.T, compTime1.UTC().String(), localTimeL1.UTC().String()) + assert.Equal(base.T, history[0].CreatedBy, "/bin/sh -c #(nop) CMD [\"/bin/sh\"]") + + assert.Equal(base.T, compTime2.UTC().String(), localTimeL2.UTC().String()) + assert.Equal(base.T, history[1].CreatedBy, "/bin/sh -c #(nop) ADD file:3b16ffee2b26d8af5…") + + assert.Equal(base.T, history[1].Size, "5.947MB") + assert.Equal(base.T, history[1].CreatedSince, "3 years ago") + assert.Equal(base.T, history[1].Snapshot, "sha256:56bf55b8eed1f0b4794a30386e4d1d3da949c…") + assert.Equal(base.T, history[1].Comment, "") + + // No human - dates and sizes and not prettyfied + history = imageHistoryJSONHelper(base, testutil.CommonImage, false, false, false) + + assert.Equal(base.T, history[0].Size, "0") + assert.Equal(base.T, history[0].CreatedSince, history[0].CreatedAt) + + assert.Equal(base.T, history[1].Size, "5947392") + assert.Equal(base.T, history[1].CreatedSince, history[1].CreatedAt) + + // No trunc - do not truncate sha or cmd + history = imageHistoryJSONHelper(base, testutil.CommonImage, true, false, true) + assert.Equal(base.T, history[1].Snapshot, "sha256:56bf55b8eed1f0b4794a30386e4d1d3da949c25bcb5155e898097cd75dc77c2a") + assert.Equal(base.T, history[1].CreatedBy, "/bin/sh -c #(nop) ADD file:3b16ffee2b26d8af5db152fcc582aaccd9e1ec9e3343874e9969a205550fe07d in / ") + + // Quiet has no effect with format, so, go no-json, no-trunc + rawHistory := imageHistoryRawHelper(base, testutil.CommonImage, true, true, true) + assert.Equal(base.T, rawHistory, "\nsha256:56bf55b8eed1f0b4794a30386e4d1d3da949c25bcb5155e898097cd75dc77c2a\n") + + // With quiet, trunc has no effect + rawHistory = imageHistoryRawHelper(base, testutil.CommonImage, false, true, true) + assert.Equal(base.T, rawHistory, "\nsha256:56bf55b8eed1f0b4794a30386e4d1d3da949c25bcb5155e898097cd75dc77c2a\n") +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 40457da177f..da1d416e544 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -872,6 +872,7 @@ Flags: - :whale: `--no-trunc`: Don't truncate output - :whale: `-q, --quiet`: Only display snapshots IDs - :whale: `--format`: Format the output using the given Go template, e.g, `{{json .}}` +- :whale: `-H, --human`: Print sizes and dates in human readable format (default true) ### :whale: nerdctl image prune diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index e51850920a9..83e6e27f612 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -348,12 +348,15 @@ func ReadImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image, return config, configDesc, err } p, err := content.ReadBlob(ctx, img.ContentStore(), configDesc) + log.G(ctx).Warnf("from blob: %s", string(p)) if err != nil { return config, configDesc, err } if err := json.Unmarshal(p, &config); err != nil { return config, configDesc, err } + deb, _ := json.MarshalIndent(config, "", " ") + log.G(ctx).Warnf("marshalled: %s", deb) return config, configDesc, nil } From 4d4fd5fb13533ac2d536b9f2d0476029e34c64e1 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 29 May 2024 20:20:33 -0700 Subject: [PATCH 0475/1066] State how to run a single integration test Signed-off-by: apostasie --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 36d9bbe1897..82fb8741216 100644 --- a/README.md +++ b/README.md @@ -268,6 +268,10 @@ docker build -t test-integration --target test-integration . docker run -t --rm --privileged test-integration ``` +To run a single integration test (in this case, `image_inspect_test`): + +`go test -exec sudo -v ./cmd/nerdctl/main_test.go ./cmd/nerdctl/image_inspect_test.go ` + #### Running integration test suite against Docker Run `go test -exec sudo -v ./cmd/nerdctl/... -args -test.target=docker` to ensure that the test suite is compatible with Docker. From eb001fadfc9bcaebafe674fcbc674ad256e8e6b5 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 15 May 2024 00:48:43 -0700 Subject: [PATCH 0476/1066] Image inspect rework Signed-off-by: apostasie --- cmd/nerdctl/image_inspect_test.go | 132 ++++++++++++- go.mod | 2 +- pkg/cmd/image/inspect.go | 184 +++++++++++++++--- pkg/inspecttypes/dockercompat/dockercompat.go | 118 ++++++----- pkg/referenceutil/referenceutil.go | 13 ++ 5 files changed, 365 insertions(+), 84 deletions(-) diff --git a/cmd/nerdctl/image_inspect_test.go b/cmd/nerdctl/image_inspect_test.go index f55fd575593..dd28da16df8 100644 --- a/cmd/nerdctl/image_inspect_test.go +++ b/cmd/nerdctl/image_inspect_test.go @@ -17,10 +17,15 @@ package main import ( + "encoding/json" + "runtime" + "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestImageInspectContainsSomeStuff(t *testing.T) { @@ -39,9 +44,134 @@ func TestImageInspectWithFormat(t *testing.T) { base := testutil.NewBase(t) base.Cmd("pull", testutil.CommonImage).AssertOK() + // test RawFormat support base.Cmd("image", "inspect", testutil.CommonImage, "--format", "{{.Id}}").AssertOK() // test typedFormat support base.Cmd("image", "inspect", testutil.CommonImage, "--format", "{{.ID}}").AssertOK() } + +func inspectImageHelper(base *testutil.Base, identifier ...string) []dockercompat.Image { + args := append([]string{"image", "inspect"}, identifier...) + cmdResult := base.Cmd(args...).Run() + assert.Equal(base.T, cmdResult.ExitCode, 0) + var dc []dockercompat.Image + if err := json.Unmarshal([]byte(cmdResult.Stdout()), &dc); err != nil { + base.T.Fatal(err) + } + return dc +} + +func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { + testutil.DockerIncompatible(t) + + if runtime.GOOS == "windows" { + t.Skip("Windows is not supported for this test right now") + } + + base := testutil.NewBase(t) + + // Overall, we need a clean slate before doing these lookups. + // More specifically, because we trigger https://github.com/containerd/nerdctl/issues/3016 + // we cannot do selective rmi, so, just nuke everything + ids := base.Cmd("image", "list", "-q").Out() + allIds := strings.Split(ids, "\n") + for _, id := range allIds { + id = strings.TrimSpace(id) + if id != "" { + base.Cmd("rmi", "-f", id).Run() + } + } + + base.Cmd("pull", "alpine", "--platform", "linux/amd64").AssertOK() + base.Cmd("pull", "busybox", "--platform", "linux/amd64").AssertOK() + base.Cmd("pull", "busybox:stable", "--platform", "linux/amd64").AssertOK() + base.Cmd("pull", "registry-1.docker.io/library/busybox", "--platform", "linux/amd64").AssertOK() + base.Cmd("pull", "registry-1.docker.io/library/busybox:stable", "--platform", "linux/amd64").AssertOK() + + tags := []string{ + "", + ":latest", + ":stable", + } + names := []string{ + "busybox", + "library/busybox", + "docker.io/library/busybox", + "registry-1.docker.io/library/busybox", + } + + // Build reference values for comparison + reference := inspectImageHelper(base, "busybox") + assert.Equal(base.T, 1, len(reference)) + // Extract image sha + sha := strings.TrimPrefix(reference[0].RepoDigests[0], "busybox@sha256:") + + differentReference := inspectImageHelper(base, "alpine") + assert.Equal(base.T, 1, len(differentReference)) + + // Testing all name and tags variants + for _, name := range names { + for _, tag := range tags { + t.Logf("Testing %s", name+tag) + result := inspectImageHelper(base, name+tag) + assert.Equal(base.T, 1, len(result)) + assert.Equal(base.T, reference[0].ID, result[0].ID) + } + } + + // Testing all name and tags variants, with a digest + for _, name := range names { + for _, tag := range tags { + t.Logf("Testing %s", name+tag+"@"+sha) + result := inspectImageHelper(base, name+tag+"@sha256:"+sha) + assert.Equal(base.T, 1, len(result)) + assert.Equal(base.T, reference[0].ID, result[0].ID) + } + } + + // Testing repo digest and short digest with or without prefix + for _, id := range []string{"sha256:" + sha, sha, sha[0:8], "sha256:" + sha[0:8]} { + t.Logf("Testing %s", id) + result := inspectImageHelper(base, id) + assert.Equal(base.T, 1, len(result)) + assert.Equal(base.T, reference[0].ID, result[0].ID) + } + + // Demonstrate image name precedence over digest lookup + // Using the shortened sha should no longer get busybox, but rather the newly tagged Alpine + t.Logf("Testing (alpine tagged) %s", sha[0:8]) + // Tag a different image with the short id + base.Cmd("tag", "alpine", sha[0:8]).AssertOK() + result := inspectImageHelper(base, sha[0:8]) + assert.Equal(base.T, 1, len(result)) + assert.Equal(base.T, differentReference[0].ID, result[0].ID) + + // Prove that wrong references with an existing digest do not get retrieved when asking by digest + for _, id := range []string{"doesnotexist", "doesnotexist:either", "busybox:bogustag"} { + t.Logf("Testing %s", id+"@"+sha) + args := append([]string{"image", "inspect"}, id+"@"+sha) + cmdResult := base.Cmd(args...).Run() + assert.Equal(base.T, cmdResult.ExitCode, 0) + assert.Equal(base.T, cmdResult.Stdout(), "") + } + + // Prove that invalid reference return no result without crashing + for _, id := range []string{"∞∞∞∞∞∞∞∞∞∞", "busybox:∞∞∞∞∞∞∞∞∞∞"} { + t.Logf("Testing %s", id) + args := append([]string{"image", "inspect"}, id) + cmdResult := base.Cmd(args...).Run() + assert.Equal(base.T, cmdResult.ExitCode, 0) + assert.Equal(base.T, cmdResult.Stdout(), "") + } + + // Retrieving multiple entries at once + t.Logf("Testing %s", "busybox busybox busybox:stable") + result = inspectImageHelper(base, "busybox", "busybox", "busybox:stable") + assert.Equal(base.T, 3, len(result)) + assert.Equal(base.T, reference[0].ID, result[0].ID) + assert.Equal(base.T, reference[0].ID, result[1].ID) + assert.Equal(base.T, reference[0].ID, result[2].ID) + +} diff --git a/go.mod b/go.mod index 9d7c20c1e6a..43f6d476590 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,7 @@ require ( github.com/containerd/ttrpc v1.2.3 // indirect github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 // indirect github.com/containers/ocicrypt v1.1.10 // indirect - github.com/distribution/reference v0.6.0 // indirect + github.com/distribution/reference v0.6.0 github.com/djherbis/times v1.6.0 // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect diff --git a/pkg/cmd/image/inspect.go b/pkg/cmd/image/inspect.go index f37e9e0e217..14b571f581e 100644 --- a/pkg/cmd/image/inspect.go +++ b/pkg/cmd/image/inspect.go @@ -19,58 +19,182 @@ package image import ( "context" "fmt" + "regexp" + "strings" "time" "github.com/containerd/containerd" + "github.com/containerd/containerd/images" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" - "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imageinspector" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" + "github.com/distribution/reference" ) +func inspectIdentifier(ctx context.Context, client *containerd.Client, identifier string) ([]images.Image, string, string, error) { + // Figure out what we have here - digest, tag, name + parsedIdentifier, err := referenceutil.ParseAnyReference(identifier) + if err != nil { + return nil, "", "", fmt.Errorf("invalid identifier %s: %w", identifier, err) + } + digest := "" + if identifierDigest, hasDigest := parsedIdentifier.(reference.Digested); hasDigest { + digest = identifierDigest.Digest().String() + } + name := "" + if identifierName, hasName := parsedIdentifier.(reference.Named); hasName { + name = identifierName.Name() + } + tag := "latest" + if identifierTag, hasTag := parsedIdentifier.(reference.Tagged); hasTag && identifierTag.Tag() != "" { + tag = identifierTag.Tag() + } + + // Initialize filters + var filters []string + // This will hold the final image list, if any + var imageList []images.Image + + // No digest in the request? Then assume it is a name + if digest == "" { + filters = []string{fmt.Sprintf("name==%s:%s", name, tag)} + // Query it + imageList, err = client.ImageService().List(ctx, filters...) + if err != nil { + return nil, "", "", fmt.Errorf("containerd image service failed: %w", err) + } + // Nothing? Then it could be a short id (aka truncated digest) - we are going to use this + if len(imageList) == 0 { + digest = fmt.Sprintf("sha256:%s.*", regexp.QuoteMeta(strings.TrimPrefix(identifier, "sha256:"))) + name = "" + tag = "" + } else { + // Otherwise, we found one by name. Get the digest from it. + digest = imageList[0].Target.Digest.String() + } + } + + // At this point, we DO have a digest (or short id), so, that is what we are retrieving + filters = []string{fmt.Sprintf("target.digest~=^%s$", digest)} + imageList, err = client.ImageService().List(ctx, filters...) + if err != nil { + return nil, "", "", fmt.Errorf("containerd image service failed: %w", err) + } + + // TODO: docker does allow retrieving images by Id, so implement as a last ditch effort (probably look-up the store) + + // Return the list we found, along with normalized name and tag + return imageList, name, tag, nil +} + // Inspect prints detailed information of each image in `images`. -func Inspect(ctx context.Context, client *containerd.Client, images []string, options types.ImageInspectOptions) error { - f := &imageInspector{ - mode: options.Mode, +func Inspect(ctx context.Context, client *containerd.Client, identifiers []string, options types.ImageInspectOptions) error { + // Verify we have a valid mode + // TODO: move this out of here, to Cobra command line arg validation + if options.Mode != "native" && options.Mode != "dockercompat" { + return fmt.Errorf("unknown mode %q", options.Mode) } - walker := &imagewalker.ImageWalker{ - Client: client, - OnFound: func(ctx context.Context, found imagewalker.Found) error { - ctx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - n, err := imageinspector.Inspect(ctx, client, found.Image, options.GOptions.Snapshotter) + // Set a timeout + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + // Will hold the final answers + var entries []interface{} + + // We have to query per provided identifier, as we need to post-process results for the case name + digest + for _, identifier := range identifiers { + candidateImageList, requestedName, requestedTag, err := inspectIdentifier(ctx, client, identifier) + if err != nil { + log.G(ctx).WithError(err).WithField("identifier", identifier).Error("failure calling inspect") + continue + } + + var validatedImage *dockercompat.Image + var repoTags []string + var repoDigests []string + + // Go through the candidates + for _, candidateImage := range candidateImageList { + // Inspect the image + candidateNativeImage, err := imageinspector.Inspect(ctx, client, candidateImage, options.GOptions.Snapshotter) if err != nil { - return err + log.G(ctx).WithError(err).WithField("name", candidateImage.Name).Error("failure inspecting image") + continue } - switch f.mode { - case "native": - f.entries = append(f.entries, n) - case "dockercompat": - d, err := dockercompat.ImageFromNative(n) + + // If native, we just add everything in there and that's it + if options.Mode == "native" { + entries = append(entries, candidateNativeImage) + continue + } + + // If dockercompat: does the candidate have a name? Get it if so + candidateRef, err := referenceutil.ParseAnyReference(candidateNativeImage.Image.Name) + if err != nil { + log.G(ctx).WithError(err).WithField("name", candidateNativeImage.Image.Name).Error("the found image has an unparsable name") + continue + } + parsedCandidateNameTag, candidateHasAName := candidateRef.(reference.NamedTagged) + + // If we were ALSO asked for a specific name on top of the digest, we need to make sure we keep only the image with that name + if requestedName != "" { + // If the candidate did not have a name, then we should ignore this one and continue + if !candidateHasAName { + continue + } + + // Otherwise, the candidate has a name. If it is the one we want, store it and continue, otherwise, fall through + candidateTag := parsedCandidateNameTag.Tag() + if candidateTag == "" { + candidateTag = "latest" + } + if parsedCandidateNameTag.Name() == requestedName && candidateTag == requestedTag { + validatedImage, err = dockercompat.ImageFromNative(candidateNativeImage) + if err != nil { + log.G(ctx).WithError(err).WithField("name", candidateNativeImage.Image.Name).Error("could not get a docker compat version of the native image") + } + continue + } + } else if validatedImage == nil { + // Alternatively, we got a request by digest only, so, if we do not know about it already, store it and continue + validatedImage, err = dockercompat.ImageFromNative(candidateNativeImage) if err != nil { - return err + log.G(ctx).WithError(err).WithField("name", candidateNativeImage.Image.Name).Error("could not get a docker compat version of the native image") } - f.entries = append(f.entries, d) - default: - return fmt.Errorf("unknown mode %q", f.mode) + continue + } + + // Fallthrough cases: + // - we got a request by digest, but we already had the image stored + // - we got a request by name, and the name of the candidate did not match the requested name + // Now, check if the candidate has a name - if it does, populate repoTags and repoDigests + if candidateHasAName { + repoTags = append(repoTags, fmt.Sprintf("%s:%s", reference.FamiliarName(parsedCandidateNameTag), parsedCandidateNameTag.Tag())) + repoDigests = append(repoDigests, fmt.Sprintf("%s@%s", reference.FamiliarName(parsedCandidateNameTag), candidateImage.Target.Digest.String())) } - return nil - }, + } + + // Done iterating through candidates. Did we find anything that matches? + if validatedImage != nil { + // Then slap in the repoTags and repoDigests we found from the other candidates + validatedImage.RepoTags = append(validatedImage.RepoTags, repoTags...) + validatedImage.RepoDigests = append(validatedImage.RepoDigests, repoDigests...) + // Store our image + // foundImages[validatedDigest] = validatedImage + entries = append(entries, validatedImage) + } } - err := walker.WalkAll(ctx, images, true) - if len(f.entries) > 0 { - if formatErr := formatter.FormatSlice(options.Format, options.Stdout, f.entries); formatErr != nil { + // Display + if len(entries) > 0 { + if formatErr := formatter.FormatSlice(options.Format, options.Stdout, entries); formatErr != nil { log.G(ctx).Error(formatErr) } } - return err -} -type imageInspector struct { - mode string - entries []interface{} + return nil } diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index da9f714c9df..bd3320977b1 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -37,7 +37,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/runtime/restart" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" @@ -47,28 +47,39 @@ import ( "github.com/tidwall/gjson" ) -// Image mimics a `docker image inspect` object. -// From https://github.com/moby/moby/blob/v20.10.1/api/types/types.go#L340-L374 +// From https://github.com/moby/moby/blob/v26.1.2/api/types/types.go#L34-L140 type Image struct { - ID string `json:"Id"` - RepoTags []string - RepoDigests []string - // TODO: Parent string - Comment string - Created string - // TODO: Container string - // TODO: ContainerConfig *container.Config - // TODO: DockerVersion string - Author string - Config *Config - Architecture string - // TODO: Variant string `json:",omitempty"` - Os string + ID string `json:"Id"` + RepoTags []string + RepoDigests []string + Parent string + Comment string + Created string + DockerVersion string + Author string + Config *Config + Architecture string + Variant string `json:",omitempty"` + Os string + // TODO: OsVersion string `json:",omitempty"` - Size int64 // Size is the unpacked size of the image - // TODO: GraphDriver GraphDriverData + + Size int64 // Size is the unpacked size of the image + VirtualSize int64 `json:"VirtualSize,omitempty"` // Deprecated + + // TODO: GraphDriver GraphDriverData + RootFS RootFS Metadata ImageMetadata + + // Deprecated: TODO: Container string + // Deprecated: TODO: ContainerConfig *container.Config +} + +// From: https://github.com/moby/moby/blob/v26.1.2/api/types/graph_driver_data.go +type GraphDriverData struct { + Data map[string]string `json:"Data"` + Name string `json:"Name"` } type RootFS struct { @@ -294,48 +305,51 @@ func ContainerFromNative(n *native.Container) (*Container, error) { return c, nil } -func ImageFromNative(n *native.Image) (*Image, error) { - i := &Image{} - - imgoci := n.ImageConfig +func ImageFromNative(nativeImage *native.Image) (*Image, error) { + imgOCI := nativeImage.ImageConfig + repository, tag := imgutil.ParseRepoTag(nativeImage.Image.Name) + + image := &Image{ + // Docker ID (digest of platform-specific config), not containerd ID (digest of multi-platform index or manifest) + ID: nativeImage.ImageConfigDesc.Digest.String(), + Parent: nativeImage.Image.Labels["org.mobyproject.image.parent"], + Architecture: imgOCI.Architecture, + Variant: imgOCI.Platform.Variant, + Os: imgOCI.OS, + Size: nativeImage.Size, + VirtualSize: nativeImage.Size, + RepoTags: []string{fmt.Sprintf("%s:%s", repository, tag)}, + RepoDigests: []string{fmt.Sprintf("%s@%s", repository, nativeImage.Image.Target.Digest.String())}, + } - i.RootFS.Type = imgoci.RootFS.Type - diffIDs := imgoci.RootFS.DiffIDs - for _, d := range diffIDs { - i.RootFS.Layers = append(i.RootFS.Layers, d.String()) + if len(imgOCI.History) > 0 { + image.Comment = imgOCI.History[len(imgOCI.History)-1].Comment + image.Created = imgOCI.History[len(imgOCI.History)-1].Created.Format(time.RFC3339Nano) + image.Author = imgOCI.History[len(imgOCI.History)-1].Author } - if len(imgoci.History) > 0 { - i.Comment = imgoci.History[len(imgoci.History)-1].Comment - i.Created = imgoci.History[len(imgoci.History)-1].Created.Format(time.RFC3339Nano) - i.Author = imgoci.History[len(imgoci.History)-1].Author + + image.RootFS.Type = imgOCI.RootFS.Type + for _, d := range imgOCI.RootFS.DiffIDs { + image.RootFS.Layers = append(image.RootFS.Layers, d.String()) } - i.Architecture = imgoci.Architecture - i.Os = imgoci.OS portSet := make(nat.PortSet) - for k := range imgoci.Config.ExposedPorts { + for k := range imgOCI.Config.ExposedPorts { portSet[nat.Port(k)] = struct{}{} } - i.Config = &Config{ - Cmd: imgoci.Config.Cmd, - Volumes: imgoci.Config.Volumes, - Env: imgoci.Config.Env, - User: imgoci.Config.User, - WorkingDir: imgoci.Config.WorkingDir, - Entrypoint: imgoci.Config.Entrypoint, - Labels: imgoci.Config.Labels, + image.Config = &Config{ + Cmd: imgOCI.Config.Cmd, + Volumes: imgOCI.Config.Volumes, + Env: imgOCI.Config.Env, + User: imgOCI.Config.User, + WorkingDir: imgOCI.Config.WorkingDir, + Entrypoint: imgOCI.Config.Entrypoint, + Labels: imgOCI.Config.Labels, ExposedPorts: portSet, } - i.ID = n.ImageConfigDesc.Digest.String() // Docker ID (digest of platform-specific config), not containerd ID (digest of multi-platform index or manifest) - - repository, tag := imgutil.ParseRepoTag(n.Image.Name) - - i.RepoTags = []string{fmt.Sprintf("%s:%s", repository, tag)} - i.RepoDigests = []string{fmt.Sprintf("%s@%s", repository, n.Image.Target.Digest.String())} - i.Size = n.Size - return i, nil + return image, nil } // mountsFromNative only filters bind mount to transform from native container. @@ -411,7 +425,7 @@ func networkSettingsFromNative(n *native.NetNS, sp *specs.Spec) (*NetworkSetting res.Networks[fakeDockerNetworkName] = nes if portsLabel, ok := sp.Annotations[labels.Ports]; ok { - var ports []gocni.PortMapping + var ports []cni.PortMapping err := json.Unmarshal([]byte(portsLabel), &ports) if err != nil { return nil, err @@ -437,7 +451,7 @@ func networkSettingsFromNative(n *native.NetNS, sp *specs.Spec) (*NetworkSetting return res, nil } -func convertToNatPort(portMappings []gocni.PortMapping) (*nat.PortMap, error) { +func convertToNatPort(portMappings []cni.PortMapping) (*nat.PortMap, error) { portMap := make(nat.PortMap) for _, portMapping := range portMappings { ports := []nat.PortBinding{} diff --git a/pkg/referenceutil/referenceutil.go b/pkg/referenceutil/referenceutil.go index 86de6558feb..9507bad23eb 100644 --- a/pkg/referenceutil/referenceutil.go +++ b/pkg/referenceutil/referenceutil.go @@ -32,6 +32,19 @@ type Reference interface { String() string } +// ParseAnyReference parses the passed reference as IPFS, CID, or a classic reference. +// Unlike ParseAny, it is not limited to the DockerRef limitations (being either tagged or digested) +// and should be used instead. +func ParseAnyReference(rawRef string) (Reference, error) { + if scheme, ref, err := ParseIPFSRefWithScheme(rawRef); err == nil { + return Reference(stringRef{scheme: scheme, s: ref}), nil + } + if c, err := cid.Decode(rawRef); err == nil { + return c, nil + } + return refdocker.ParseAnyReference(rawRef) +} + // ParseAny parses the passed reference with allowing it to be non-docker reference. // If the ref has IPFS scheme or can be parsed as CID, it's parsed as an IPFS reference. // Otherwise it's parsed as a docker reference. From f491e83f01f027705aa40a39e1261123577b9c6b Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 30 May 2024 13:28:24 -0700 Subject: [PATCH 0477/1066] Disabling test on unsupported platforms Signed-off-by: apostasie --- cmd/nerdctl/container_run_stargz_linux_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/nerdctl/container_run_stargz_linux_test.go b/cmd/nerdctl/container_run_stargz_linux_test.go index 3c3c621f746..469cb641b00 100644 --- a/cmd/nerdctl/container_run_stargz_linux_test.go +++ b/cmd/nerdctl/container_run_stargz_linux_test.go @@ -17,6 +17,7 @@ package main import ( + "runtime" "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" @@ -24,6 +25,10 @@ import ( func TestRunStargz(t *testing.T) { testutil.DockerIncompatible(t) + if runtime.GOARCH != "amd64" { + t.Skip("skipping test as FedoraESGZImage is amd64 only") + } + base := testutil.NewBase(t) requiresStargz(base) // if stargz snapshotter is functional, "/.stargz-snapshotter" appears From 6917840b83daf76601999e207c6a3de746e0d299 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 29 May 2024 21:29:51 -0700 Subject: [PATCH 0478/1066] CI: .md files changes should not trigger tests Signed-off-by: apostasie --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 032cf892af8..b7136c58519 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,6 +6,8 @@ on: - main - 'release/**' pull_request: + paths-ignore: + - '**.md' env: GO_VERSION: 1.22.x From 11802cf3b38418a715357468c473a783930eea92 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 1 Jun 2024 11:30:50 -0700 Subject: [PATCH 0479/1066] Fix wrong package import Signed-off-by: apostasie --- pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go index f3017176b99..f58cfde0543 100644 --- a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go +++ b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go @@ -23,6 +23,7 @@ import ( "fmt" "os" + "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" dockerconfig "github.com/containerd/containerd/remotes/docker/config" @@ -30,7 +31,6 @@ import ( dockercliconfig "github.com/docker/cli/cli/config" "github.com/docker/cli/cli/config/credentials" dockercliconfigtypes "github.com/docker/cli/cli/config/types" - "github.com/docker/docker/errdefs" ) var PushTracker = docker.NewInMemoryTracker() From 875a962e504ad7fa195bfc2a5783c5d2fedb9463 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 2 Jun 2024 11:12:56 -0700 Subject: [PATCH 0480/1066] Remove spurious debugging leftover Signed-off-by: apostasie --- pkg/imgutil/imgutil.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 83e6e27f612..e51850920a9 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -348,15 +348,12 @@ func ReadImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image, return config, configDesc, err } p, err := content.ReadBlob(ctx, img.ContentStore(), configDesc) - log.G(ctx).Warnf("from blob: %s", string(p)) if err != nil { return config, configDesc, err } if err := json.Unmarshal(p, &config); err != nil { return config, configDesc, err } - deb, _ := json.MarshalIndent(config, "", " ") - log.G(ctx).Warnf("marshalled: %s", deb) return config, configDesc, nil } From 7675d267c04ecfd3dac91013db3c261e755d4ca7 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Mon, 3 Jun 2024 04:17:03 +0000 Subject: [PATCH 0481/1066] update imgcrypt (1.1.11) Signed-off-by: Kay Yan --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 52126ebf292..3d68323aafd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ ARG BUILDKIT_VERSION=v0.13.2 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption -ARG IMGCRYPT_VERSION=v1.1.10 +ARG IMGCRYPT_VERSION=v1.1.11 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v2.1.0 ARG SLIRP4NETNS_VERSION=v1.3.1 From 5b8d5a30b52bca563dc613a7736729384931b8da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 22:28:57 +0000 Subject: [PATCH 0482/1066] build(deps): bump golang.org/x/crypto from 0.23.0 to 0.24.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.23.0 to 0.24.0. - [Commits](https://github.com/golang/crypto/compare/v0.23.0...v0.24.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 83e7023c332..727d666d945 100644 --- a/go.mod +++ b/go.mod @@ -55,12 +55,12 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.23.0 + golang.org/x/crypto v0.24.0 golang.org/x/net v0.25.0 golang.org/x/sync v0.7.0 - golang.org/x/sys v0.20.0 - golang.org/x/term v0.20.0 - golang.org/x/text v0.15.0 + golang.org/x/sys v0.21.0 + golang.org/x/term v0.21.0 + golang.org/x/text v0.16.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) diff --git a/go.sum b/go.sum index 7634cc21c31..a6e415c2410 100644 --- a/go.sum +++ b/go.sum @@ -337,8 +337,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= @@ -397,23 +397,23 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -425,8 +425,8 @@ golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= -golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 2240323d8b9cfdf2db98c701e2fc68d827e47f5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 05:04:33 +0000 Subject: [PATCH 0483/1066] build(deps): bump golang.org/x/net from 0.25.0 to 0.26.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.25.0 to 0.26.0. - [Commits](https://github.com/golang/net/compare/v0.25.0...v0.26.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 727d666d945..50d5897b094 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 golang.org/x/crypto v0.24.0 - golang.org/x/net v0.25.0 + golang.org/x/net v0.26.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.21.0 golang.org/x/term v0.21.0 diff --git a/go.sum b/go.sum index a6e415c2410..69906938b21 100644 --- a/go.sum +++ b/go.sum @@ -362,8 +362,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 530b09136779ff77c2cec24f813ab63cc77d45a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 22:07:26 +0000 Subject: [PATCH 0484/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.1.3+incompatible to 26.1.4+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v26.1.3...v26.1.4) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 50d5897b094..cc5f6f585ae 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 github.com/docker/cli v26.1.3+incompatible - github.com/docker/docker v26.1.3+incompatible + github.com/docker/docker v26.1.4+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 69906938b21..414b1aa949d 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/docker/cli v26.1.3+incompatible h1:bUpXT/N0kDE3VUHI2r5VMsYQgi38kYuoC0oL9yt3lqc= github.com/docker/cli v26.1.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v26.1.3+incompatible h1:lLCzRbrVZrljpVNobJu1J2FHk8V0s4BawoZippkc+xo= -github.com/docker/docker v26.1.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= +github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 47b452613e0ce88fe2b4eced51b5650fbb87631a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 22:07:42 +0000 Subject: [PATCH 0485/1066] build(deps): bump github.com/containerd/containerd from 1.7.17 to 1.7.18 Bumps [github.com/containerd/containerd](https://github.com/containerd/containerd) from 1.7.17 to 1.7.18. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.17...v1.7.18) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 50d5897b094..99ea4ade8f0 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.1.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd v1.7.17 + github.com/containerd/containerd v1.7.18 github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.9 diff --git a/go.sum b/go.sum index 69906938b21..0dca1e2a5d1 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,8 @@ 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.17 h1:KjNnn0+tAVQHAoaWRjmdak9WlvnFR/8rU1CHHy8Rm2A= -github.com/containerd/containerd v1.7.17/go.mod h1:vK+hhT4TIv2uejlcDlbVIc8+h/BqtKLIyNrtCZol8lI= +github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= +github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= 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= From b94caffee291ce751da5daab532873cc2adeff56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Jun 2024 02:34:36 +0000 Subject: [PATCH 0486/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 26.1.3+incompatible to 26.1.4+incompatible. - [Commits](https://github.com/docker/cli/compare/v26.1.3...v26.1.4) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cc5f6f585ae..83bcfa59d93 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 - github.com/docker/cli v26.1.3+incompatible + github.com/docker/cli v26.1.4+incompatible github.com/docker/docker v26.1.4+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 414b1aa949d..c1c5c8ccf94 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v26.1.3+incompatible h1:bUpXT/N0kDE3VUHI2r5VMsYQgi38kYuoC0oL9yt3lqc= -github.com/docker/cli v26.1.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwenxRM7/rLu8= +github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= From 4907e59c086b23ca7d103d740aba089f360fed4c Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Wed, 5 Jun 2024 13:08:56 +0000 Subject: [PATCH 0487/1066] fix container list with json format Signed-off-by: Kay Yan --- cmd/nerdctl/container_list_test.go | 18 ++++++++++++++++++ pkg/cmd/container/list.go | 9 ++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/container_list_test.go b/cmd/nerdctl/container_list_test.go index 9b48b67ef47..8b37a999ec0 100644 --- a/cmd/nerdctl/container_list_test.go +++ b/cmd/nerdctl/container_list_test.go @@ -41,3 +41,21 @@ func TestContainerListWithFormatLabel(t *testing.T) { "--filter", "label="+labelK, "--format", fmt.Sprintf("{{.Label %q}}", labelK)).AssertOutExactly(labelV + "\n") } + +func TestContainerListWithJsonFormatLabel(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + tID := testutil.Identifier(t) + cID := tID + labelK := "label-key-" + tID + labelV := "label-value-" + tID + + base.Cmd("run", "-d", + "--name", cID, + "--label", labelK+"="+labelV, + testutil.CommonImage, "sleep", "infinity").AssertOK() + defer base.Cmd("rm", "-f", cID).AssertOK() + base.Cmd("ps", "-a", + "--filter", "label="+labelK, + "--format", "json").AssertOutContains(fmt.Sprintf("%s=%s", labelK, labelV)) +} diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index b4b0a5f4ee4..5a1c1992531 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -97,12 +97,14 @@ type ListItem struct { Status string Runtime string // nerdctl extension Size string - Labels map[string]string + Labels string + LabelsMap map[string]string `json:"-"` + // TODO: "LocalVolumes", "Mounts", "Networks", "RunningFor", "State" } func (x *ListItem) Label(s string) string { - return x.Labels[s] + return x.LabelsMap[s] } func prepareContainers(ctx context.Context, client *containerd.Client, containers []containerd.Container, options types.ContainerListOptions) ([]ListItem, error) { @@ -138,7 +140,8 @@ func prepareContainers(ctx context.Context, client *containerd.Client, container Ports: formatter.FormatPorts(info.Labels), Status: formatter.ContainerStatus(ctx, c), Runtime: info.Runtime.Name, - Labels: info.Labels, + Labels: formatter.FormatLabels(info.Labels), + LabelsMap: info.Labels, } if options.Size { containerSize, err := getContainerSize(ctx, client, c, info) From e021a92aeb15462a1f0729651fc9185510df9fff Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 6 Jun 2024 14:02:31 +0900 Subject: [PATCH 0488/1066] MAINTAINERS: promote Jin Dong (djdongjin) from a REVIEWER to a COMMITTER Signed-off-by: Akihiro Suda --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index ddee8a402a3..f14b8a88c6c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16,11 +16,11 @@ "fahedouch","Fahed Dorgaa","fahed.dorgaa@gmail.com","EE7A 5503 CE0D 38AC 5B95 A500 F35F F497 60A8 65FA" "Zheaoli", "Zheao Li", "me@manjusaka.me","6E0D D9FA BAD5 AF61 D884 01EE 878F 445D 9C6C E65E" "junnplus","Ye Sijun","junnplus@gmail.com","" +"djdongjin", "Jin Dong", "djdongjin95@gmail.com","" # REVIEWERS # GitHub ID, Name, Email address, GPG fingerprint "jsturtevant","James Sturtevant","jstur@microsoft.com","" "yuchanns", "Hanchin Hsieh", "me@yuchanns.xyz","" "manugupt1", "Manu Gupta", "manugupt1@gmail.com","FCA9 504A 4118 EA5C F466 CC30 A5C3 A8F4 E7FE 9E10" -"djdongjin", "Jin Dong", "djdongjin95@gmail.com","" "yankay", "Kay Yan", "kay.yan@daocloud.io", "" From b0c234922a4b3252f8b2298c52338c8de280f637 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 6 Jun 2024 21:38:25 +0900 Subject: [PATCH 0489/1066] MAINTAINERS: move Hanchin Hsieh (yuchanns) from a REVIEWER to a EMERITUS Hanchin Hsieh (yuchanns) served as a Reviewer of nerdctl from November 2022 to June 2024. Hanchin has made significant contributions such as the addition of syslog driver (#1377) and IPv6 networking (#1558). We show our huge appreciation to Hanchin. Signed-off-by: Akihiro Suda --- EMERITUS.md | 12 ++++++++++++ MAINTAINERS | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 EMERITUS.md diff --git a/EMERITUS.md b/EMERITUS.md new file mode 100644 index 00000000000..0cd95c3840d --- /dev/null +++ b/EMERITUS.md @@ -0,0 +1,12 @@ +See [`MAINTAINERS`](./MAINTAINERS) for the current active maintainers. +- - - +# nerdctl Emeritus Maintainers + +## Reviewers +### Hanchin Hsieh ([@yuchanns](https://github.com/yuchanns)) +Hanchin Hsieh (GitHub ID [@yuchanns](https://github.com/yuchanns)) served as +a Reviewer of nerdctl from November 2022 to June 2024. + +Hanchin has made significant contributions such as the addition of +[syslog driver](https://github.com/containerd/nerdctl/pull/1377) and +[IPv6 networking](https://github.com/containerd/nerdctl/pull/1558). diff --git a/MAINTAINERS b/MAINTAINERS index ddee8a402a3..53482adb39b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20,7 +20,9 @@ # REVIEWERS # GitHub ID, Name, Email address, GPG fingerprint "jsturtevant","James Sturtevant","jstur@microsoft.com","" -"yuchanns", "Hanchin Hsieh", "me@yuchanns.xyz","" "manugupt1", "Manu Gupta", "manugupt1@gmail.com","FCA9 504A 4118 EA5C F466 CC30 A5C3 A8F4 E7FE 9E10" "djdongjin", "Jin Dong", "djdongjin95@gmail.com","" "yankay", "Kay Yan", "kay.yan@daocloud.io", "" + +# EMERITUS +# See EMERITUS.md From 80731ff39a21db7b9b58d4faebaf6ef8009a5cc8 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 21 May 2024 20:50:07 -0700 Subject: [PATCH 0490/1066] Caching and list optimizations Signed-off-by: apostasie --- pkg/cmd/container/inspect.go | 39 +----- pkg/cmd/container/list.go | 33 +++-- pkg/cmd/image/inspect.go | 5 +- pkg/cmd/image/list.go | 178 ++++++++++++++++++--------- pkg/containerdutil/content.go | 89 ++++++++++++++ pkg/containerdutil/helpers.go | 45 +++++++ pkg/containerdutil/snapshotter.go | 61 +++++++++ pkg/imageinspector/imageinspector.go | 8 +- pkg/imgutil/imgutil.go | 65 +++++----- 9 files changed, 372 insertions(+), 151 deletions(-) create mode 100644 pkg/containerdutil/content.go create mode 100644 pkg/containerdutil/helpers.go create mode 100644 pkg/containerdutil/snapshotter.go diff --git a/pkg/cmd/container/inspect.go b/pkg/cmd/container/inspect.go index ee238a7f4d2..564159e2a74 100644 --- a/pkg/cmd/container/inspect.go +++ b/pkg/cmd/container/inspect.go @@ -25,9 +25,11 @@ import ( "github.com/containerd/containerd/snapshots" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerdutil" "github.com/containerd/nerdctl/v2/pkg/containerinspector" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" ) @@ -36,7 +38,7 @@ func Inspect(ctx context.Context, client *containerd.Client, containers []string f := &containerInspector{ mode: options.Mode, size: options.Size, - snapshotter: client.SnapshotService(options.GOptions.Snapshotter), + snapshotter: containerdutil.SnapshotService(client, options.GOptions.Snapshotter), } walker := &containerwalker.ContainerWalker{ @@ -61,39 +63,6 @@ type containerInspector struct { entries []interface{} } -// resourceTotal will return: -// - the Usage value of the resource referenced by ID -// - the cumulative Usage value of the resource, and all parents, recursively -// Typically, for a running container, this will equal the size of the read-write layer, plus the sum of the size of all layers in the base image -func resourceTotal(ctx context.Context, snapshotter snapshots.Snapshotter, resourceID string) (snapshots.Usage, snapshots.Usage, error) { - var first snapshots.Usage - var total snapshots.Usage - var info snapshots.Info - - for next := resourceID; next != ""; next = info.Parent { - // Get the resource usage info - usage, err := snapshotter.Usage(ctx, next) - if err != nil { - return first, total, err - } - // In case that's the first one, store that - if next == resourceID { - first = usage - } - // And increment totals - total.Size += usage.Size - total.Inodes += usage.Inodes - - // Now, get the parent, if any and iterate - info, err = snapshotter.Stat(ctx, next) - if err != nil { - return first, total, err - } - } - - return first, total, nil -} - func (x *containerInspector) Handler(ctx context.Context, found containerwalker.Found) error { ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() @@ -111,7 +80,7 @@ func (x *containerInspector) Handler(ctx context.Context, found containerwalker. return err } if x.size { - resourceUsage, allResourceUsage, err := resourceTotal(ctx, x.snapshotter, d.ID) + resourceUsage, allResourceUsage, err := imgutil.ResourceUsage(ctx, x.snapshotter, d.ID) if err == nil { d.SizeRw = &resourceUsage.Size d.SizeRootFs = &allResourceUsage.Size diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index b4b0a5f4ee4..c69461c1b42 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -25,11 +25,12 @@ import ( "time" "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/pkg/progress" + "github.com/containerd/containerd/snapshots" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerdutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" @@ -107,6 +108,7 @@ func (x *ListItem) Label(s string) string { func prepareContainers(ctx context.Context, client *containerd.Client, containers []containerd.Container, options types.ContainerListOptions) ([]ListItem, error) { listItems := make([]ListItem, len(containers)) + snapshottersCache := map[string]snapshots.Snapshotter{} for i, c := range containers { info, err := c.Info(ctx, containerd.WithoutRefreshedMetadata) if err != nil { @@ -141,7 +143,12 @@ func prepareContainers(ctx context.Context, client *containerd.Client, container Labels: info.Labels, } if options.Size { - containerSize, err := getContainerSize(ctx, client, c, info) + snapshotter, ok := snapshottersCache[info.Snapshotter] + if !ok { + snapshottersCache[info.Snapshotter] = containerdutil.SnapshotService(client, info.Snapshotter) + snapshotter = snapshottersCache[info.Snapshotter] + } + containerSize, err := getContainerSize(ctx, snapshotter, info.SnapshotKey) if err != nil { return nil, err } @@ -180,30 +187,18 @@ func getContainerNetworks(containerLables map[string]string) []string { return networks } -func getContainerSize(ctx context.Context, client *containerd.Client, c containerd.Container, info containers.Container) (string, error) { +func getContainerSize(ctx context.Context, snapshotter snapshots.Snapshotter, snapshotKey string) (string, error) { // get container snapshot size - snapshotKey := info.SnapshotKey var containerSize int64 + var imageSize int64 if snapshotKey != "" { - usage, err := client.SnapshotService(info.Snapshotter).Usage(ctx, snapshotKey) + rw, all, err := imgutil.ResourceUsage(ctx, snapshotter, snapshotKey) if err != nil { return "", err } - containerSize = usage.Size - } - - // get the image interface - image, err := c.Image(ctx) - if err != nil { - return "", err - } - - sn := client.SnapshotService(info.Snapshotter) - - imageSize, err := imgutil.UnpackedImageSize(ctx, sn, image) - if err != nil { - return "", err + containerSize = rw.Size + imageSize = all.Size } return fmt.Sprintf("%s (virtual %s)", progress.Bytes(containerSize).String(), progress.Bytes(imageSize).String()), nil diff --git a/pkg/cmd/image/inspect.go b/pkg/cmd/image/inspect.go index 14b571f581e..aa54de9acb5 100644 --- a/pkg/cmd/image/inspect.go +++ b/pkg/cmd/image/inspect.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerdutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/imageinspector" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" @@ -97,7 +98,6 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin if options.Mode != "native" && options.Mode != "dockercompat" { return fmt.Errorf("unknown mode %q", options.Mode) } - // Set a timeout ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() @@ -105,6 +105,7 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin // Will hold the final answers var entries []interface{} + snapshotter := containerdutil.SnapshotService(client, options.GOptions.Snapshotter) // We have to query per provided identifier, as we need to post-process results for the case name + digest for _, identifier := range identifiers { candidateImageList, requestedName, requestedTag, err := inspectIdentifier(ctx, client, identifier) @@ -120,7 +121,7 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin // Go through the candidates for _, candidateImage := range candidateImageList { // Inspect the image - candidateNativeImage, err := imageinspector.Inspect(ctx, client, candidateImage, options.GOptions.Snapshotter) + candidateNativeImage, err := imageinspector.Inspect(ctx, client, candidateImage, snapshotter) if err != nil { log.G(ctx).WithError(err).WithField("name", candidateImage.Name).Error("failure inspecting image") continue diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 4bd8843442c..95266e8dc18 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -19,10 +19,10 @@ package image import ( "bytes" "context" + "encoding/json" "errors" "fmt" "io" - "path" "strings" "text/tabwriter" "text/template" @@ -31,14 +31,16 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" - "github.com/containerd/containerd/pkg/progress" "github.com/containerd/containerd/snapshots" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerdutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/platforms" - v1 "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/docker/go-units" + "github.com/opencontainers/image-spec/identity" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // ListCommandHandler `List` and print images matching filters in `options`. @@ -161,15 +163,15 @@ func printImages(ctx context.Context, client *containerd.Client, imageList []ima } printer := &imagePrinter{ - w: w, - quiet: options.Quiet, - noTrunc: options.NoTrunc, - digestsFlag: digestsFlag, - namesFlag: options.Names, - tmpl: tmpl, - client: client, - contentStore: client.ContentStore(), - snapshotter: client.SnapshotService(options.GOptions.Snapshotter), + w: w, + quiet: options.Quiet, + noTrunc: options.NoTrunc, + digestsFlag: digestsFlag, + namesFlag: options.Names, + tmpl: tmpl, + client: client, + provider: containerdutil.NewProvider(client), + snapshotter: containerdutil.SnapshotService(client, options.GOptions.Snapshotter), } for _, img := range imageList { @@ -188,50 +190,127 @@ type imagePrinter struct { quiet, noTrunc, digestsFlag, namesFlag bool tmpl *template.Template client *containerd.Client - contentStore content.Store + provider content.Provider snapshotter snapshots.Snapshotter } -func (x *imagePrinter) printImage(ctx context.Context, img images.Image) error { - ociPlatforms, err := images.Platforms(ctx, x.contentStore, img.Target) +type image struct { + blobSize int64 + size int64 + platform platforms.Platform + config *ocispec.Descriptor +} + +func readManifest(ctx context.Context, provider content.Provider, snapshotter snapshots.Snapshotter, desc ocispec.Descriptor) (*image, error) { + // Read the manifest blob from the descriptor + manifestData, err := containerdutil.ReadBlob(ctx, provider, desc) if err != nil { - log.G(ctx).WithError(err).Warnf("failed to get the platform list of image %q", img.Name) - return x.printImageSinglePlatform(ctx, img, platforms.DefaultSpec()) + return nil, err } - psm := map[string]struct{}{} - for _, ociPlatform := range ociPlatforms { - platformKey := makePlatformKey(ociPlatform) - if _, done := psm[platformKey]; done { - continue - } - psm[platformKey] = struct{}{} - if err := x.printImageSinglePlatform(ctx, img, ociPlatform); err != nil { - log.G(ctx).WithError(err).Warnf("failed to get platform %q of image %q", platforms.Format(ociPlatform), img.Name) - } + + // Unmarshal as Manifest + var manifest ocispec.Manifest + if err := json.Unmarshal(manifestData, &manifest); err != nil { + return nil, err } - return nil + + // Now, read the config + configData, err := containerdutil.ReadBlob(ctx, provider, manifest.Config) + if err != nil { + return nil, err + } + + // Unmarshal as Image + var config ocispec.Image + if err := json.Unmarshal(configData, &config); err != nil { + log.G(ctx).Error("Error unmarshaling config") + return nil, err + } + + // If we are here, the image exists and is valid, so, do our size lookups + + // Aggregate the descriptor size, and blob size from the config and layers + blobSize := desc.Size + manifest.Config.Size + for _, layerDescriptor := range manifest.Layers { + blobSize += layerDescriptor.Size + } + + // Get the platform + plt := platforms.Normalize(ocispec.Platform{OS: config.OS, Architecture: config.Architecture, Variant: config.Variant}) + + // Get the filesystem size for all layers + chainID := identity.ChainID(config.RootFS.DiffIDs).String() + size := int64(0) + if _, actualSize, err := imgutil.ResourceUsage(ctx, snapshotter, chainID); err == nil { + size = actualSize.Size + } + + return &image{ + blobSize: blobSize, + size: size, + platform: plt, + config: &manifest.Config, + }, nil } -func makePlatformKey(platform v1.Platform) string { - if platform.OS == "" { - return "unknown" +func readIndex(ctx context.Context, provider content.Provider, snapshotter snapshots.Snapshotter, desc ocispec.Descriptor) (map[string]*image, error) { + descs := map[string]*image{} + + // Read the index + indexData, err := containerdutil.ReadBlob(ctx, provider, desc) + if err != nil { + return nil, err + } + + // Unmarshal as Index + var index ocispec.Index + if err := json.Unmarshal(indexData, &index); err != nil { + return nil, err } - return path.Join(platform.OS, platform.Architecture, platform.OSVersion, platform.Variant) + // Iterate over manifest descriptors and read them all + for _, manifestDescriptor := range index.Manifests { + manifest, err := readManifest(ctx, provider, snapshotter, manifestDescriptor) + if err != nil { + continue + } + descs[platforms.FormatAll(manifest.platform)] = manifest + } + return descs, err } -func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images.Image, ociPlatform v1.Platform) error { - platMC := platforms.OnlyStrict(ociPlatform) - if avail, _, _, _, availErr := images.Check(ctx, x.contentStore, img.Target, platMC); !avail { - log.G(ctx).WithError(availErr).Debugf("skipping printing image %q for platform %q", img.Name, platforms.Format(ociPlatform)) - return nil +func read(ctx context.Context, provider content.Provider, snapshotter snapshots.Snapshotter, desc ocispec.Descriptor) (map[string]*image, error) { + if images.IsManifestType(desc.MediaType) { + manifest, err := readManifest(ctx, provider, snapshotter, desc) + if err != nil { + return nil, err + } + descs := map[string]*image{} + descs[platforms.FormatAll(manifest.platform)] = manifest + return descs, nil + } + if images.IsIndexType(desc.MediaType) { + return readIndex(ctx, provider, snapshotter, desc) } + return nil, fmt.Errorf("unknown media type: %s", desc.MediaType) +} - image := containerd.NewImageWithPlatform(x.client, img, platMC) - desc, err := image.Config(ctx) +func (x *imagePrinter) printImage(ctx context.Context, img images.Image) error { + candidateImages, err := read(ctx, x.provider, x.snapshotter, img.Target) if err != nil { - log.G(ctx).WithError(err).Warnf("failed to get config of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) + return err } + + for platform, desc := range candidateImages { + if err := x.printImageSinglePlatform(*desc.config, img, desc.blobSize, desc.size, desc.platform); err != nil { + log.G(ctx).WithError(err).Debugf("failed to get platform %q of image %q", platform, img.Name) + } + } + + return nil +} + +func (x *imagePrinter) printImageSinglePlatform(desc ocispec.Descriptor, img images.Image, blobSize int64, size int64, plt platforms.Platform) error { var ( repository string tag string @@ -241,17 +320,6 @@ func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images. repository, tag = imgutil.ParseRepoTag(img.Name) } - blobSize, err := image.Size(ctx) - if err != nil { - log.G(ctx).WithError(err).Warnf("failed to get blob size of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) - } - - size, err := imgutil.UnpackedImageSize(ctx, x.snapshotter, image) - if err != nil { - // Warnf is too verbose: https://github.com/containerd/nerdctl/issues/2058 - log.G(ctx).WithError(err).Debugf("failed to get unpacked size of image %q for platform %q", img.Name, platforms.Format(ociPlatform)) - } - p := imagePrintable{ CreatedAt: img.CreatedAt.Round(time.Second).Local().String(), // format like "2021-08-07 02:19:45 +0900 JST" CreatedSince: formatter.TimeSinceInHuman(img.CreatedAt), @@ -260,9 +328,9 @@ func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images. Repository: repository, Tag: tag, Name: img.Name, - Size: progress.Bytes(size).String(), - BlobSize: progress.Bytes(blobSize).String(), - Platform: platforms.Format(ociPlatform), + Size: units.HumanSize(float64(size)), + BlobSize: units.HumanSize(float64(blobSize)), + Platform: platforms.FormatAll(plt), } if p.Repository == "" { p.Repository = "" @@ -279,7 +347,7 @@ func (x *imagePrinter) printImageSinglePlatform(ctx context.Context, img images. if err := x.tmpl.Execute(&b, p); err != nil { return err } - if _, err = fmt.Fprintln(x.w, b.String()); err != nil { + if _, err := fmt.Fprintln(x.w, b.String()); err != nil { return err } } else if x.quiet { diff --git a/pkg/containerdutil/content.go b/pkg/containerdutil/content.go new file mode 100644 index 00000000000..6c7742a3d29 --- /dev/null +++ b/pkg/containerdutil/content.go @@ -0,0 +1,89 @@ +/* + 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 containerdutil provides "caching" versions of containerd native snapshotter and content store. +// NOTE: caching should only be used for single, atomic operations, like `nerdctl images`, and NOT kept +// across successive, distincts operations. As such, caching is not persistent across invocations of nerdctl, +// and only lasts as long as the lifetime of the Snapshotter or ContentStore. +package containerdutil + +import ( + "context" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/content" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +// ContentStore should be called to get a Provider with caching +func NewProvider(client *containerd.Client) content.Provider { + return &providerWithCache{ + client.ContentStore(), + make(map[string]*readerAtWithCache), + } +} + +type providerWithCache struct { + native content.Provider + cache map[string]*readerAtWithCache +} + +func (provider *providerWithCache) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) { + key := desc.Digest.String() + // If we had en entry already, get the size over + value, ok := provider.cache[key] + if !ok { + newReaderAt, err := provider.native.ReaderAt(ctx, desc) + if err != nil { + return nil, err + } + // Build the final object + value = &readerAtWithCache{ + newReaderAt, + -1, + func() { + delete(provider.cache, key) + }, + } + // Cache it + provider.cache[key] = value + } + + return value, nil +} + +// ReaderAtWithCache implements the content.ReaderAt interface +type readerAtWithCache struct { + content.ReaderAt + size int64 + prune func() +} + +func (rac *readerAtWithCache) Size() int64 { + // local implementation in containerd technically provides a similar mechanism, so, this method not really useful + // by default - but obviously, this is implementation dependent + if rac.size == -1 { + rac.size = rac.ReaderAt.Size() + } + return rac.size +} + +func (rac *readerAtWithCache) Close() error { + err := rac.ReaderAt.Close() + // Remove ourselves from the cache + rac.prune() + return err +} diff --git a/pkg/containerdutil/helpers.go b/pkg/containerdutil/helpers.go new file mode 100644 index 00000000000..1d410035ffd --- /dev/null +++ b/pkg/containerdutil/helpers.go @@ -0,0 +1,45 @@ +/* + 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 containerdutil + +import ( + "context" + + "github.com/containerd/containerd/content" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +var ReadBlob = readBlobWithCache() + +type readBlob func(ctx context.Context, provider content.Provider, desc ocispec.Descriptor) ([]byte, error) + +func readBlobWithCache() readBlob { + var cache = make(map[string]([]byte)) + + return func(ctx context.Context, provider content.Provider, desc ocispec.Descriptor) ([]byte, error) { + var err error + v, ok := cache[desc.Digest.String()] + if !ok { + v, err = content.ReadBlob(ctx, provider, desc) + if err == nil { + cache[desc.Digest.String()] = v + } + } + + return v, err + } +} diff --git a/pkg/containerdutil/snapshotter.go b/pkg/containerdutil/snapshotter.go new file mode 100644 index 00000000000..738e98f7a69 --- /dev/null +++ b/pkg/containerdutil/snapshotter.go @@ -0,0 +1,61 @@ +/* + 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 containerdutil + +import ( + "context" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/snapshots" +) + +// SnapshotService should be called to get a new caching snapshotter +func SnapshotService(client *containerd.Client, snapshotterName string) snapshots.Snapshotter { + return &snapshotterWithCache{ + client.SnapshotService(snapshotterName), + map[string]snapshots.Info{}, + map[string]snapshots.Usage{}, + } +} + +type snapshotterWithCache struct { + snapshots.Snapshotter + statCache map[string]snapshots.Info + usageCache map[string]snapshots.Usage +} + +func (snap *snapshotterWithCache) Stat(ctx context.Context, key string) (snapshots.Info, error) { + if stat, ok := snap.statCache[key]; ok { + return stat, nil + } + stat, err := snap.Snapshotter.Stat(ctx, key) + if err == nil { + snap.statCache[key] = stat + } + return stat, err +} + +func (snap *snapshotterWithCache) Usage(ctx context.Context, key string) (snapshots.Usage, error) { + if usage, ok := snap.usageCache[key]; ok { + return usage, nil + } + usage, err := snap.Snapshotter.Usage(ctx, key) + if err == nil { + snap.usageCache[key] = usage + } + return usage, err +} diff --git a/pkg/imageinspector/imageinspector.go b/pkg/imageinspector/imageinspector.go index 239720e154f..c5f34a8995f 100644 --- a/pkg/imageinspector/imageinspector.go +++ b/pkg/imageinspector/imageinspector.go @@ -21,13 +21,14 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/images" + "github.com/containerd/containerd/snapshots" "github.com/containerd/log" - imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) // Inspect inspects the image, for the platform specified in image.platform. -func Inspect(ctx context.Context, client *containerd.Client, image images.Image, snapshotter string) (*native.Image, error) { +func Inspect(ctx context.Context, client *containerd.Client, image images.Image, snapshotter snapshots.Snapshotter) (*native.Image, error) { n := &native.Image{} @@ -55,8 +56,7 @@ func Inspect(ctx context.Context, client *containerd.Client, image images.Image, n.ImageConfigDesc = imageConfigDesc n.ImageConfig = imageConfig } - snapSvc := client.SnapshotService(snapshotter) - n.Size, err = imgutil.UnpackedImageSize(ctx, snapSvc, img) + n.Size, err = imgutil.UnpackedImageSize(ctx, snapshotter, img) if err != nil { log.G(ctx).WithError(err).WithField("id", image.Name).Warnf("failed to inspect calculate size") } diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index e51850920a9..71e010459aa 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -377,27 +377,36 @@ func ParseRepoTag(imgName string) (string, string) { return repository, tag } -type snapshotKey string - -// recursive function to calculate total usage of key's parent -func (key snapshotKey) add(ctx context.Context, s snapshots.Snapshotter, usage *snapshots.Usage) error { - if key == "" { - return nil - } - u, err := s.Usage(ctx, string(key)) - if err != nil { - return err - } - - usage.Add(u) +// ResourceUsage will return: +// - the Usage value of the resource referenced by ID +// - the cumulative Usage value of the resource, and all parents, recursively +// Typically, for a running container, this will equal the size of the read-write layer, plus the sum of the size of all layers in the base image +func ResourceUsage(ctx context.Context, snapshotter snapshots.Snapshotter, resourceID string) (snapshots.Usage, snapshots.Usage, error) { + first := snapshots.Usage{} + total := snapshots.Usage{} + var info snapshots.Info + for next := resourceID; next != ""; next = info.Parent { + // Get the resource usage info + usage, err := snapshotter.Usage(ctx, next) + if err != nil { + return first, total, err + } + // In case that's the first one, store that + if next == resourceID { + first = usage + } + // And increment totals + total.Size += usage.Size + total.Inodes += usage.Inodes - info, err := s.Stat(ctx, string(key)) - if err != nil { - return err + // Now, get the parent, if any and iterate + info, err = snapshotter.Stat(ctx, next) + if err != nil { + return first, total, err + } } - key = snapshotKey(info.Parent) - return key.add(ctx, s, usage) + return first, total, nil } // UnpackedImageSize is the size of the unpacked snapshots. @@ -409,23 +418,7 @@ func UnpackedImageSize(ctx context.Context, s snapshots.Snapshotter, img contain } chainID := identity.ChainID(diffIDs).String() - usage, err := s.Usage(ctx, chainID) - if err != nil { - if errdefs.IsNotFound(err) { - log.G(ctx).WithError(err).Debugf("image %q seems not unpacked", img.Name()) - return 0, nil - } - return 0, err - } - - info, err := s.Stat(ctx, chainID) - if err != nil { - return 0, err - } + _, total, err := ResourceUsage(ctx, s, chainID) - //add ChainID's parent usage to the total usage - if err := snapshotKey(info.Parent).add(ctx, s, &usage); err != nil { - return 0, err - } - return usage.Size, nil + return total.Size, err } From dc237a354f96dd75b5c53f5ceca2c49cbc672a50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jun 2024 22:44:15 +0000 Subject: [PATCH 0491/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.12.3 to 0.12.4 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.12.3 to 0.12.4. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.3...v0.12.4) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 72ae9146983..2ee403678ba 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.2 - github.com/Microsoft/hcsshim v0.12.3 + github.com/Microsoft/hcsshim v0.12.4 github.com/awslabs/soci-snapshotter v0.6.1 github.com/compose-spec/compose-go v1.20.2 github.com/containerd/accelerated-container-image v1.1.3 diff --git a/go.sum b/go.sum index 391d6e37f3e..c5bdefae7a3 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= 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.12.3 h1:LS9NXqXhMoqNCplK1ApmVSfB4UnVLRDWRapB6EIlxE0= -github.com/Microsoft/hcsshim v0.12.3/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ= +github.com/Microsoft/hcsshim v0.12.4 h1:Ev7YUMHAHoWNm+aDSPzc5W9s6E2jyL1szpVDJeZ/Rr4= +github.com/Microsoft/hcsshim v0.12.4/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ= github.com/awslabs/soci-snapshotter v0.6.1 h1:ggiuiCPReSNvfUL084Ujyp0glRNiCsZiaCh2rE580HA= github.com/awslabs/soci-snapshotter v0.6.1/go.mod h1:o9NuuMmvmcpc+jRSoJlQqSqrWCjMO1x67C65wmCme7E= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= From edb8c19d0a7eacb5367627cbb3b12b88a8f0ba88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 22:05:37 +0000 Subject: [PATCH 0492/1066] build(deps): bump docker/build-push-action from 5.3.0 to 5.4.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.3.0 to 5.4.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v5.3.0...v5.4.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index d98aad58e8a..af907e8ee28 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -59,7 +59,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v5.3.0 + uses: docker/build-push-action@v5.4.0 with: context: . platforms: linux/amd64,linux/arm64 From b20070d2c1152ad9fa6fa6e8b7a9a2b64f24dd80 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 6 Jun 2024 13:28:20 -0700 Subject: [PATCH 0493/1066] Revamped testregistry and login tests Signed-off-by: apostasie --- cmd/nerdctl/compose_run_linux_test.go | 7 +- .../container_run_verify_linux_test.go | 7 +- cmd/nerdctl/image_convert_linux_test.go | 22 +- cmd/nerdctl/image_encrypt_linux_test.go | 6 +- cmd/nerdctl/image_pull_linux_test.go | 16 +- cmd/nerdctl/image_push_linux_test.go | 52 +- cmd/nerdctl/login_linux_test.go | 392 +++++++++----- cmd/nerdctl/multi_platform_linux_test.go | 18 +- pkg/testutil/portlock/portlock.go | 64 +++ pkg/testutil/testca/testca.go | 12 +- pkg/testutil/testregistry/certsd.go | 47 ++ .../testregistry/testregistry_linux.go | 509 +++++++++++------- pkg/testutil/testutil.go | 2 +- 13 files changed, 755 insertions(+), 399 deletions(-) create mode 100644 pkg/testutil/portlock/portlock.go create mode 100644 pkg/testutil/testregistry/certsd.go diff --git a/cmd/nerdctl/compose_run_linux_test.go b/cmd/nerdctl/compose_run_linux_test.go index ea075f4e9d9..74874d4d298 100644 --- a/cmd/nerdctl/compose_run_linux_test.go +++ b/cmd/nerdctl/compose_run_linux_test.go @@ -432,12 +432,13 @@ func TestComposePushAndPullWithCosignVerify(t *testing.T) { keyPair := newCosignKeyPair(t, "cosign-key-pair") defer keyPair.cleanup() - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) + localhostIP := "127.0.0.1" t.Logf("localhost IP=%q", localhostIP) testImageRefPrefix := fmt.Sprintf("%s:%d/", - localhostIP, reg.ListenPort) + localhostIP, reg.Port) t.Logf("testImageRefPrefix=%q", testImageRefPrefix) var ( diff --git a/cmd/nerdctl/container_run_verify_linux_test.go b/cmd/nerdctl/container_run_verify_linux_test.go index e5c500d59da..306403c9cd9 100644 --- a/cmd/nerdctl/container_run_verify_linux_test.go +++ b/cmd/nerdctl/container_run_verify_linux_test.go @@ -34,12 +34,13 @@ func TestRunVerifyCosign(t *testing.T) { base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) + localhostIP := "127.0.0.1" t.Logf("localhost IP=%q", localhostIP) testImageRef := fmt.Sprintf("%s:%d/%s", - localhostIP, reg.ListenPort, tID) + localhostIP, reg.Port, tID) t.Logf("testImageRef=%q", testImageRef) dockerfile := fmt.Sprintf(`FROM %s diff --git a/cmd/nerdctl/image_convert_linux_test.go b/cmd/nerdctl/image_convert_linux_test.go index c6fb457d962..a8b53401d72 100644 --- a/cmd/nerdctl/image_convert_linux_test.go +++ b/cmd/nerdctl/image_convert_linux_test.go @@ -33,7 +33,10 @@ func TestImageConvertNydus(t *testing.T) { } testutil.RequireExecutable(t, "nydus-image") testutil.DockerIncompatible(t) + base := testutil.NewBase(t) + t.Parallel() + convertedImage := testutil.Identifier(t) + ":nydus" base.Cmd("rmi", convertedImage).Run() base.Cmd("pull", testutil.CommonImage).AssertOK() @@ -48,18 +51,20 @@ func TestImageConvertNydus(t *testing.T) { t.Skip("Nydusify check is not supported rootless mode.") } - // skip if nydusify is not installed + // skip if nydusify and nydusd are not installed testutil.RequireExecutable(t, "nydusify") + testutil.RequireExecutable(t, "nydusd") // setup local docker registry - registryPort := 15000 - registry := testregistry.NewPlainHTTP(base, registryPort) - defer registry.Cleanup() + registry := testregistry.NewWithNoAuth(base, 0, false) + remoteImage := fmt.Sprintf("%s:%d/nydusd-image:test", "localhost", registry.Port) + t.Cleanup(func() { + base.Cmd("rmi", remoteImage).Run() + registry.Cleanup(nil) + }) - remoteImage := fmt.Sprintf("%s:%d/nydusd-image:test", registry.IP.String(), registryPort) base.Cmd("tag", convertedImage, remoteImage).AssertOK() - defer base.Cmd("rmi", remoteImage).Run() - base.Cmd("push", "--insecure-registry", remoteImage).AssertOK() + base.Cmd("push", remoteImage).AssertOK() nydusifyCmd := testutil.Cmd{ Cmd: icmd.Command( "nydusify", @@ -73,5 +78,8 @@ func TestImageConvertNydus(t *testing.T) { ), Base: base, } + + // nydus is creating temporary files - make sure we are in a proper location for that + nydusifyCmd.Cmd.Dir = base.T.TempDir() nydusifyCmd.AssertOK() } diff --git a/cmd/nerdctl/image_encrypt_linux_test.go b/cmd/nerdctl/image_encrypt_linux_test.go index d20daa60b9a..f6ba49ab5f1 100644 --- a/cmd/nerdctl/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image_encrypt_linux_test.go @@ -113,10 +113,10 @@ func TestImageEncryptJWE(t *testing.T) { defer keyPair.cleanup() base := testutil.NewBase(t) tID := testutil.Identifier(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) base.Cmd("pull", testutil.CommonImage).AssertOK() - encryptImageRef := fmt.Sprintf("127.0.0.1:%d/%s:encrypted", reg.ListenPort, tID) + encryptImageRef := fmt.Sprintf("127.0.0.1:%d/%s:encrypted", reg.Port, tID) defer base.Cmd("rmi", encryptImageRef).Run() base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.pub, testutil.CommonImage, encryptImageRef).AssertOK() base.Cmd("image", "inspect", "--mode=native", "--format={{len .Index.Manifests}}", encryptImageRef).AssertOutExactly("1\n") diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image_pull_linux_test.go index 931d7905737..37153c3d7af 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image_pull_linux_test.go @@ -67,12 +67,12 @@ func TestImageVerifyWithCosign(t *testing.T) { base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) localhostIP := "127.0.0.1" t.Logf("localhost IP=%q", localhostIP) testImageRef := fmt.Sprintf("%s:%d/%s", - localhostIP, reg.ListenPort, tID) + localhostIP, reg.Port, tID) t.Logf("testImageRef=%q", testImageRef) dockerfile := fmt.Sprintf(`FROM %s @@ -91,8 +91,8 @@ func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { testutil.RequiresBuild(t) base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() - reg := testregistry.NewPlainHTTP(base, 80) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 80, false) + defer reg.Cleanup(nil) testImageRef := fmt.Sprintf("%s/%s:%s", reg.IP.String(), testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) t.Logf("testImageRef=%q", testImageRef) @@ -117,12 +117,12 @@ func TestImageVerifyWithCosignShouldFailWhenKeyIsNotCorrect(t *testing.T) { base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) localhostIP := "127.0.0.1" t.Logf("localhost IP=%q", localhostIP) testImageRef := fmt.Sprintf("%s:%d/%s", - localhostIP, reg.ListenPort, tID) + localhostIP, reg.Port, tID) t.Logf("testImageRef=%q", testImageRef) dockerfile := fmt.Sprintf(`FROM %s diff --git a/cmd/nerdctl/image_push_linux_test.go b/cmd/nerdctl/image_push_linux_test.go index 0a65980e19c..79fa63f52cb 100644 --- a/cmd/nerdctl/image_push_linux_test.go +++ b/cmd/nerdctl/image_push_linux_test.go @@ -30,12 +30,12 @@ import ( func TestPushPlainHTTPFails(t *testing.T) { testutil.RequiresBuild(t) base := testutil.NewBase(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) base.Cmd("pull", testutil.CommonImage).AssertOK() testImageRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.ListenPort, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) + reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) t.Logf("testImageRef=%q", testImageRef) base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() @@ -49,14 +49,14 @@ func TestPushPlainHTTPFails(t *testing.T) { func TestPushPlainHTTPLocalhost(t *testing.T) { testutil.RequiresBuild(t) base := testutil.NewBase(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) localhostIP := "127.0.0.1" t.Logf("localhost IP=%q", localhostIP) base.Cmd("pull", testutil.CommonImage).AssertOK() testImageRef := fmt.Sprintf("%s:%d/%s:%s", - localhostIP, reg.ListenPort, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) + localhostIP, reg.Port, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) t.Logf("testImageRef=%q", testImageRef) base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() @@ -69,12 +69,12 @@ func TestPushPlainHTTPInsecure(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) base.Cmd("pull", testutil.CommonImage).AssertOK() testImageRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.ListenPort, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) + reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) t.Logf("testImageRef=%q", testImageRef) base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() @@ -87,8 +87,8 @@ func TestPushPlainHttpInsecureWithDefaultPort(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - reg := testregistry.NewPlainHTTP(base, 80) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 80, false) + defer reg.Cleanup(nil) base.Cmd("pull", testutil.CommonImage).AssertOK() testImageRef := fmt.Sprintf("%s/%s:%s", @@ -105,14 +105,14 @@ func TestPushInsecureWithLogin(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - reg := testregistry.NewHTTPS(base, "admin", "badmin") - defer reg.Cleanup() + reg := testregistry.NewWithTokenAuth(base, "admin", "badmin", 0, true) + defer reg.Cleanup(nil) base.Cmd("--insecure-registry", "login", "-u", "admin", "-p", "badmin", - fmt.Sprintf("%s:%d", reg.IP.String(), reg.ListenPort)).AssertOK() + fmt.Sprintf("%s:%d", reg.IP.String(), reg.Port)).AssertOK() base.Cmd("pull", testutil.CommonImage).AssertOK() testImageRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.ListenPort, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) + reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) t.Logf("testImageRef=%q", testImageRef) base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() @@ -126,14 +126,14 @@ func TestPushWithHostsDir(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - reg := testregistry.NewHTTPS(base, "admin", "badmin") - defer reg.Cleanup() + reg := testregistry.NewWithTokenAuth(base, "admin", "badmin", 0, true) + defer reg.Cleanup(nil) - base.Cmd("--hosts-dir", reg.HostsDir, "login", "-u", "admin", "-p", "badmin", fmt.Sprintf("%s:%d", reg.IP.String(), reg.ListenPort)).AssertOK() + base.Cmd("--hosts-dir", reg.HostsDir, "login", "-u", "admin", "-p", "badmin", fmt.Sprintf("%s:%d", reg.IP.String(), reg.Port)).AssertOK() base.Cmd("pull", testutil.CommonImage).AssertOK() testImageRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.ListenPort, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) + reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) t.Logf("testImageRef=%q", testImageRef) base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() @@ -147,18 +147,18 @@ func TestPushNonDistributableArtifacts(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) base.Cmd("pull", testutil.NonDistBlobImage).AssertOK() testImgRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.ListenPort, testutil.Identifier(t), strings.Split(testutil.NonDistBlobImage, ":")[1]) + reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.NonDistBlobImage, ":")[1]) base.Cmd("tag", testutil.NonDistBlobImage, testImgRef).AssertOK() base.Cmd("--debug", "--insecure-registry", "push", testImgRef).AssertOK() - blobURL := fmt.Sprintf("http://%s:%d/v2/%s/blobs/%s", reg.IP.String(), reg.ListenPort, testutil.Identifier(t), testutil.NonDistBlobDigest) + blobURL := fmt.Sprintf("http://%s:%d/v2/%s/blobs/%s", reg.IP.String(), reg.Port, testutil.Identifier(t), testutil.NonDistBlobDigest) resp, err := http.Get(blobURL) assert.Assert(t, err, "error making http request") if resp.Body != nil { @@ -179,12 +179,12 @@ func TestPushSoci(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) requiresSoci(base) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) base.Cmd("pull", testutil.UbuntuImage).AssertOK() testImageRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.ListenPort, testutil.Identifier(t), strings.Split(testutil.UbuntuImage, ":")[1]) + reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.UbuntuImage, ":")[1]) t.Logf("testImageRef=%q", testImageRef) base.Cmd("tag", testutil.UbuntuImage, testImageRef).AssertOK() diff --git a/cmd/nerdctl/login_linux_test.go b/cmd/nerdctl/login_linux_test.go index ce145e530ee..4429b4480ea 100644 --- a/cmd/nerdctl/login_linux_test.go +++ b/cmd/nerdctl/login_linux_test.go @@ -17,174 +17,310 @@ package main import ( + "crypto/rand" + "encoding/base64" "fmt" "net" - "path" + "os" "strconv" "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testca" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" + "gotest.tools/v3/icmd" ) -func TestLogin(t *testing.T) { - // Skip docker, because Docker doesn't have `--hosts-dir` option, and we don't want to contaminate the global /etc/docker/certs.d during this test - testutil.DockerIncompatible(t) +func safeRandomString(n int) string { + b := make([]byte, n) + _, _ = rand.Read(b) + // XXX WARNING there is something in the registry (or more likely in the way we generate htpasswd files) + // that is broken and does not resist truly random strings + // return string(b) + return base64.URLEncoding.EncodeToString(b) +} - base := testutil.NewBase(t) - reg := testregistry.NewHTTPS(base, "admin", "validTestPassword") - defer reg.Cleanup() +type Client struct { + args []string + configPath string +} + +func (ag *Client) WithInsecure(value bool) *Client { + ag.args = append(ag.args, "--insecure-registry="+strconv.FormatBool(value)) + return ag +} - regHost := net.JoinHostPort(reg.IP.String(), strconv.Itoa(reg.ListenPort)) +func (ag *Client) WithHostsDir(hostDirs string) *Client { + ag.args = append(ag.args, "--hosts-dir", hostDirs) + return ag +} - t.Logf("Good password") - base.Cmd("--debug-full", "--hosts-dir", reg.HostsDir, "login", "-u", "admin", "-p", "validTestPassword", regHost).AssertOK() +func (ag *Client) WithCredentials(username, password string) *Client { + ag.args = append(ag.args, "--username", username, "--password", password) + return ag +} - t.Logf("Bad password") - base.Cmd("--debug-full", "--hosts-dir", reg.HostsDir, "login", "-u", "admin", "-p", "invalidTestPassword", regHost).AssertFail() +func (ag *Client) Run(base *testutil.Base, host string) *testutil.Cmd { + if ag.configPath == "" { + ag.configPath, _ = os.MkdirTemp(base.T.TempDir(), "docker-config") + } + args := append([]string{"--debug-full", "login"}, ag.args...) + icmdCmd := icmd.Command(base.Binary, append(base.Args, append(args, host)...)...) + icmdCmd.Env = append(base.Env, "HOME="+os.Getenv("HOME"), "DOCKER_CONFIG="+ag.configPath) + return &testutil.Cmd{ + Cmd: icmdCmd, + Base: base, + } } -func TestLoginWithSpecificRegHosts(t *testing.T) { - // Skip docker, because Docker doesn't have `--hosts-dir` option, and we don't want to contaminate the global /etc/docker/certs.d during this test +func TestLogin(t *testing.T) { + // Skip docker, because Docker doesn't have `--hosts-dir` nor `insecure-registry` option testutil.DockerIncompatible(t) base := testutil.NewBase(t) - reg := testregistry.NewHTTPS(base, "admin", "validTestPassword") - defer reg.Cleanup() + t.Parallel() - regHost := net.JoinHostPort(reg.IP.String(), strconv.Itoa(reg.ListenPort)) + testregistry.EnsureImages(base) - t.Logf("Prepare regHost URL with path and Scheme") - - type testCase struct { - url string - log string - } - testCases := []testCase{ + testCases := []struct { + port int + tls bool + auth string + insecure bool + }{ { - url: "https://" + path.Join(regHost, "test"), - log: "Login with repository containing path and scheme in the URL", + 80, + false, + "basic", + true, }, { - url: path.Join(regHost, "test"), - log: "Login with repository containing path and without scheme in the URL", + 443, + false, + "basic", + true, + }, + { + 0, + false, + "basic", + true, + }, + { + 80, + true, + "basic", + false, + }, + { + 443, + true, + "basic", + false, + }, + { + 0, + true, + "basic", + false, }, - } - for _, tc := range testCases { - t.Logf(tc.log) - base.Cmd("--debug-full", "--hosts-dir", reg.HostsDir, "login", "-u", "admin", "-p", "validTestPassword", tc.url).AssertOK() - } - -} - -func TestLoginWithPlainHttp(t *testing.T) { - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - reg5000 := testregistry.NewAuthWithHTTP(base, "admin", "validTestPassword", 5000, 5001) - reg80 := testregistry.NewAuthWithHTTP(base, "admin", "validTestPassword", 80, 5002) - defer reg5000.Cleanup() - defer reg80.Cleanup() - testCasesForPort5000 := []struct { - regHost string - regPort int - useRegPort bool - username string - password string - shouldSuccess bool - registry *testregistry.TestRegistry - shouldUseInSecure bool - }{ { - regHost: "127.0.0.1", - regPort: 5000, - useRegPort: true, - username: "admin", - password: "validTestPassword", - shouldSuccess: true, - registry: reg5000, - shouldUseInSecure: true, + 80, + false, + "token", + true, }, { - regHost: "127.0.0.1", - regPort: 5000, - useRegPort: true, - username: "admin", - password: "invalidTestPassword", - shouldSuccess: false, - registry: reg5000, - shouldUseInSecure: true, + 443, + false, + "token", + true, }, { - regHost: "127.0.0.1", - regPort: 5000, - useRegPort: true, - username: "admin", - password: "validTestPassword", - // Following the merging of the below, any localhost/loopback registries will - // get automatically downgraded to HTTP so this will still succceed: - // https://github.com/containerd/containerd/pull/7393 - shouldSuccess: true, - registry: reg5000, - shouldUseInSecure: false, + 0, + false, + "token", + true, }, { - regHost: "127.0.0.1", - regPort: 80, - useRegPort: false, - username: "admin", - password: "validTestPassword", - shouldSuccess: true, - registry: reg80, - shouldUseInSecure: true, + 80, + true, + "token", + false, }, { - regHost: "127.0.0.1", - regPort: 80, - useRegPort: false, - username: "admin", - password: "invalidTestPassword", - shouldSuccess: false, - registry: reg80, - shouldUseInSecure: true, + 443, + true, + "token", + false, }, { - regHost: "127.0.0.1", - regPort: 80, - useRegPort: false, - username: "admin", - password: "validTestPassword", - // Following the merging of the below, any localhost/loopback registries will - // get automatically downgraded to HTTP so this will still succceed: - // https://github.com/containerd/containerd/pull/7393 - shouldSuccess: true, - registry: reg80, - shouldUseInSecure: false, + 0, + true, + "token", + false, }, } - for _, tc := range testCasesForPort5000 { - tcName := fmt.Sprintf("%+v", tc) - t.Run(tcName, func(t *testing.T) { - regHost := tc.regHost - if tc.useRegPort { - regHost = fmt.Sprintf("%s:%d", regHost, tc.regPort) + + for _, tc := range testCases { + // Since we have a lock mechanism for acquiring ports, we can just parallelize everything + t.Run(fmt.Sprintf("Login against registry with tls: %t port: %d auth: %s", tc.tls, tc.port, tc.auth), func(t *testing.T) { + // Tests with fixed ports should not be parallelized (although the port locking mechanism will prevent conflicts) + // as their children are, and this might deadlock given how Parallel works + if tc.port == 0 { + t.Parallel() + } + + // Generate credentials so that we never cross hit another test registry (spiced up with unicode) + // Note that the grammar for basic auth does not allow colons in usernames, while token auth allows it + username := safeRandomString(30) + "∞" + password := safeRandomString(30) + ":∞" + + // Get a CA if we want TLS + var ca *testca.CA + if tc.tls { + ca = testca.New(base.T) } - if tc.shouldSuccess { - t.Logf("Good password") - } else { - t.Logf("Bad password") + + // Add the requested authentication + var auth testregistry.Auth + auth = &testregistry.NoAuth{} + var dependentCleanup func(error) + if tc.auth == "basic" { + auth = &testregistry.BasicAuth{ + Username: username, + Password: password, + } + } else if tc.auth == "token" { + authCa := ca + // We could be on !tls - still need a ca to sign jwt + if authCa == nil { + authCa = testca.New(base.T) + } + as := testregistry.NewAuthServer(base, authCa, 0, username, password, tc.tls) + auth = &testregistry.TokenAuth{ + Address: as.Scheme + "://" + net.JoinHostPort(as.IP.String(), strconv.Itoa(as.Port)), + CertPath: as.CertPath, + } + dependentCleanup = as.Cleanup } - var args []string - if tc.shouldUseInSecure { - args = append(args, "--insecure-registry") + + // Start the registry + reg := testregistry.NewRegistry(base, ca, tc.port, auth, dependentCleanup) + + // Attach our cleanup function + t.Cleanup(func() { + reg.Cleanup(nil) + }) + + regHosts := []string{ + net.JoinHostPort(reg.IP.String(), strconv.Itoa(reg.Port)), } - args = append(args, []string{ - "--debug-full", "--hosts-dir", tc.registry.HostsDir, "login", "-u", tc.username, "-p", tc.password, regHost, - }...) - cmd := base.Cmd(args...) - if tc.shouldSuccess { - cmd.AssertOK() - } else { - cmd.AssertFail() + + // XXX seems like omitting ports is broken on main currently + // (plus the hosts.toml resolution is not good either) + // XXX we should also add hostname here (maybe use the container name?) + // Obviously also need to add localhost to the mix once we fix behavior + /* + if reg.Port == 443 || reg.Port == 80 { + regHosts = append(regHosts, reg.IP.String()) + } + */ + + for _, value := range regHosts { + regHost := value + t.Run(regHost, func(t *testing.T) { + t.Parallel() + + t.Run("Valid credentials (no certs) ", func(t *testing.T) { + t.Parallel() + c := (&Client{}). + WithCredentials(username, password) + + // Fail without insecure + c.Run(base, regHost).AssertFail() + + // Succeed with insecure + c.WithInsecure(true). + Run(base, regHost).AssertOK() + }) + + t.Run("Valid credentials (with certs)", func(t *testing.T) { + t.Parallel() + c := (&Client{}). + WithCredentials(username, password). + WithHostsDir(reg.HostsDir) + + if tc.insecure { + c.Run(base, regHost).AssertFail() + } else { + c.Run(base, regHost).AssertOK() + } + + c.WithInsecure(true). + Run(base, regHost).AssertOK() + }) + + t.Run("Valid credentials (with certs), any variant", func(t *testing.T) { + t.Parallel() + c := (&Client{}). + WithCredentials(username, password). + WithHostsDir(reg.HostsDir). + // Just use insecure here for all servers - it does not matter for what we are testing here + WithInsecure(true) + + c.Run(base, "http://"+regHost).AssertOK() + c.Run(base, "https://"+regHost).AssertOK() + c.Run(base, "http://"+regHost+"/whatever?foo=bar;foo:bar#foo=bar").AssertOK() + c.Run(base, "https://"+regHost+"/whatever?foo=bar&bar=foo;foo=foo+bar:bar#foo=bar").AssertOK() + }) + + t.Run("Wrong pass (no certs)", func(t *testing.T) { + t.Parallel() + c := (&Client{}). + WithCredentials(username, "invalid") + + c.Run(base, regHost).AssertFail() + + c.WithInsecure(true). + Run(base, regHost).AssertFail() + }) + + t.Run("Wrong user (no certs)", func(t *testing.T) { + t.Parallel() + c := (&Client{}). + WithCredentials("invalid", password) + + c.Run(base, regHost).AssertFail() + + c.WithInsecure(true). + Run(base, regHost).AssertFail() + }) + + t.Run("Wrong pass (with certs)", func(t *testing.T) { + t.Parallel() + c := (&Client{}). + WithCredentials(username, "invalid"). + WithHostsDir(reg.HostsDir) + + c.Run(base, regHost).AssertFail() + + c.WithInsecure(true). + Run(base, regHost).AssertFail() + }) + + t.Run("Wrong user (with certs)", func(t *testing.T) { + t.Parallel() + c := (&Client{}). + WithCredentials("invalid", password). + WithHostsDir(reg.HostsDir) + + c.Run(base, regHost).AssertFail() + + c.WithInsecure(true). + Run(base, regHost).AssertFail() + }) + }) } }) } diff --git a/cmd/nerdctl/multi_platform_linux_test.go b/cmd/nerdctl/multi_platform_linux_test.go index f46210b98ff..cf9b130dd59 100644 --- a/cmd/nerdctl/multi_platform_linux_test.go +++ b/cmd/nerdctl/multi_platform_linux_test.go @@ -57,10 +57,10 @@ func TestMultiPlatformBuildPush(t *testing.T) { base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) - imageName := fmt.Sprintf("localhost:%d/%s:latest", reg.ListenPort, tID) + imageName := fmt.Sprintf("localhost:%d/%s:latest", reg.Port, tID) defer base.Cmd("rmi", imageName).Run() dockerfile := fmt.Sprintf(`FROM %s @@ -84,10 +84,10 @@ func TestMultiPlatformBuildPushNoRun(t *testing.T) { base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) - imageName := fmt.Sprintf("localhost:%d/%s:latest", reg.ListenPort, tID) + imageName := fmt.Sprintf("localhost:%d/%s:latest", reg.Port, tID) defer base.Cmd("rmi", imageName).Run() dockerfile := fmt.Sprintf(`FROM %s @@ -105,10 +105,10 @@ func TestMultiPlatformPullPushAllPlatforms(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) tID := testutil.Identifier(t) - reg := testregistry.NewPlainHTTP(base, 5000) - defer reg.Cleanup() + reg := testregistry.NewWithNoAuth(base, 0, false) + defer reg.Cleanup(nil) - pushImageName := fmt.Sprintf("localhost:%d/%s:latest", reg.ListenPort, tID) + pushImageName := fmt.Sprintf("localhost:%d/%s:latest", reg.Port, tID) defer base.Cmd("rmi", pushImageName).Run() base.Cmd("pull", "--all-platforms", testutil.AlpineImage).AssertOK() diff --git a/pkg/testutil/portlock/portlock.go b/pkg/testutil/portlock/portlock.go new file mode 100644 index 00000000000..5e1b5bcacee --- /dev/null +++ b/pkg/testutil/portlock/portlock.go @@ -0,0 +1,64 @@ +/* + 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. +*/ + +// portlock provides a mechanism for containers to acquire and release ports they plan to expose, and a wait mechanism +// This allows tests dependent on running containers to always parallelize without having to worry about port collision +// with any other test +// Note that this does NOT protect against trying to use a port that is already used by an unrelated third-party service or container +// Also note that *generally* finding a free port is not easy: +// - to just "listen" and see if it works won't work for containerized services that are DNAT-ed (plus, that would be racy) +// - inspecting iptables instead (or in addition to) may work for containers, but this depends on how networking has been set (and yes, it is also racy) +// Our approach here is optimistic: tests are responsible for calling Acquire and Release +package portlock + +import ( + "fmt" + "sync" + "time" +) + +var mut = &sync.Mutex{} //nolint:gochecknoglobals +var portList = map[int]bool{} + +func Acquire(port int) (int, error) { + flexible := false + if port == 0 { + port = 5000 + flexible = true + } + for { + mut.Lock() + if _, ok := portList[port]; !ok { + portList[port] = true + mut.Unlock() + return port, nil + } + mut.Unlock() + if flexible { + port++ + continue + } + fmt.Println("Waiting for port to become available...", port) + time.Sleep(1 * time.Second) + } +} + +func Release(port int) error { + mut.Lock() + delete(portList, port) + mut.Unlock() + return nil +} diff --git a/pkg/testutil/testca/testca.go b/pkg/testutil/testca/testca.go index 3ae92ccc923..53a0eddd37c 100644 --- a/pkg/testutil/testca/testca.go +++ b/pkg/testutil/testca/testca.go @@ -95,12 +95,14 @@ func (c *Cert) Close() error { return c.closeF() } -func (ca *CA) NewCert(host string) *Cert { +func (ca *CA) NewCert(host string, additional ...string) *Cert { t := ca.t key, err := rsa.GenerateKey(rand.Reader, keyLength) assert.NilError(t, err) + additional = append([]string{host}, additional...) + cert := &x509.Certificate{ SerialNumber: serialNumber(t), Subject: pkix.Name{ @@ -111,10 +113,12 @@ func (ca *CA) NewCert(host string) *Cert { NotAfter: time.Now().Add(24 * time.Hour), KeyUsage: x509.KeyUsageCRLSign, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - DNSNames: []string{host}, + DNSNames: additional, } - if ip := net.ParseIP(host); ip != nil { - cert.IPAddresses = append(cert.IPAddresses, ip) + for _, h := range additional { + if ip := net.ParseIP(h); ip != nil { + cert.IPAddresses = append(cert.IPAddresses, ip) + } } dir, err := os.MkdirTemp(t.TempDir(), "cert") diff --git a/pkg/testutil/testregistry/certsd.go b/pkg/testutil/testregistry/certsd.go new file mode 100644 index 00000000000..955bc4ba12f --- /dev/null +++ b/pkg/testutil/testregistry/certsd.go @@ -0,0 +1,47 @@ +/* + 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 testregistry + +import ( + "fmt" + "net" + "os" + "path/filepath" + "strconv" +) + +func generateCertsd(dir string, certPath string, hostIP string, port int) error { + joined := hostIP + if port != 0 { + joined = net.JoinHostPort(hostIP, strconv.Itoa(port)) + } + + hostsSubDir := filepath.Join(dir, joined) + err := os.MkdirAll(hostsSubDir, 0700) + if err != nil { + return err + } + + hostsTOMLPath := filepath.Join(hostsSubDir, "hosts.toml") + // See https://github.com/containerd/containerd/blob/main/docs/hosts.md + hostsTOML := fmt.Sprintf(` +server = "https://%s" +[host."https://%s"] + ca = %q + `, joined, joined, certPath) + return os.WriteFile(hostsTOMLPath, []byte(hostsTOML), 0700) +} diff --git a/pkg/testutil/testregistry/testregistry_linux.go b/pkg/testutil/testregistry/testregistry_linux.go index 4b15df56e68..b5c05525846 100644 --- a/pkg/testutil/testregistry/testregistry_linux.go +++ b/pkg/testutil/testregistry/testregistry_linux.go @@ -25,175 +25,70 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/portlock" "github.com/containerd/nerdctl/v2/pkg/testutil/testca" - "golang.org/x/crypto/bcrypt" "gotest.tools/v3/assert" ) -type TestRegistry struct { - IP net.IP - ListenIP net.IP - ListenPort int - HostsDir string // contains ":/hosts.toml" - Cleanup func() - Logs func() +type RegistryServer struct { + IP net.IP + Port int + Scheme string + ListenIP net.IP + Cleanup func(err error) + Logs func() + HostsDir string // contains ":/hosts.toml" } -func NewPlainHTTP(base *testutil.Base, port int) *TestRegistry { - hostIP, err := nettestutil.NonLoopbackIPv4() - assert.NilError(base.T, err) - // listen on 0.0.0.0 to enable 127.0.0.1 - listenIP := net.ParseIP("0.0.0.0") - listenPort := port - base.T.Logf("hostIP=%q, listenIP=%q, listenPort=%d", hostIP, listenIP, listenPort) +type TokenAuthServer struct { + IP net.IP + Port int + Scheme string + ListenIP net.IP + Cleanup func(err error) + Logs func() + Auth Auth + CertPath string +} - registryContainerName := "reg-" + testutil.Identifier(base.T) - cmd := base.Cmd("run", - "-d", - "-p", fmt.Sprintf("%s:%d:5000", listenIP, listenPort), - "--name", registryContainerName, - testutil.RegistryImage) - cmd.AssertOK() - if _, err = nettestutil.HTTPGet(fmt.Sprintf("http://%s:%d/v2", hostIP.String(), listenPort), 30, false); err != nil { - base.Cmd("rm", "-f", registryContainerName).Run() - base.T.Fatal(err) - } - return &TestRegistry{ - IP: hostIP, - ListenIP: listenIP, - ListenPort: listenPort, - Cleanup: func() { base.Cmd("rm", "-f", registryContainerName).AssertOK() }, - } +func EnsureImages(base *testutil.Base) { + base.Cmd("pull", testutil.RegistryImage).AssertOK() + base.Cmd("pull", testutil.DockerAuthImage).AssertOK() } -func NewAuthWithHTTP(base *testutil.Base, user, pass string, listenPort int, authPort int) *TestRegistry { +func NewAuthServer(base *testutil.Base, ca *testca.CA, port int, user, pass string, tls bool) *TokenAuthServer { name := testutil.Identifier(base.T) - hostIP, err := nettestutil.NonLoopbackIPv4() - assert.NilError(base.T, err) // listen on 0.0.0.0 to enable 127.0.0.1 listenIP := net.ParseIP("0.0.0.0") - base.T.Logf("hostIP=%q, listenIP=%q, listenPort=%d, authPort=%d", hostIP, listenIP, listenPort, authPort) - - ca := testca.New(base.T) - registryCert := ca.NewCert(hostIP.String()) - authCert := ca.NewCert(hostIP.String()) - + hostIP, err := nettestutil.NonLoopbackIPv4() + assert.NilError(base.T, err, fmt.Errorf("failed finding ipv4 non loopback interface: %w", err)) // Prepare configuration file for authentication server // Details: https://github.com/cesanta/docker_auth/blob/1.7.1/examples/simple.yml - authConfigFile, err := os.CreateTemp("", "authconfig") - assert.NilError(base.T, err) + configFile, err := os.CreateTemp("", "authconfig") + assert.NilError(base.T, err, fmt.Errorf("failed creating temporary directory for config file: %w", err)) bpass, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) - assert.NilError(base.T, err) - authConfigFileName := authConfigFile.Name() - _, err = authConfigFile.Write([]byte(fmt.Sprintf(` + assert.NilError(base.T, err, fmt.Errorf("failed bcrypt encrypting password: %w", err)) + configFileName := configFile.Name() + scheme := "http" + configContent := fmt.Sprintf(` server: addr: ":5100" - certificate: "/auth/domain.crt" - key: "/auth/domain.key" token: issuer: "Acme auth server" expiration: 900 + certificate: "/auth/domain.crt" + key: "/auth/domain.key" users: "%s": password: "%s" acl: - match: {account: "%s"} actions: ["*"] -`, user, string(bpass), user))) - assert.NilError(base.T, err) - - // Run authentication server - authContainerName := fmt.Sprintf("auth-%s-%d", name, authPort) - cmd := base.Cmd("run", - "-d", - "-p", fmt.Sprintf("%s:%d:5100", listenIP, authPort), - "--name", authContainerName, - "-v", authCert.CertPath+":/auth/domain.crt", - "-v", authCert.KeyPath+":/auth/domain.key", - "-v", authConfigFileName+":/config/auth_config.yml", - testutil.DockerAuthImage, - "/config/auth_config.yml") - cmd.AssertOK() - - // Run docker_auth-enabled registry - // Details: https://github.com/cesanta/docker_auth/blob/1.7.1/examples/simple.yml - registryContainerName := fmt.Sprintf("%s-%s-%d", "reg", name, listenPort) - cmd = base.Cmd("run", - "-d", - "-p", fmt.Sprintf("%s:%d:5000", listenIP, listenPort), - "--name", registryContainerName, - "--env", "REGISTRY_AUTH=token", - "--env", "REGISTRY_AUTH_TOKEN_REALM="+fmt.Sprintf("https://%s:%d/auth", hostIP.String(), authPort), - "--env", "REGISTRY_AUTH_TOKEN_SERVICE=Docker registry", - "--env", "REGISTRY_AUTH_TOKEN_ISSUER=Acme auth server", - "--env", "REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE=/auth/domain.crt", - // rootcertbundle is not CA cert: https://github.com/distribution/distribution/issues/1143 - "-v", authCert.CertPath+":/auth/domain.crt", - testutil.RegistryImage) - cmd.AssertOK() - joined := net.JoinHostPort(hostIP.String(), strconv.Itoa(listenPort)) - if _, err = nettestutil.HTTPGet(fmt.Sprintf("http://%s/v2", joined), 30, true); err != nil { - base.Cmd("rm", "-f", registryContainerName).Run() - base.T.Fatal(err) - } - hostsDir, err := os.MkdirTemp(base.T.TempDir(), "certs.d") - assert.NilError(base.T, err) - hostsSubDir := filepath.Join(hostsDir, joined) - err = os.MkdirAll(hostsSubDir, 0700) - assert.NilError(base.T, err) - hostsTOMLPath := filepath.Join(hostsSubDir, "hosts.toml") - // See https://github.com/containerd/containerd/blob/main/docs/hosts.md - hostsTOML := fmt.Sprintf(` -server = "https://%s" -[host."https://%s"] - ca = %q - `, joined, joined, ca.CertPath) - base.T.Logf("Writing %q: %q", hostsTOMLPath, hostsTOML) - err = os.WriteFile(hostsTOMLPath, []byte(hostsTOML), 0700) - assert.NilError(base.T, err) - return &TestRegistry{ - IP: hostIP, - ListenIP: listenIP, - ListenPort: listenPort, - HostsDir: hostsDir, - Cleanup: func() { - base.Cmd("rm", "-f", registryContainerName).AssertOK() - base.Cmd("rm", "-f", authContainerName).AssertOK() - assert.NilError(base.T, registryCert.Close()) - assert.NilError(base.T, authCert.Close()) - assert.NilError(base.T, authConfigFile.Close()) - os.Remove(authConfigFileName) - }, - Logs: func() { - base.T.Logf("%s: %q", registryContainerName, base.Cmd("logs", registryContainerName).Run().String()) - base.T.Logf("%s: %q", authContainerName, base.Cmd("logs", authContainerName).Run().String()) - }, - } -} - -func NewHTTPS(base *testutil.Base, user, pass string) *TestRegistry { - name := testutil.Identifier(base.T) - hostIP, err := nettestutil.NonLoopbackIPv4() - assert.NilError(base.T, err) - // listen on 0.0.0.0 to enable 127.0.0.1 - listenIP := net.ParseIP("0.0.0.0") - const listenPort = 5000 // TODO: choose random empty port - const authPort = 5100 // TODO: choose random empty port - base.T.Logf("hostIP=%q, listenIP=%q, listenPort=%d, authPort=%d", hostIP, listenIP, listenPort, authPort) - - ca := testca.New(base.T) - registryCert := ca.NewCert(hostIP.String()) - authCert := ca.NewCert(hostIP.String()) - - // Prepare configuration file for authentication server - // Details: https://github.com/cesanta/docker_auth/blob/1.7.1/examples/simple.yml - authConfigFile, err := os.CreateTemp("", "authconfig") - assert.NilError(base.T, err) - bpass, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) - assert.NilError(base.T, err) - authConfigFileName := authConfigFile.Name() - _, err = authConfigFile.Write([]byte(fmt.Sprintf(` +`, user, string(bpass), user) + if tls { + scheme = "https" + configContent = fmt.Sprintf(` server: addr: ":5100" certificate: "/auth/domain.crt" @@ -207,78 +102,278 @@ users: acl: - match: {account: "%s"} actions: ["*"] -`, user, string(bpass), user))) - assert.NilError(base.T, err) +`, user, string(bpass), user) + } + _, err = configFile.Write([]byte(configContent)) + assert.NilError(base.T, err, fmt.Errorf("failed writing configuration: %w", err)) - // Run authentication server - authContainerName := "auth-" + name - cmd := base.Cmd("run", - "-d", - "-p", fmt.Sprintf("%s:%d:5100", listenIP, authPort), - "--name", authContainerName, - "-v", authCert.CertPath+":/auth/domain.crt", - "-v", authCert.KeyPath+":/auth/domain.key", - "-v", authConfigFileName+":/config/auth_config.yml", - testutil.DockerAuthImage, - "/config/auth_config.yml") - cmd.AssertOK() - - // Run docker_auth-enabled registry - // Details: https://github.com/cesanta/docker_auth/blob/1.7.1/examples/simple.yml - registryContainerName := "reg-" + name - cmd = base.Cmd("run", - "-d", - "-p", fmt.Sprintf("%s:%d:5000", listenIP, listenPort), - "--name", registryContainerName, + cert := ca.NewCert(hostIP.String()) + + port, err = portlock.Acquire(port) + assert.NilError(base.T, err, fmt.Errorf("failed acquiring port: %w", err)) + containerName := fmt.Sprintf("auth-%s-%d", name, port) + + cleanup := func(err error) { + result := base.Cmd("rm", "-f", containerName).Run() + errPortRelease := portlock.Release(port) + errCertClose := cert.Close() + errConfigClose := configFile.Close() + errConfigRemove := os.Remove(configFileName) + if err == nil { + assert.NilError(base.T, result.Error, fmt.Errorf("failed stopping container: %w", err)) + assert.NilError(base.T, errPortRelease, fmt.Errorf("failed releasing port: %w", err)) + assert.NilError(base.T, errCertClose, fmt.Errorf("failed cleaning certs: %w", err)) + assert.NilError(base.T, errConfigClose, fmt.Errorf("failed closing config file: %w", err)) + assert.NilError(base.T, errConfigRemove, fmt.Errorf("failed removing config file: %w", err)) + } + } + + err = func() error { + // Run authentication server + cmd := base.Cmd( + "run", + "--pull=never", + "-d", + "-p", fmt.Sprintf("%s:%d:5100", listenIP, port), + "--name", containerName, + "-v", cert.CertPath+":/auth/domain.crt", + "-v", cert.KeyPath+":/auth/domain.key", + "-v", configFileName+":/config/auth_config.yml", + testutil.DockerAuthImage, + "/config/auth_config.yml").Run() + if cmd.Error != nil { + base.T.Logf("%s:\n%s\n%s\n-------\n%s", containerName, cmd.Cmd, cmd.Stdout(), cmd.Stderr()) + return cmd.Error + } + joined := net.JoinHostPort(hostIP.String(), strconv.Itoa(port)) + _, err = nettestutil.HTTPGet(fmt.Sprintf("%s://%s/auth", scheme, joined), 30, true) + return err + }() + + if err != nil { + cl := base.Cmd("logs", containerName).Run() + base.T.Logf("%s:\n%s\n%s\n=========================\n%s", containerName, cl.Cmd, cl.Stdout(), cl.Stderr()) + cleanup(err) + } + assert.NilError(base.T, err, fmt.Errorf("failed starting auth container in a timely manner: %w", err)) + + return &TokenAuthServer{ + IP: hostIP, + Port: port, + Scheme: scheme, + ListenIP: listenIP, + CertPath: cert.CertPath, + Auth: &TokenAuth{ + Address: scheme + "://" + net.JoinHostPort(hostIP.String(), strconv.Itoa(port)), + CertPath: cert.CertPath, + }, + Cleanup: cleanup, + Logs: func() { + base.T.Logf("%s: %q", containerName, base.Cmd("logs", containerName).Run().String()) + }, + } + +} + +// Auth is an interface to pass to the test registry for configuring authentication +type Auth interface { + Params(*testutil.Base) []string +} + +type NoAuth struct { +} + +func (na *NoAuth) Params(base *testutil.Base) []string { + return []string{} +} + +type TokenAuth struct { + Address string + CertPath string +} + +func (ta *TokenAuth) Params(base *testutil.Base) []string { + return []string{ "--env", "REGISTRY_AUTH=token", - "--env", "REGISTRY_AUTH_TOKEN_REALM="+fmt.Sprintf("https://%s:%d/auth", hostIP.String(), authPort), + "--env", "REGISTRY_AUTH_TOKEN_REALM=" + ta.Address + "/auth", "--env", "REGISTRY_AUTH_TOKEN_SERVICE=Docker registry", "--env", "REGISTRY_AUTH_TOKEN_ISSUER=Acme auth server", "--env", "REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE=/auth/domain.crt", - "--env", "REGISTRY_HTTP_TLS_CERTIFICATE=/registry/domain.crt", - "--env", "REGISTRY_HTTP_TLS_KEY=/registry/domain.key", - // rootcertbundle is not CA cert: https://github.com/distribution/distribution/issues/1143 - "-v", authCert.CertPath+":/auth/domain.crt", - "-v", registryCert.CertPath+":/registry/domain.crt", - "-v", registryCert.KeyPath+":/registry/domain.key", - testutil.RegistryImage) - cmd.AssertOK() - joined := net.JoinHostPort(hostIP.String(), strconv.Itoa(listenPort)) - if _, err = nettestutil.HTTPGet(fmt.Sprintf("https://%s/v2", joined), 30, true); err != nil { - base.Cmd("rm", "-f", registryContainerName).Run() - base.T.Fatal(err) + "-v", ta.CertPath + ":/auth/domain.crt", } - hostsDir, err := os.MkdirTemp(base.T.TempDir(), "certs.d") - assert.NilError(base.T, err) - hostsSubDir := filepath.Join(hostsDir, joined) - err = os.MkdirAll(hostsSubDir, 0700) - assert.NilError(base.T, err) - hostsTOMLPath := filepath.Join(hostsSubDir, "hosts.toml") - // See https://github.com/containerd/containerd/blob/main/docs/hosts.md - hostsTOML := fmt.Sprintf(` -server = "https://%s" -[host."https://%s"] - ca = %q - `, joined, joined, ca.CertPath) - base.T.Logf("Writing %q: %q", hostsTOMLPath, hostsTOML) - err = os.WriteFile(hostsTOMLPath, []byte(hostsTOML), 0700) - assert.NilError(base.T, err) - return &TestRegistry{ - IP: hostIP, - ListenIP: listenIP, - ListenPort: listenPort, - HostsDir: hostsDir, - Cleanup: func() { - base.Cmd("rm", "-f", registryContainerName).AssertOK() - base.Cmd("rm", "-f", authContainerName).AssertOK() - assert.NilError(base.T, registryCert.Close()) - assert.NilError(base.T, authCert.Close()) - assert.NilError(base.T, authConfigFile.Close()) - os.Remove(authConfigFileName) - }, +} + +type BasicAuth struct { + Realm string + HtFile string + Username string + Password string +} + +func (ba *BasicAuth) Params(base *testutil.Base) []string { + if ba.Realm == "" { + ba.Realm = "Basic Realm" + } + if ba.HtFile == "" && ba.Username != "" && ba.Password != "" { + pass := ba.Password + encryptedPass, _ := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) + tmpDir, _ := os.MkdirTemp(base.T.TempDir(), "htpasswd") + ba.HtFile = filepath.Join(tmpDir, "htpasswd") + _ = os.WriteFile(ba.HtFile, []byte(fmt.Sprintf(`%s:%s`, ba.Username, string(encryptedPass[:]))), 0600) + } + ret := []string{ + "--env", "REGISTRY_AUTH=htpasswd", + "--env", "REGISTRY_AUTH_HTPASSWD_REALM=" + ba.Realm, + "--env", "REGISTRY_AUTH_HTPASSWD_PATH=/htpasswd", + } + if ba.HtFile != "" { + ret = append(ret, "-v", ba.HtFile+":/htpasswd") + } + return ret +} + +func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundCleanup func(error)) *RegistryServer { + name := testutil.Identifier(base.T) + // listen on 0.0.0.0 to enable 127.0.0.1 + listenIP := net.ParseIP("0.0.0.0") + hostIP, err := nettestutil.NonLoopbackIPv4() + assert.NilError(base.T, err, fmt.Errorf("failed finding ipv4 non loopback interface: %w", err)) + port, err = portlock.Acquire(port) + assert.NilError(base.T, err, fmt.Errorf("failed acquiring port: %w", err)) + + containerName := fmt.Sprintf("registry-%s-%d", name, port) + args := []string{ + "run", + "--pull=never", + "-d", + "-p", fmt.Sprintf("%s:%d:5000", listenIP, port), + "--name", containerName, + } + scheme := "http" + var cert *testca.Cert + if ca != nil { + scheme = "https" + cert = ca.NewCert(hostIP.String(), "127.0.0.1") + args = append(args, + "--env", "REGISTRY_HTTP_TLS_CERTIFICATE=/registry/domain.crt", + "--env", "REGISTRY_HTTP_TLS_KEY=/registry/domain.key", + "-v", cert.CertPath+":/registry/domain.crt", + "-v", cert.KeyPath+":/registry/domain.key", + ) + } + + args = append(args, auth.Params(base)...) + args = append(args, testutil.RegistryImage) + + cleanup := func(err error) { + result := base.Cmd("rm", "-f", containerName).Run() + errPortRelease := portlock.Release(port) + var errCertClose error + if cert != nil { + errCertClose = cert.Close() + } + if boundCleanup != nil { + boundCleanup(err) + } + if cert != nil && err == nil { + assert.NilError(base.T, errCertClose, fmt.Errorf("failed cleaning certificates: %w", err)) + } + if err == nil { + assert.NilError(base.T, result.Error, fmt.Errorf("failed removing container: %w", err)) + assert.NilError(base.T, errPortRelease, fmt.Errorf("failed releasing port: %w", err)) + } + } + + hostsDir, err := func() (string, error) { + hDir, err := os.MkdirTemp(base.T.TempDir(), "certs.d") + if err != nil { + return "", err + } + + if ca != nil { + err = generateCertsd(hDir, ca.CertPath, hostIP.String(), port) + if err != nil { + return "", err + } + err = generateCertsd(hDir, ca.CertPath, "127.0.0.1", port) + if err != nil { + return "", err + } + if port == 443 { + err = generateCertsd(hDir, ca.CertPath, hostIP.String(), 0) + if err != nil { + return "", err + } + err = generateCertsd(hDir, ca.CertPath, "127.0.0.1", 0) + if err != nil { + return "", err + } + } + } + + cmd := base.Cmd(args...).Run() + if cmd.Error != nil { + base.T.Logf("%s:\n%s\n%s\n-------\n%s", containerName, cmd.Cmd, cmd.Stdout(), cmd.Stderr()) + return "", cmd.Error + } + + if _, err = nettestutil.HTTPGet(fmt.Sprintf("%s://%s:%s/v2", scheme, hostIP.String(), strconv.Itoa(port)), 30, true); err != nil { + return "", err + } + + return hDir, nil + }() + + if err != nil { + // cs := base.Cmd("inspect", containerName).Run() + // base.T.Logf("%s:\n%s\n%s\n=========================\n%s", containerName, cs.Cmd, cs.Stdout(), cs.Stderr()) + cl := base.Cmd("logs", containerName).Run() + base.T.Logf("%s:\n%s\n%s\n=========================\n%s", containerName, cl.Cmd, cl.Stdout(), cl.Stderr()) + cleanup(err) + } + assert.NilError(base.T, err, fmt.Errorf("failed starting registry container in a timely manner: %w", err)) + + return &RegistryServer{ + IP: hostIP, + Port: port, + Scheme: scheme, + ListenIP: listenIP, + Cleanup: cleanup, Logs: func() { - base.T.Logf("%s: %q", registryContainerName, base.Cmd("logs", registryContainerName).Run().String()) - base.T.Logf("%s: %q", authContainerName, base.Cmd("logs", authContainerName).Run().String()) + base.T.Logf("%s: %q", containerName, base.Cmd("logs", containerName).Run().String()) }, + HostsDir: hostsDir, + } +} + +func NewWithTokenAuth(base *testutil.Base, user, pass string, port int, tls bool) *RegistryServer { + ca := testca.New(base.T) + as := NewAuthServer(base, ca, 0, user, pass, tls) + auth := &TokenAuth{ + Address: as.Scheme + "://" + net.JoinHostPort(as.IP.String(), strconv.Itoa(as.Port)), + CertPath: as.CertPath, + } + return NewRegistry(base, ca, port, auth, as.Cleanup) +} + +func NewWithNoAuth(base *testutil.Base, port int, tls bool) *RegistryServer { + EnsureImages(base) + + var ca *testca.CA + if tls { + ca = testca.New(base.T) + } + return NewRegistry(base, ca, port, &NoAuth{}, nil) +} + +func NewWithBasicAuth(base *testutil.Base, user, pass string, port int, tls bool) *RegistryServer { + auth := &BasicAuth{ + Username: user, + Password: pass, + } + var ca *testca.CA + if tls { + ca = testca.New(base.T) } + return NewRegistry(base, ca, port, auth, nil) } diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index e64271bca57..accc5228d72 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -687,7 +687,7 @@ func newBase(t *testing.T, ns string, ipv6Compatible bool) *Base { IPv6Compatible: ipv6Compatible, } if base.EnableIPv6 && !base.IPv6Compatible { - t.Skip("runner skips non-IPv6 complatible tests in the IPv6 environment") + t.Skip("runner skips non-IPv6 compatible tests in the IPv6 environment") } else if !base.EnableIPv6 && base.IPv6Compatible { t.Skip("runner skips IPv6 compatible tests in the non-IPv6 environment") } From 37c0cb67255f07f155684aa7801b89b1a9bae3d4 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 10 Jun 2024 23:56:50 -0700 Subject: [PATCH 0494/1066] Safer / faster convert zstd Signed-off-by: apostasie --- cmd/nerdctl/image_convert_test.go | 64 ++++++++++++++++--------------- pkg/imgutil/converter/zstd.go | 45 +++++++++++----------- 2 files changed, 56 insertions(+), 53 deletions(-) diff --git a/cmd/nerdctl/image_convert_test.go b/cmd/nerdctl/image_convert_test.go index 1f308f2bdc0..8df0b5d6e76 100644 --- a/cmd/nerdctl/image_convert_test.go +++ b/cmd/nerdctl/image_convert_test.go @@ -23,44 +23,48 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil" ) -func TestImageConvertEStargz(t *testing.T) { +func TestImageConvert(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("no windows support yet") } testutil.DockerIncompatible(t) base := testutil.NewBase(t) - convertedImage := testutil.Identifier(t) + ":esgz" - base.Cmd("rmi", convertedImage).Run() - defer base.Cmd("rmi", convertedImage).Run() + t.Parallel() + base.Cmd("pull", testutil.CommonImage).AssertOK() - base.Cmd("image", "convert", "--estargz", "--oci", - testutil.CommonImage, convertedImage).AssertOK() -} -func TestImageConvertZstd(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("no windows support yet") + testCases := []struct { + identifier string + args []string + }{ + { + "esgz", + []string{"--estargz"}, + }, + { + "zstd", + []string{"--zstd", "--zstd-compression-level", "3"}, + }, + { + "zstdchunked", + []string{"--zstdchunked", "--zstdchunked-compression-level", "3"}, + }, } - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - convertedImage := testutil.Identifier(t) + ":zstd" - base.Cmd("rmi", convertedImage).Run() - defer base.Cmd("rmi", convertedImage).Run() - base.Cmd("pull", testutil.CommonImage).AssertOK() - base.Cmd("image", "convert", "--zstd", "--oci", "--zstd-compression-level", "3", - testutil.CommonImage, convertedImage).AssertOK() -} -func TestImageConvertZstdChunked(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("no windows support yet") + for _, tc := range testCases { + convertedImage := testutil.Identifier(t) + ":" + tc.identifier + args := append([]string{"image", "convert", "--oci"}, tc.args...) + args = append(args, testutil.CommonImage, convertedImage) + + t.Run(tc.identifier, func(t *testing.T) { + t.Parallel() + + base.Cmd("rmi", convertedImage).Run() + t.Cleanup(func() { + base.Cmd("rmi", convertedImage).Run() + }) + + base.Cmd(args...).AssertOK() + }) } - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - convertedImage := testutil.Identifier(t) + ":zstdchunked" - base.Cmd("rmi", convertedImage).Run() - defer base.Cmd("rmi", convertedImage).Run() - base.Cmd("pull", testutil.CommonImage).AssertOK() - base.Cmd("image", "convert", "--zstdchunked", "--oci", "--zstdchunked-compression-level", "3", - testutil.CommonImage, convertedImage).AssertOK() } diff --git a/pkg/imgutil/converter/zstd.go b/pkg/imgutil/converter/zstd.go index aee052bc07f..6d85dabc5ed 100644 --- a/pkg/imgutil/converter/zstd.go +++ b/pkg/imgutil/converter/zstd.go @@ -21,12 +21,12 @@ import ( "fmt" "io" + "github.com/containerd/containerd/archive/compression" "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/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/klauspost/compress/zstd" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -40,34 +40,33 @@ func ZstdLayerConvertFunc(options types.ImageConvertOptions) (converter.ConvertF // No conversion. No need to return an error here. return nil, nil } - uncompressedDesc := &desc - if !uncompress.IsUncompressedType(desc.MediaType) { - var err error - uncompressedDesc, err = uncompress.LayerConvertFunc(ctx, cs, desc) - if err != nil { - return nil, err - } - if uncompressedDesc == nil { - return nil, fmt.Errorf("unexpectedly got the same blob after compression (%s, %q)", desc.Digest, desc.MediaType) - } - defer func() { - if err := cs.Delete(ctx, uncompressedDesc.Digest); err != nil { - log.L.WithError(err).WithField("uncompressedDesc", uncompressedDesc).Warn("failed to remove tmp uncompressed layer") - } - }() - log.L.Debugf("zstd: uncompressed %s into %s", desc.Digest, uncompressedDesc.Digest) + var err error + // Read it + readerAt, err := cs.ReaderAt(ctx, desc) + if err != nil { + return nil, err } + defer readerAt.Close() + sectionReader := io.NewSectionReader(readerAt, 0, desc.Size) info, err := cs.Info(ctx, desc.Digest) if err != nil { return nil, err } - readerAt, err := cs.ReaderAt(ctx, *uncompressedDesc) - if err != nil { - return nil, err + + var oldReader io.Reader + // If it is compressed, get a decompressed stream + if !uncompress.IsUncompressedType(desc.MediaType) { + decompStream, err := compression.DecompressStream(sectionReader) + if err != nil { + return nil, err + } + defer decompStream.Close() + oldReader = decompStream + } else { + oldReader = sectionReader } - defer readerAt.Close() - sr := io.NewSectionReader(readerAt, 0, uncompressedDesc.Size) + ref := fmt.Sprintf("convert-zstd-from-%s", desc.Digest) w, err := content.OpenWriter(ctx, cs, content.WithRef(ref)) if err != nil { @@ -88,7 +87,7 @@ func ZstdLayerConvertFunc(options types.ImageConvertOptions) (converter.ConvertF return nil, err } go func() { - if _, err := io.Copy(enc, sr); err != nil { + if _, err := io.Copy(enc, oldReader); err != nil { pr.CloseWithError(err) return } From 972a9b108d1c49f30b33289a44d38daf9fbed832 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Jun 2024 22:08:19 +0000 Subject: [PATCH 0495/1066] build(deps): bump github.com/containerd/platforms from 0.2.0 to 0.2.1 Bumps [github.com/containerd/platforms](https://github.com/containerd/platforms) from 0.2.0 to 0.2.1. - [Release notes](https://github.com/containerd/platforms/releases) - [Commits](https://github.com/containerd/platforms/compare/v0.2.0...v0.2.1) --- updated-dependencies: - dependency-name: github.com/containerd/platforms dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2ee403678ba..109d136355c 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/imgcrypt v1.1.11 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.13.13 - github.com/containerd/platforms v0.2.0 + github.com/containerd/platforms v0.2.1 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 github.com/containerd/stargz-snapshotter/ipfs v0.15.1 diff --git a/go.sum b/go.sum index c5bdefae7a3..dff1428bd15 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,8 @@ 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.13 h1:4eCKSNjmozLQ038G2a3X8DEwmrsHsRPMdVGX+zjcaTc= github.com/containerd/nydus-snapshotter v0.13.13/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= -github.com/containerd/platforms v0.2.0 h1:clGNvVIcY3k39VJSYdFGohI1b3bP/eeBUVR5+XA28oo= -github.com/containerd/platforms v0.2.0/go.mod h1:XOM2BS6kN6gXafPLg80V6y/QUib+xoLyC3qVmHzibko= +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= From f942d2c56bf3a9f5fe576d8f34f24cb3666eeb78 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 14 Jun 2024 08:36:47 +0900 Subject: [PATCH 0496/1066] test-integration-docker-compatibility: install Docker v24 The test suit is still not ready for Docker >= v25 (issue 3088) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b7136c58519..d6352857c12 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -251,15 +251,26 @@ jobs: go-version: ${{ env.GO_VERSION }} cache: true check-latest: true - - name: "Enable BuildKit" + # Docker >= v25 is still unsupported: https://github.com/containerd/nerdctl/issues/3088 + - 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' Date: Fri, 14 Jun 2024 02:08:08 +0000 Subject: [PATCH 0497/1066] build(deps): bump actions/checkout from 4.1.6 to 4.1.7 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.6...v4.1.7) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 22 +++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index af907e8ee28..d1e199cf2ed 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 65209734b4a..50f4bab6650 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - uses: actions/setup-go@v5 with: go-version: 1.22.x diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d6352857c12..b66314c39f7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 @@ -39,7 +39,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -59,7 +59,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -90,7 +90,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -125,7 +125,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 1 - name: Enable ipv4 and ipv6 forwarding @@ -206,7 +206,7 @@ jobs: ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" TEST_TARGET: "${{ matrix.target }}" steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -228,7 +228,7 @@ jobs: matrix: go-version: ["1.21.x", "1.22.x"] steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -243,7 +243,7 @@ jobs: runs-on: ubuntu-22.04 timeout-minutes: 45 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -301,7 +301,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -310,7 +310,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: repository: containerd/containerd ref: v1.7.17 @@ -333,7 +333,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - uses: actions/cache@v4 with: path: /root/.vagrant.d From 14d8b42a4f109a80039703a9a5b0b323a91d7d56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Jun 2024 02:09:11 +0000 Subject: [PATCH 0498/1066] build(deps): bump github.com/klauspost/compress from 1.17.8 to 1.17.9 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.8 to 1.17.9. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.8...v1.17.9) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 109d136355c..b98fd3833a3 100644 --- a/go.mod +++ b/go.mod @@ -94,7 +94,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.8 + github.com/klauspost/compress v1.17.9 github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect diff --git a/go.sum b/go.sum index dff1428bd15..be258e6fd49 100644 --- a/go.sum +++ b/go.sum @@ -172,8 +172,8 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= -github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= From 37098ac6cd3d8fbf47573c5ff86c5878146a9f6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Jun 2024 22:10:08 +0000 Subject: [PATCH 0499/1066] build(deps): bump github.com/spf13/cobra from 1.8.0 to 1.8.1 Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1. - [Release notes](https://github.com/spf13/cobra/releases) - [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1) --- updated-dependencies: - dependency-name: github.com/spf13/cobra dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index b98fd3833a3..239ca58ac60 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/pelletier/go-toml/v2 v2.2.2 github.com/rootless-containers/bypass4netns v0.4.1 github.com/rootless-containers/rootlesskit/v2 v2.1.0 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/tidwall/gjson v1.17.1 github.com/vishvananda/netlink v1.2.1-beta.2 diff --git a/go.sum b/go.sum index be258e6fd49..83c415f4b26 100644 --- a/go.sum +++ b/go.sum @@ -74,7 +74,7 @@ github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsa github.com/coreos/go-iptables v0.7.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= @@ -269,8 +269,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 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-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw= From f4a7e0c8bc859566d5a1eb9c1616ddabd9d5f928 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 15 Jun 2024 18:22:49 -0700 Subject: [PATCH 0500/1066] Restore logger output Signed-off-by: apostasie --- pkg/ocihook/ocihook.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 55a8b58c916..4ab13a7ce78 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -80,8 +80,15 @@ func Run(stdin io.Reader, stderr io.Writer, event, dataStore, cniPath, cniNetcon if err != nil { return err } - defer logFile.Close() + currentOutput := log.L.Logger.Out log.L.Logger.SetOutput(io.MultiWriter(stderr, logFile)) + defer func() { + log.L.Logger.SetOutput(currentOutput) + err = logFile.Close() + if err != nil { + log.L.Logger.WithError(err).Error("failed closing oci hook log file") + } + }() opts, err := newHandlerOpts(&state, dataStore, cniPath, cniNetconfPath) if err != nil { From a3195b27b7cb2de33fa87a2916f969d60694d400 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 6 Jun 2024 13:58:45 +0900 Subject: [PATCH 0501/1066] MAINTAINERS: promote Kay Yan (yankay) from a REVIEWER to a COMMITTER Signed-off-by: Akihiro Suda --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5371bc343d7..bd30678e582 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17,12 +17,12 @@ "Zheaoli", "Zheao Li", "me@manjusaka.me","6E0D D9FA BAD5 AF61 D884 01EE 878F 445D 9C6C E65E" "junnplus","Ye Sijun","junnplus@gmail.com","" "djdongjin", "Jin Dong", "djdongjin95@gmail.com","" +"yankay", "Kay Yan", "kay.yan@daocloud.io", "" # REVIEWERS # GitHub ID, Name, Email address, GPG fingerprint "jsturtevant","James Sturtevant","jstur@microsoft.com","" "manugupt1", "Manu Gupta", "manugupt1@gmail.com","FCA9 504A 4118 EA5C F466 CC30 A5C3 A8F4 E7FE 9E10" -"yankay", "Kay Yan", "kay.yan@daocloud.io", "" # EMERITUS # See EMERITUS.md From 091de7469fecd134a937f6192481803e62c5bc5d Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Mon, 17 Jun 2024 02:54:01 +0000 Subject: [PATCH 0502/1066] update containerd (1.7.18), runc (1.1.13) Signed-off-by: Kay Yan --- .github/workflows/test.yml | 24 ++++++++++++------------ Dockerfile | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b66314c39f7..a21af90b0ae 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,11 +79,11 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.32 + containerd: v1.6.33 - ubuntu: 20.04 - containerd: v1.7.17 + containerd: v1.7.18 - ubuntu: 22.04 - containerd: v1.7.17 + containerd: v1.7.18 - ubuntu: 22.04 containerd: main env: @@ -120,7 +120,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 22.04 - containerd: v1.7.17 + containerd: v1.7.18 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -169,15 +169,15 @@ jobs: # ubuntu-22.04: cgroup v1, ubuntu-22.04: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.32 + containerd: v1.6.33 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.17 + containerd: v1.7.18 rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.17 + containerd: v1.7.18 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 @@ -185,15 +185,15 @@ jobs: rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.6.32 + containerd: v1.6.33 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.17 + containerd: v1.7.18 rootlesskit: v2.1.0 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: v1.7.17 + containerd: v1.7.18 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 @@ -313,7 +313,7 @@ jobs: - uses: actions/checkout@v4.1.7 with: repository: containerd/containerd - ref: v1.7.17 + ref: v1.7.18 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -321,7 +321,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.17 + ctrdVersion: 1.7.18 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/Dockerfile b/Dockerfile index 3d68323aafd..d0a9a16536c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,8 +18,8 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.17 -ARG RUNC_VERSION=v1.1.12 +ARG CONTAINERD_VERSION=v1.7.18 +ARG RUNC_VERSION=v1.1.13 ARG CNI_PLUGINS_VERSION=v1.5.0 # Extra deps: Build From b63f4d6bfb243aa37d429eea216131ec3d8b9093 Mon Sep 17 00:00:00 2001 From: David Son Date: Fri, 7 Jun 2024 21:33:50 +0000 Subject: [PATCH 0503/1066] Add --pull option to build command Signed-off-by: David Son --- cmd/nerdctl/builder_build.go | 10 ++++ cmd/nerdctl/builder_linux_test.go | 90 +++++++++++++++++++++++++++++++ docs/command-reference.md | 1 + pkg/api/types/builder_types.go | 2 + pkg/cmd/builder/build.go | 9 ++++ 5 files changed, 112 insertions(+) diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index 47cc31f7ff1..0fa319a1eb6 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -51,6 +51,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container buildCommand.Flags().StringP("output", "o", "", "Output destination (format: type=local,dest=path)") buildCommand.Flags().String("progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output") buildCommand.Flags().String("provenance", "", "Shorthand for \"--attest=type=provenance\"") + buildCommand.Flags().Bool("pull", false, "On true, always attempt to pull latest image version from remote. Default uses buildkit's default.") buildCommand.Flags().StringArray("secret", nil, "Secret file to expose to the build: id=mysecret,src=/local/secret") buildCommand.Flags().StringArray("allow", nil, "Allow extra privileged entitlement, e.g. network.host, security.insecure") buildCommand.RegisterFlagCompletionFunc("allow", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -133,6 +134,14 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu if err != nil { return types.BuilderBuildOptions{}, err } + var pull *bool + if cmd.Flags().Changed("pull") { + pullFlag, err := cmd.Flags().GetBool("pull") + if err != nil { + return types.BuilderBuildOptions{}, err + } + pull = &pullFlag + } secret, err := cmd.Flags().GetStringArray("secret") if err != nil { return types.BuilderBuildOptions{}, err @@ -205,6 +214,7 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu BuildArgs: buildArgs, Label: label, NoCache: noCache, + Pull: pull, Secret: secret, Allow: allow, Attest: attest, diff --git a/cmd/nerdctl/builder_linux_test.go b/cmd/nerdctl/builder_linux_test.go index 717e83ac1cf..ef86ede7047 100644 --- a/cmd/nerdctl/builder_linux_test.go +++ b/cmd/nerdctl/builder_linux_test.go @@ -19,9 +19,13 @@ package main import ( "bytes" "fmt" + "os" + "os/exec" + "path/filepath" "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "gotest.tools/v3/assert" ) func TestBuilderDebug(t *testing.T) { @@ -36,3 +40,89 @@ CMD ["echo", "nerdctl-builder-debug-test-string"] base.Cmd("builder", "debug", buildCtx).CmdOption(testutil.WithStdin(bytes.NewReader([]byte("c\n")))).AssertOK() } + +func TestBuildWithPull(t *testing.T) { + testutil.DockerIncompatible(t) + testutil.RequiresBuild(t) + + oldImage := testutil.BusyboxImage + oldImageSha := "141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47" + newImage := testutil.AlpineImage + + buildkitConfig := fmt.Sprintf(`[worker.oci] +enabled = false + +[worker.containerd] +enabled = true +namespace = "%s"`, testutil.Namespace) + + cleanup := useBuildkitConfig(t, buildkitConfig) + defer cleanup() + + testCases := []struct { + name string + pull string + }{ + { + name: "build with local image", + pull: "false", + }, + { + name: "build with newest image", + pull: "true", + }, + { + name: "build with buildkit default", + // buildkit default pulls from remote + pull: "default", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + base := testutil.NewBase(t) + defer base.Cmd("builder", "prune").AssertOK() + base.Cmd("image", "prune", "--force", "--all").AssertOK() + + base.Cmd("pull", oldImage).Run() + base.Cmd("tag", oldImage, newImage).Run() + + dockerfile := fmt.Sprintf(`FROM %s`, newImage) + tmpDir := t.TempDir() + err := os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644) + assert.NilError(t, err) + + buildCtx := createBuildContext(t, dockerfile) + + buildCmd := []string{"build", buildCtx} + switch tc.pull { + case "false": + buildCmd = append(buildCmd, "--pull=false") + base.Cmd(buildCmd...).AssertErrContains(oldImageSha) + case "true": + buildCmd = append(buildCmd, "--pull=true") + base.Cmd(buildCmd...).AssertErrNotContains(oldImageSha) + case "default": + base.Cmd(buildCmd...).AssertErrNotContains(oldImageSha) + } + }) + } +} + +func useBuildkitConfig(t *testing.T, config string) (cleanup func()) { + buildkitConfigPath := "/etc/buildkit/buildkitd.toml" + + currConfig, err := exec.Command("cat", buildkitConfigPath).Output() + assert.NilError(t, err) + + os.WriteFile(buildkitConfigPath, []byte(config), 0644) + _, err = exec.Command("systemctl", "restart", "buildkit").Output() + assert.NilError(t, err) + + return func() { + assert.NilError(t, os.WriteFile(buildkitConfigPath, currConfig, 0644)) + _, err = exec.Command("systemctl", "restart", "buildkit").Output() + assert.NilError(t, err) + } +} diff --git a/docs/command-reference.md b/docs/command-reference.md index da1d416e544..4da9b342eb8 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -692,6 +692,7 @@ Flags: - :whale: `type=image,name=example.com/image,push=true`: Push to a registry (see [`buildctl build`](https://github.com/moby/buildkit/tree/v0.9.0#imageregistry) documentation) - :whale: `--progress=(auto|plain|tty)`: Set type of progress output (auto, plain, tty). Use plain to show container output - :whale: `--provenance`: Shorthand for \"--attest=type=provenance\", see [`buildx_build.md`](https://github.com/docker/buildx/blob/v0.12.1/docs/reference/buildx_build.md#provenance) documentation +- :whale: `--pull=(true|false)`: On true, always attempt to pull latest image version from remote. Default uses buildkit's default. - :whale: `--secret`: Secret file to expose to the build: id=mysecret,src=/local/secret - :whale: `--allow`: Allow extra privileged entitlement, e.g. network.host, security.insecure (It’s required to configure the buildkitd to enable the feature, see [`buildkitd.toml`](https://github.com/moby/buildkit/blob/master/docs/buildkitd.toml.md) documentation) - :whale: `--attest`: Attestation parameters (format: "type=sbom,generator=image"), see [`buildx_build.md`](https://github.com/docker/buildx/blob/v0.12.1/docs/reference/buildx_build.md#attest) documentation diff --git a/pkg/api/types/builder_types.go b/pkg/api/types/builder_types.go index 7a0dd4cb885..fd8f7d87ca9 100644 --- a/pkg/api/types/builder_types.go +++ b/pkg/api/types/builder_types.go @@ -69,6 +69,8 @@ type BuilderBuildOptions struct { ExtendedBuildContext []string // NetworkMode mode for the build context NetworkMode string + // Pull determines if we should try to pull latest image from remote. Default is buildkit's default. + Pull *bool } // BuilderPruneOptions specifies options for `nerdctl builder prune`. diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index fe544ac4a39..070779a0b2e 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -367,6 +367,15 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option buildctlArgs = append(buildctlArgs, "--no-cache") } + if options.Pull != nil { + switch *options.Pull { + case true: + buildctlArgs = append(buildctlArgs, "--opt=image-resolve-mode=pull") + case false: + buildctlArgs = append(buildctlArgs, "--opt=image-resolve-mode=local") + } + } + for _, s := range strutil.DedupeStrSlice(options.Secret) { buildctlArgs = append(buildctlArgs, "--secret="+s) } From e789f2cda863cda6d0ed1e76d182671570bfe3da Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 16 Jun 2024 16:53:37 -0700 Subject: [PATCH 0504/1066] Docker v26 compatibility & test fixes Signed-off-by: apostasie --- .github/workflows/test.yml | 11 +-- cmd/nerdctl/container_create_linux_test.go | 91 +++++++++++------- .../container_run_network_linux_test.go | 96 ++++++++++++------- cmd/nerdctl/network_inspect_test.go | 2 +- .../container_network_manager.go | 10 +- 5 files changed, 127 insertions(+), 83 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b66314c39f7..36e866aac0b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -251,8 +251,7 @@ jobs: go-version: ${{ env.GO_VERSION }} cache: true check-latest: true - # Docker >= v25 is still unsupported: https://github.com/containerd/nerdctl/issues/3088 - - name: "Install Docker v24" + - name: "Install Docker v26" run: | set -eux -o pipefail # Uninstall the preinstalled Docker @@ -264,10 +263,10 @@ jobs: cat /etc/docker/daemon.json # Download Docker packages curl -OSL https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/containerd.io_1.6.33-1_amd64.deb - curl -OSL https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/docker-ce_24.0.9-1~ubuntu.22.04~jammy_amd64.deb - curl -OSL https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/docker-ce-cli_24.0.9-1~ubuntu.22.04~jammy_amd64.deb - curl -OSL https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/docker-buildx-plugin_0.13.1-1~ubuntu.22.04~jammy_amd64.deb - curl -OSL https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/docker-compose-plugin_2.25.0-1~ubuntu.22.04~jammy_amd64.deb + curl -OSL https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/docker-ce_26.1.4-1~ubuntu.22.04~jammy_amd64.deb + curl -OSl https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/docker-ce-cli_26.1.4-1~ubuntu.22.04~jammy_amd64.deb + curl -OSL https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/docker-buildx-plugin_0.14.1-1~ubuntu.22.04~jammy_amd64.deb + curl -OSL https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/docker-compose-plugin_2.27.1-1~ubuntu.22.04~jammy_amd64.deb # Install Docker sudo apt-get install -y ./*.deb rm -f ./*.deb diff --git a/cmd/nerdctl/container_create_linux_test.go b/cmd/nerdctl/container_create_linux_test.go index ba70bda420b..960a2ff3222 100644 --- a/cmd/nerdctl/container_create_linux_test.go +++ b/cmd/nerdctl/container_create_linux_test.go @@ -19,6 +19,7 @@ package main import ( "fmt" "runtime" + "strings" "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" @@ -57,69 +58,85 @@ func TestCreateWithMACAddress(t *testing.T) { networkBridge := "testNetworkBridge" + tID networkMACvlan := "testNetworkMACvlan" + tID networkIPvlan := "testNetworkIPvlan" + tID - base.Cmd("network", "create", networkBridge, "--driver", "bridge").AssertOK() - base.Cmd("network", "create", networkMACvlan, "--driver", "macvlan").AssertOK() - base.Cmd("network", "create", networkIPvlan, "--driver", "ipvlan").AssertOK() - t.Cleanup(func() { + + tearDown := func() { base.Cmd("network", "rm", networkBridge).Run() base.Cmd("network", "rm", networkMACvlan).Run() base.Cmd("network", "rm", networkIPvlan).Run() - }) + } + + tearDown() + t.Cleanup(tearDown) + + base.Cmd("network", "create", networkBridge, "--driver", "bridge").AssertOK() + base.Cmd("network", "create", networkMACvlan, "--driver", "macvlan").AssertOK() + base.Cmd("network", "create", networkIPvlan, "--driver", "ipvlan").AssertOK() + + defaultMac := base.Cmd("run", "--rm", "-i", "--network", "host", testutil.CommonImage). + CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))). + Run().Stdout() + + passedMac := "we expect the generated mac on the output" tests := []struct { Network string WantErr bool Expect string }{ - {"host", true, "conflicting options"}, - {"none", true, "can't open '/sys/class/net/eth0/address'"}, - {"container:whatever" + tID, true, "conflicting options"}, - {"bridge", false, ""}, - {networkBridge, false, ""}, - {networkMACvlan, false, ""}, + {"host", false, defaultMac}, // anything but the actual address being passed + {"none", false, ""}, + {"container:whatever" + tID, true, "container"}, // "No such container" vs. "could not find container" + {"bridge", false, passedMac}, + {networkBridge, false, passedMac}, + {networkMACvlan, false, passedMac}, {networkIPvlan, true, "not support"}, } for i, test := range tests { containerName := fmt.Sprintf("%s_%d", tID, i) testName := fmt.Sprintf("%s_container:%s_network:%s_expect:%s", tID, containerName, test.Network, test.Expect) + expect := test.Expect + network := test.Network + wantErr := test.WantErr t.Run(testName, func(tt *testing.T) { + tt.Parallel() + macAddress, err := nettestutil.GenerateMACAddress() if err != nil { tt.Errorf("failed to generate MAC address: %s", err) } - if test.Expect == "" && !test.WantErr { - test.Expect = macAddress + if expect == passedMac { + expect = macAddress } tt.Cleanup(func() { base.Cmd("rm", "-f", containerName).Run() }) - cmd := base.Cmd("create", "--network", test.Network, "--mac-address", macAddress, "--name", containerName, testutil.CommonImage, "cat", "/sys/class/net/eth0/address") - if !test.WantErr { - cmd.AssertOK() + // This is currently blocked by https://github.com/containerd/nerdctl/pull/3104 + // res := base.Cmd("create", "-i", "--network", network, "--mac-address", macAddress, testutil.CommonImage).Run() + res := base.Cmd("create", "--network", network, "--name", containerName, + "--mac-address", macAddress, testutil.CommonImage, + "sh", "-c", "--", "ip addr show eth0 | grep ether").Run() + + if !wantErr { + assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res.Combined()) + // This is currently blocked by: https://github.com/containerd/nerdctl/pull/3104 + // res = base.Cmd("start", "-i", containerName). + // CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))).Run() base.Cmd("start", containerName).AssertOK() - cmd = base.Cmd("logs", containerName) - cmd.AssertOK() - cmd.AssertOutContains(test.Expect) + res = base.Cmd("logs", containerName).Run() + assert.Assert(t, strings.Contains(res.Stdout(), expect), fmt.Sprintf("expected output to contain %q: %q", expect, res.Stdout())) + assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res.Combined()) } else { - if (testutil.GetTarget() == testutil.Docker && test.Network == networkIPvlan) || test.Network == "none" { - // 1. unlike nerdctl - // when using network ipvlan in Docker + if testutil.GetTarget() == testutil.Docker && + (network == networkIPvlan || network == "container:whatever"+tID) { + // unlike nerdctl + // when using network ipvlan or container in Docker // it delays fail on executing start command - // 2. start on network none will success in both - // nerdctl and Docker - cmd.AssertOK() - cmd = base.Cmd("start", containerName) - if test.Network == "none" { - // we check the result on logs command - cmd.AssertOK() - cmd = base.Cmd("logs", containerName) - } - } - cmd.AssertCombinedOutContains(test.Expect) - if test.Network == "none" { - cmd.AssertOK() - } else { - cmd.AssertFail() + assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res.Combined()) + res = base.Cmd("start", "-i", containerName). + CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))).Run() } + + assert.Assert(t, strings.Contains(res.Combined(), expect), fmt.Sprintf("expected output to contain %q: %q", expect, res.Combined())) + assert.Assert(t, res.ExitCode != 0, "Command should have failed", res.Combined()) } }) } diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index 58349cba619..0f6f8990371 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -354,12 +354,17 @@ 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 + // docker 24 silently ignored the ip - now, docker 26 is erroring out - furthermore, this ip only makes sense + // in the context of nerdctl bridge network, so, this test needs rewritting either way + /* + { + ip: "10.4.0.2", + shouldSuccess: true, + useNetwork: false, + checkTheIPAddress: false, + }, + */ } tID := testutil.Identifier(t) for i, tc := range testCases { @@ -453,43 +458,68 @@ func TestRunContainerWithMACAddress(t *testing.T) { networkBridge := "testNetworkBridge" + tID networkMACvlan := "testNetworkMACvlan" + tID networkIPvlan := "testNetworkIPvlan" + tID - base.Cmd("network", "create", networkBridge, "--driver", "bridge").AssertOK() - base.Cmd("network", "create", networkMACvlan, "--driver", "macvlan").AssertOK() - base.Cmd("network", "create", networkIPvlan, "--driver", "ipvlan").AssertOK() - t.Cleanup(func() { + tearDown := func() { base.Cmd("network", "rm", networkBridge).Run() base.Cmd("network", "rm", networkMACvlan).Run() base.Cmd("network", "rm", networkIPvlan).Run() - }) + } + + tearDown() + t.Cleanup(tearDown) + + base.Cmd("network", "create", networkBridge, "--driver", "bridge").AssertOK() + base.Cmd("network", "create", networkMACvlan, "--driver", "macvlan").AssertOK() + base.Cmd("network", "create", networkIPvlan, "--driver", "ipvlan").AssertOK() + + defaultMac := base.Cmd("run", "--rm", "-i", "--network", "host", testutil.CommonImage). + CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))). + Run().Stdout() + + passedMac := "we expect the generated mac on the output" + tests := []struct { Network string WantErr bool Expect string }{ - {"host", true, "conflicting options"}, - {"none", true, "can't open '/sys/class/net/eth0/address'"}, - {"container:whatever" + tID, true, "conflicting options"}, - {"bridge", false, ""}, - {networkBridge, false, ""}, - {networkMACvlan, false, ""}, + {"host", false, defaultMac}, // anything but the actual address being passed + {"none", false, ""}, // nothing + {"container:whatever" + tID, true, "container"}, // "No such container" vs. "could not find container" + {"bridge", false, passedMac}, + {networkBridge, false, passedMac}, + {networkMACvlan, false, passedMac}, {networkIPvlan, true, "not support"}, } - for _, test := range tests { - macAddress, err := nettestutil.GenerateMACAddress() - if err != nil { - t.Errorf("failed to generate MAC address: %s", err) - } - if test.Expect == "" && !test.WantErr { - test.Expect = macAddress - } - cmd := base.Cmd("run", "--rm", "--network", test.Network, "--mac-address", macAddress, testutil.CommonImage, "cat", "/sys/class/net/eth0/address") - if test.WantErr { - cmd.AssertFail() - cmd.AssertCombinedOutContains(test.Expect) - } else { - cmd.AssertOK() - cmd.AssertOutContains(test.Expect) - } + + for i, test := range tests { + containerName := fmt.Sprintf("%s_%d", tID, i) + testName := fmt.Sprintf("%s_container:%s_network:%s_expect:%s", tID, containerName, test.Network, test.Expect) + expect := test.Expect + network := test.Network + wantErr := test.WantErr + t.Run(testName, func(tt *testing.T) { + tt.Parallel() + + macAddress, err := nettestutil.GenerateMACAddress() + if err != nil { + t.Errorf("failed to generate MAC address: %s", err) + } + if expect == passedMac { + expect = macAddress + } + + res := base.Cmd("run", "--rm", "-i", "--network", network, "--mac-address", macAddress, testutil.CommonImage). + CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))).Run() + + if wantErr { + assert.Assert(t, res.ExitCode != 0, "Command should have failed", res.Combined()) + assert.Assert(t, strings.Contains(res.Combined(), expect), fmt.Sprintf("expected output to contain %q: %q", expect, res.Combined())) + } else { + assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res.Combined()) + assert.Assert(t, strings.Contains(res.Stdout(), expect), fmt.Sprintf("expected output to contain %q: %q", expect, res.Stdout())) + } + }) + } } diff --git a/cmd/nerdctl/network_inspect_test.go b/cmd/nerdctl/network_inspect_test.go index 5a43cab1ceb..bab22c998eb 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/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 1f746c2d4bb..f6db2e78d55 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -200,9 +200,9 @@ func (m *containerNetworkManager) VerifyNetworkOptions(_ context.Context) error return errors.New("conflicting options: only one network specification is allowed when using '--network=container:'") } + // Note that mac-address is accepted, though it is a no-op nonZeroParams := nonZeroMapValues(map[string]interface{}{ - "--hostname": m.netOpts.Hostname, - "--mac-address": m.netOpts.MACAddress, + "--hostname": m.netOpts.Hostname, // NOTE: an empty slice still counts as a non-zero value so we check its length: "-p/--publish": len(m.netOpts.PortMappings) != 0, "--dns": len(m.netOpts.DNSServers) != 0, @@ -286,6 +286,8 @@ func (m *containerNetworkManager) InternalNetworkingOptionLabels(ctx context.Con if m.netOpts.NetworkSlice == nil || len(m.netOpts.NetworkSlice) != 1 { return opts, fmt.Errorf("conflicting options: exactly one network specification is allowed when using '--network=container:'") } + // MacAddress is not allowed with container networking + opts.MACAddress = "" container, err := m.getNetworkingContainerForArgument(ctx, m.netOpts.NetworkSlice[0], m.client) if err != nil { @@ -357,10 +359,6 @@ func (m *hostNetworkManager) VerifyNetworkOptions(_ context.Context) error { return errors.New("cannot use host networking on Windows") } - if m.netOpts.MACAddress != "" { - return errors.New("conflicting options: mac-address and the network mode") - } - return validateUtsSettings(m.netOpts) } From eace9da19f84f94f0f282c804d5f85c33d8f17dc Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 17 Jun 2024 15:08:30 -0700 Subject: [PATCH 0505/1066] Add doc note about --ip and bridge Signed-off-by: apostasie --- docs/command-reference.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/command-reference.md b/docs/command-reference.md index da1d416e544..d44d903e80c 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -183,7 +183,7 @@ Network flags: - :whale: `-h, --hostname`: Container host name - :whale: `--add-host`: Add a custom host-to-IP mapping (host:ip). `ip` could be a special string `host-gateway`, - which will be resolved to the `host-gateway-ip` in nerdctl.toml or global flag. -- :whale: `--ip`: Specific static IP address(es) to use +- :whale: `--ip`: Specific static IP address(es) to use. Note that unlike docker, nerdctl allows specifying it with the default bridge network. - :whale: `--ip6`: Specific static IP6 address(es) to use. Should be used with user networks - :whale: `--mac-address`: Specific MAC address to use. Be aware that it does not check if manually specified MAC addresses are unique. Supports network @@ -388,7 +388,7 @@ IPFS flags: Unimplemented `docker run` flags: `--attach`, `--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*`, `--publish-all`, `--sig-proxy`, `--storage-opt`, `--userns`, `--volume-driver` ### :whale: :blue_square: nerdctl exec From 9a76ba10c816a9a3063cfaa74d2929e647d8137b Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 17 Jun 2024 15:16:47 -0700 Subject: [PATCH 0506/1066] Disable build and publish on PR for purely md changes Signed-off-by: apostasie --- .github/workflows/ghcr-image-build-and-publish.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index d1e199cf2ed..cf943129ce8 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -12,6 +12,8 @@ on: tags: ['v*.*.*'] pull_request: branches: [main] + paths-ignore: + - '**.md' env: # Use docker.io for Docker Hub if empty From 0b201417b712fd441ef929a6cb27385caab62e7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 22:26:38 +0000 Subject: [PATCH 0507/1066] build(deps): bump github.com/containernetworking/plugins Bumps [github.com/containernetworking/plugins](https://github.com/containernetworking/plugins) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/containernetworking/plugins/releases) - [Commits](https://github.com/containernetworking/plugins/compare/v1.5.0...v1.5.1) --- updated-dependencies: - dependency-name: github.com/containernetworking/plugins dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 239ca58ac60..9a32a2a0fee 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/containerd/stargz-snapshotter/ipfs v0.15.1 github.com/containerd/typeurl/v2 v2.1.1 github.com/containernetworking/cni v1.2.0 - github.com/containernetworking/plugins v1.5.0 + github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 diff --git a/go.sum b/go.sum index 83c415f4b26..b14aa06d8b6 100644 --- a/go.sum +++ b/go.sum @@ -66,8 +66,8 @@ github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9Fqctt github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= github.com/containernetworking/cni v1.2.0 h1:fEjhlfWwWAXEvlcMQu/i6z8DA0Kbu7EcmR5+zb6cm5I= github.com/containernetworking/cni v1.2.0/go.mod h1:/r+vA/7vrynNfbvSP9g8tIKEoy6win7sALJAw4ZiJks= -github.com/containernetworking/plugins v1.5.0 h1:P09DMlfvvsLSskDoftnuwXY7lwa7IAhTGznZxA5E8fk= -github.com/containernetworking/plugins v1.5.0/go.mod h1:bcXMvG9gWGc6jVXeodmMzuXmXqpqMguZm6Zu/oIr7AA= +github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= +github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= 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= @@ -231,8 +231,8 @@ github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/onsi/ginkgo/v2 v2.17.3 h1:oJcvKpIb7/8uLpDDtnQuf18xVnwKp8DTD7DQ6gTd/MU= -github.com/onsi/ginkgo/v2 v2.17.3/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= From 34d7c3108f2e75a250476d0b9adf13d0068a425c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 22:50:48 +0000 Subject: [PATCH 0508/1066] build(deps): bump docker/build-push-action from 5.4.0 to 6.0.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5.4.0 to 6.0.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v5.4.0...v6.0.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index d1e199cf2ed..bcd2766d3b6 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -59,7 +59,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v5.4.0 + uses: docker/build-push-action@v6.0.0 with: context: . platforms: linux/amd64,linux/arm64 From 2606265d9cc35cddebb5341635f0f3f16a18adaa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 23:30:14 +0000 Subject: [PATCH 0509/1066] build(deps): bump github.com/containernetworking/cni from 1.2.0 to 1.2.1 Bumps [github.com/containernetworking/cni](https://github.com/containernetworking/cni) from 1.2.0 to 1.2.1. - [Release notes](https://github.com/containernetworking/cni/releases) - [Commits](https://github.com/containernetworking/cni/compare/v1.2.0...v1.2.1) --- updated-dependencies: - dependency-name: github.com/containernetworking/cni dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 9a32a2a0fee..9d208acfa13 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/containerd/stargz-snapshotter/estargz v0.15.1 github.com/containerd/stargz-snapshotter/ipfs v0.15.1 github.com/containerd/typeurl/v2 v2.1.1 - github.com/containernetworking/cni v1.2.0 + github.com/containernetworking/cni v1.2.1 github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 diff --git a/go.sum b/go.sum index b14aa06d8b6..9cb706ad61a 100644 --- a/go.sum +++ b/go.sum @@ -64,8 +64,8 @@ github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 h1:rQvjv7gRi6 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= github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= -github.com/containernetworking/cni v1.2.0 h1:fEjhlfWwWAXEvlcMQu/i6z8DA0Kbu7EcmR5+zb6cm5I= -github.com/containernetworking/cni v1.2.0/go.mod h1:/r+vA/7vrynNfbvSP9g8tIKEoy6win7sALJAw4ZiJks= +github.com/containernetworking/cni v1.2.1 h1:PU9lIBbXNqdPIEuIxWGbtznlecv4Y+ZYqjX/j/2S7ug= +github.com/containernetworking/cni v1.2.1/go.mod h1:m2nkpHY4lRZx89NUXHj4jahE5JCgaJuygB8cSwj0CTU= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= github.com/containers/ocicrypt v1.1.10 h1:r7UR6o8+lyhkEywetubUUgcKFjOWOaWz8cEBrCPX0ic= @@ -119,7 +119,6 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= From ac4830dfaa8a785d0cc61724f307b42fe49d1d4e Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 18 Jun 2024 10:28:30 +0900 Subject: [PATCH 0510/1066] MAINTAINERS: move Ye Sijun (junnplus) from a COMMITTER to a EMERITUS Ye Sijun (junnplus) served as a Committer of nerdctl from November 2022 to June 2024. Sijun has made significant improvements especially to `nerdctl compose`, IPAM, and cosign integration. https://github.com/containerd/nerdctl/pulls?q=author%3Ajunnplus+ We show our huge appreciation to Sijun. Signed-off-by: Akihiro Suda --- EMERITUS.md | 9 +++++++++ MAINTAINERS | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/EMERITUS.md b/EMERITUS.md index 0cd95c3840d..ed17a87f02f 100644 --- a/EMERITUS.md +++ b/EMERITUS.md @@ -2,6 +2,15 @@ See [`MAINTAINERS`](./MAINTAINERS) for the current active maintainers. - - - # nerdctl Emeritus Maintainers +## Committers +### Ye Sijun ([@junnplus](https://github.com/junnplus)) +Ye Sijun (GitHub ID [@junnplus](https://github.com/junnplus)) served as +a Committer of nerdctl from November 2022 to June 2024. +Prior to his role as a Committer, Sijun served as a Reviewer since February 2022. + +Sijun has made [significant improvements](https://github.com/containerd/nerdctl/pulls?q=author%3Ajunnplus+) +especially to `nerdctl compose`, IPAM, and cosign integration. + ## Reviewers ### Hanchin Hsieh ([@yuchanns](https://github.com/yuchanns)) Hanchin Hsieh (GitHub ID [@yuchanns](https://github.com/yuchanns)) served as diff --git a/MAINTAINERS b/MAINTAINERS index bd30678e582..8fbc21ebdf6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15,7 +15,6 @@ "ktock","Kohei Tokunaga","ktokunaga.mail@gmail.com","" "fahedouch","Fahed Dorgaa","fahed.dorgaa@gmail.com","EE7A 5503 CE0D 38AC 5B95 A500 F35F F497 60A8 65FA" "Zheaoli", "Zheao Li", "me@manjusaka.me","6E0D D9FA BAD5 AF61 D884 01EE 878F 445D 9C6C E65E" -"junnplus","Ye Sijun","junnplus@gmail.com","" "djdongjin", "Jin Dong", "djdongjin95@gmail.com","" "yankay", "Kay Yan", "kay.yan@daocloud.io", "" From c0e4e92c259e9f1cef33fec7fdd4f32442c98987 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 17 Jun 2024 14:25:40 -0700 Subject: [PATCH 0511/1066] Add mechanism to prevent Cmd from executing multiple times Signed-off-by: apostasie --- pkg/testutil/testutil.go | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index accc5228d72..5c16585c513 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -26,6 +26,7 @@ import ( "path/filepath" "runtime" "strings" + "sync" "testing" "time" @@ -343,11 +344,26 @@ func (b *Base) EnsureContainerExited(con string, expectedExitCode int) { type Cmd struct { icmd.Cmd *Base + runResult *icmd.Result + mu sync.Mutex } func (c *Cmd) Run() *icmd.Result { c.Base.T.Helper() - return icmd.RunCmd(c.Cmd) + c.mu.Lock() + c.runResult = icmd.RunCmd(c.Cmd) + c.mu.Unlock() + return c.runResult +} + +func (c *Cmd) runIfNecessary() *icmd.Result { + c.Base.T.Helper() + c.mu.Lock() + if c.runResult == nil { + c.runResult = icmd.RunCmd(c.Cmd) + } + c.mu.Unlock() + return c.runResult } func (c *Cmd) CmdOption(cmdOptions ...func(*Cmd)) *Cmd { @@ -359,7 +375,7 @@ func (c *Cmd) CmdOption(cmdOptions ...func(*Cmd)) *Cmd { func (c *Cmd) Assert(expected icmd.Expected) { c.Base.T.Helper() - c.Run().Assert(c.Base.T, expected) + c.runIfNecessary().Assert(c.Base.T, expected) } func (c *Cmd) AssertOK() { @@ -369,13 +385,13 @@ func (c *Cmd) AssertOK() { func (c *Cmd) AssertFail() { c.Base.T.Helper() - res := c.Run() + res := c.runIfNecessary() assert.Assert(c.Base.T, res.ExitCode != 0) } func (c *Cmd) AssertExitCode(exitCode int) { c.Base.T.Helper() - res := c.Run() + res := c.runIfNecessary() assert.Assert(c.Base.T, res.ExitCode == exitCode, res.Combined()) } @@ -397,7 +413,7 @@ func (c *Cmd) AssertErrContains(s string) { func (c *Cmd) AssertCombinedOutContains(s string) { c.Base.T.Helper() - res := c.Run() + res := c.runIfNecessary() assert.Assert(c.Base.T, strings.Contains(res.Combined(), s), fmt.Sprintf("expected output to contain %q: %q", s, res.Combined())) } @@ -489,21 +505,21 @@ func (c *Cmd) AssertNoOut(s string) { func (c *Cmd) AssertOutWithFunc(fn func(stdout string) error) { c.Base.T.Helper() - res := c.Run() + res := c.runIfNecessary() assert.Equal(c.Base.T, 0, res.ExitCode, res.Combined()) assert.NilError(c.Base.T, fn(res.Stdout()), res.Combined()) } func (c *Cmd) AssertOutStreamsWithFunc(fn func(stdout, stderr string) error) { c.Base.T.Helper() - res := c.Run() + res := c.runIfNecessary() assert.Equal(c.Base.T, 0, res.ExitCode, res.Combined()) assert.NilError(c.Base.T, fn(res.Stdout(), res.Stderr()), res.Combined()) } func (c *Cmd) Out() string { c.Base.T.Helper() - res := c.Run() + res := c.runIfNecessary() assert.Equal(c.Base.T, 0, res.ExitCode, res.Combined()) return res.Stdout() } From 6d0c8f872d86f625bfb9bc24e06ef66f4d139b2f Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 17 Jun 2024 18:18:55 -0700 Subject: [PATCH 0512/1066] Replace SetEnv invocation by base.Env to unlock parallelization Signed-off-by: apostasie --- cmd/nerdctl/builder_build_test.go | 13 +++++----- cmd/nerdctl/compose_config_test.go | 2 +- cmd/nerdctl/compose_exec_linux_test.go | 3 +-- cmd/nerdctl/compose_run_linux_test.go | 25 +++++++++---------- cmd/nerdctl/compose_up_linux_test.go | 3 +-- cmd/nerdctl/container_exec_test.go | 3 +-- cmd/nerdctl/container_run_test.go | 4 +-- .../container_run_verify_linux_test.go | 24 +++++++++--------- cmd/nerdctl/image_pull_linux_test.go | 19 +++++++------- cmd/nerdctl/ipfs_compose_linux_test.go | 3 +-- cmd/nerdctl/ipfs_linux_test.go | 11 ++++---- cmd/nerdctl/ipfs_registry_linux_test.go | 5 ++-- cmd/nerdctl/main_test.go | 3 --- cmd/nerdctl/system_info_test.go | 3 +-- pkg/testutil/testutil.go | 1 + 15 files changed, 56 insertions(+), 66 deletions(-) diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index 6df2f7bd210..59b25d7fc42 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -190,7 +190,7 @@ CMD ["echo", "nerdctl-build-test-dockerfile"] defer os.Chdir(pwd) // hack os.Getwd return "(unreachable)" on rootless - t.Setenv("PWD", buildCtx) + base.Env = append(base.Env, "PWD="+buildCtx) base.Cmd("build", "-t", imageName, "-f", "Dockerfile", "..").AssertOK() base.Cmd("build", "-t", imageName, "-f", "Dockerfile", ".").AssertOK() @@ -281,14 +281,13 @@ CMD echo $TEST_STRING for _, tc := range validCases { t.Run(tc.name, func(t *testing.T) { + subBase := testutil.NewBase(t) if tc.envSet { - err := os.Setenv("TEST_STRING", tc.envValue) - assert.NilError(t, err) - defer os.Unsetenv("TEST_STRING") + subBase.Env = append(base.Env, "TEST_STRING="+tc.envValue) } - base.Cmd("build", buildCtx, "-t", imageName, "--build-arg", tc.arg).AssertOK() - base.Cmd("run", "--rm", imageName).AssertOutExactly(tc.expected) + subBase.Cmd("build", buildCtx, "-t", imageName, "--build-arg", tc.arg).AssertOK() + subBase.Cmd("run", "--rm", imageName).AssertOutExactly(tc.expected) }) } } @@ -485,7 +484,7 @@ CMD ["cat", "/source-date-epoch"] buildCtx := createBuildContext(t, dockerfile) const sourceDateEpochEnvStr = "1111111111" - t.Setenv("SOURCE_DATE_EPOCH", sourceDateEpochEnvStr) + base.Env = append(base.Env, "SOURCE_DATE_EPOCH="+sourceDateEpochEnvStr) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("run", "--rm", imageName).AssertOutExactly(sourceDateEpochEnvStr + "\n") diff --git a/cmd/nerdctl/compose_config_test.go b/cmd/nerdctl/compose_config_test.go index d2af27b5832..67e99580cdd 100644 --- a/cmd/nerdctl/compose_config_test.go +++ b/cmd/nerdctl/compose_config_test.go @@ -128,7 +128,7 @@ services: image: alpine:3.14 `) - base.Env = append(os.Environ(), "COMPOSE_FILE="+comp.YAMLFullPath()+","+filepath.Join(comp.Dir(), "docker-compose.test.yml"), "COMPOSE_PATH_SEPARATOR=,") + base.Env = append(base.Env, "COMPOSE_FILE="+comp.YAMLFullPath()+","+filepath.Join(comp.Dir(), "docker-compose.test.yml"), "COMPOSE_PATH_SEPARATOR=,") base.ComposeCmd("config").AssertOutContains("alpine:3.14") base.ComposeCmd("--project-directory", comp.Dir(), "config", "--services").AssertOutContainsAll("hello1\n", "hello2\n") diff --git a/cmd/nerdctl/compose_exec_linux_test.go b/cmd/nerdctl/compose_exec_linux_test.go index 26d9f07738c..2cb758f77dc 100644 --- a/cmd/nerdctl/compose_exec_linux_test.go +++ b/cmd/nerdctl/compose_exec_linux_test.go @@ -20,7 +20,6 @@ import ( "errors" "fmt" "net" - "os" "runtime" "strings" "testing" @@ -78,7 +77,7 @@ services: defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").AssertOK() // FYI: https://github.com/containerd/nerdctl/blob/e4b2b6da56555dc29ed66d0fd8e7094ff2bc002d/cmd/nerdctl/run_test.go#L177 - base.Env = append(os.Environ(), "CORGE=corge-value-in-host", "GARPLY=garply-value-in-host") + base.Env = append(base.Env, "CORGE=corge-value-in-host", "GARPLY=garply-value-in-host") base.ComposeCmd("-f", comp.YAMLFullPath(), "exec", "-i=false", "--no-TTY", "--env", "FOO=foo1,foo2", "--env", "BAR=bar1 bar2", diff --git a/cmd/nerdctl/compose_run_linux_test.go b/cmd/nerdctl/compose_run_linux_test.go index 74874d4d298..f2e06fcea35 100644 --- a/cmd/nerdctl/compose_run_linux_test.go +++ b/cmd/nerdctl/compose_run_linux_test.go @@ -424,22 +424,21 @@ func TestComposePushAndPullWithCosignVerify(t *testing.T) { testutil.RequireExecutable(t, "cosign") testutil.DockerIncompatible(t) testutil.RequiresBuild(t) - base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() + t.Parallel() - // set up cosign and local registry - t.Setenv("COSIGN_PASSWORD", "1") - keyPair := newCosignKeyPair(t, "cosign-key-pair") - defer keyPair.cleanup() + base := testutil.NewBase(t) + base.Env = append(base.Env, "COSIGN_PASSWORD=1") + keyPair := newCosignKeyPair(t, "cosign-key-pair", "1") reg := testregistry.NewWithNoAuth(base, 0, false) - defer reg.Cleanup(nil) - - localhostIP := "127.0.0.1" - t.Logf("localhost IP=%q", localhostIP) - testImageRefPrefix := fmt.Sprintf("%s:%d/", - localhostIP, reg.Port) - t.Logf("testImageRefPrefix=%q", testImageRefPrefix) + t.Cleanup(func() { + keyPair.cleanup() + base.Cmd("builder", "prune").Run() + reg.Cleanup(nil) + }) + + tID := testutil.Identifier(t) + testImageRefPrefix := fmt.Sprintf("127.0.0.1:%d/%s/", reg.Port, tID) var ( imageSvc0 = testImageRefPrefix + "composebuild_svc0" diff --git a/cmd/nerdctl/compose_up_linux_test.go b/cmd/nerdctl/compose_up_linux_test.go index 95dc761c54b..d060bada8c6 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/cmd/nerdctl/compose_up_linux_test.go @@ -19,7 +19,6 @@ package main import ( "fmt" "io" - "os" "strings" "testing" "time" @@ -269,7 +268,7 @@ services: projectName := comp.ProjectName() t.Logf("projectName=%q", projectName) - base.Env = append(os.Environ(), "ADDRESS=0.0.0.0") + base.Env = append(base.Env, "ADDRESS=0.0.0.0") base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "-d").AssertOK() defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() diff --git a/cmd/nerdctl/container_exec_test.go b/cmd/nerdctl/container_exec_test.go index bcd1b41abe9..c952aadb8d2 100644 --- a/cmd/nerdctl/container_exec_test.go +++ b/cmd/nerdctl/container_exec_test.go @@ -18,7 +18,6 @@ package main import ( "errors" - "os" "runtime" "strings" "testing" @@ -80,7 +79,7 @@ func TestExecEnv(t *testing.T) { base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", "1h").AssertOK() base.EnsureContainerStarted(testContainer) - base.Env = append(os.Environ(), "CORGE=corge-value-in-host", "GARPLY=garply-value-in-host") + base.Env = append(base.Env, "CORGE=corge-value-in-host", "GARPLY=garply-value-in-host") base.Cmd("exec", "--env", "FOO=foo1,foo2", "--env", "BAR=bar1 bar2", diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index 2fb732573c7..1beaf6b0fc0 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -145,7 +145,7 @@ func TestRunCIDFile(t *testing.T) { func TestRunEnvFile(t *testing.T) { t.Parallel() base := testutil.NewBase(t) - base.Env = append(os.Environ(), "HOST_ENV=ENV-IN-HOST") + base.Env = append(base.Env, "HOST_ENV=ENV-IN-HOST") tID := testutil.Identifier(t) file1, err := os.CreateTemp("", tID) @@ -172,7 +172,7 @@ func TestRunEnvFile(t *testing.T) { func TestRunEnv(t *testing.T) { t.Parallel() base := testutil.NewBase(t) - base.Env = append(os.Environ(), "CORGE=corge-value-in-host", "GARPLY=garply-value-in-host") + base.Env = append(base.Env, "CORGE=corge-value-in-host", "GARPLY=garply-value-in-host") base.Cmd("run", "--rm", "--env", "FOO=foo1,foo2", "--env", "BAR=bar1 bar2", diff --git a/cmd/nerdctl/container_run_verify_linux_test.go b/cmd/nerdctl/container_run_verify_linux_test.go index 306403c9cd9..9ef955dc986 100644 --- a/cmd/nerdctl/container_run_verify_linux_test.go +++ b/cmd/nerdctl/container_run_verify_linux_test.go @@ -28,21 +28,21 @@ func TestRunVerifyCosign(t *testing.T) { testutil.RequireExecutable(t, "cosign") testutil.DockerIncompatible(t) testutil.RequiresBuild(t) - t.Setenv("COSIGN_PASSWORD", "1") - keyPair := newCosignKeyPair(t, "cosign-key-pair") - defer keyPair.cleanup() + t.Parallel() + base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() - tID := testutil.Identifier(t) - reg := testregistry.NewWithNoAuth(base, 0, false) - defer reg.Cleanup(nil) + base.Env = append(base.Env, "COSIGN_PASSWORD=1") - localhostIP := "127.0.0.1" - t.Logf("localhost IP=%q", localhostIP) - testImageRef := fmt.Sprintf("%s:%d/%s", - localhostIP, reg.Port, tID) - t.Logf("testImageRef=%q", testImageRef) + keyPair := newCosignKeyPair(t, "cosign-key-pair", "1") + reg := testregistry.NewWithNoAuth(base, 0, false) + t.Cleanup(func() { + keyPair.cleanup() + base.Cmd("builder", "prune").Run() + reg.Cleanup(nil) + }) + tID := testutil.Identifier(t) + testImageRef := fmt.Sprintf("127.0.0.1:%d/%s", reg.Port, tID) dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image_pull_linux_test.go index 37153c3d7af..86aba9972bd 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image_pull_linux_test.go @@ -35,12 +35,13 @@ type cosignKeyPair struct { cleanup func() } -func newCosignKeyPair(t testing.TB, path string) *cosignKeyPair { +func newCosignKeyPair(t testing.TB, path string, password string) *cosignKeyPair { td, err := os.MkdirTemp(t.TempDir(), path) assert.NilError(t, err) cmd := exec.Command("cosign", "generate-key-pair") cmd.Dir = td + cmd.Env = append(cmd.Env, fmt.Sprintf("COSIGN_PASSWORD=%s", password)) if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) } @@ -61,11 +62,11 @@ func TestImageVerifyWithCosign(t *testing.T) { testutil.RequireExecutable(t, "cosign") testutil.DockerIncompatible(t) testutil.RequiresBuild(t) - t.Setenv("COSIGN_PASSWORD", "1") - keyPair := newCosignKeyPair(t, "cosign-key-pair") - defer keyPair.cleanup() base := testutil.NewBase(t) + base.Env = append(base.Env, "COSIGN_PASSWORD=1") defer base.Cmd("builder", "prune").Run() + keyPair := newCosignKeyPair(t, "cosign-key-pair", "1") + defer keyPair.cleanup() tID := testutil.Identifier(t) reg := testregistry.NewWithNoAuth(base, 0, false) defer reg.Cleanup(nil) @@ -111,10 +112,10 @@ func TestImageVerifyWithCosignShouldFailWhenKeyIsNotCorrect(t *testing.T) { testutil.RequireExecutable(t, "cosign") testutil.DockerIncompatible(t) testutil.RequiresBuild(t) - t.Setenv("COSIGN_PASSWORD", "1") - keyPair := newCosignKeyPair(t, "cosign-key-pair") - defer keyPair.cleanup() base := testutil.NewBase(t) + base.Env = append(base.Env, "COSIGN_PASSWORD=1") + keyPair := newCosignKeyPair(t, "cosign-key-pair", "1") + defer keyPair.cleanup() defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) reg := testregistry.NewWithNoAuth(base, 0, false) @@ -135,8 +136,8 @@ CMD ["echo", "nerdctl-build-test-string"] base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.publicKey).AssertOK() - t.Setenv("COSIGN_PASSWORD", "2") - newKeyPair := newCosignKeyPair(t, "cosign-key-pair-test") + base.Env = append(base.Env, "COSIGN_PASSWORD=2") + newKeyPair := newCosignKeyPair(t, "cosign-key-pair-test", "2") base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+newKeyPair.publicKey).AssertFail() } diff --git a/cmd/nerdctl/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs_compose_linux_test.go index 30ff09b5a9a..06f211f3897 100644 --- a/cmd/nerdctl/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs_compose_linux_test.go @@ -19,7 +19,6 @@ package main import ( "fmt" "io" - "os" "strings" "testing" @@ -67,7 +66,7 @@ func TestIPFSComposeUp(t *testing.T) { for i, img := range []string{testutil.WordpressImage, testutil.MariaDBImage} { ipfsImgs[i] = pushImageToIPFS(t, base, img, tt.pushOptions...) } - base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER="+tt.snapshotter) + base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER="+tt.snapshotter) testComposeUp(t, base, fmt.Sprintf(` version: '3.1' diff --git a/cmd/nerdctl/ipfs_linux_test.go b/cmd/nerdctl/ipfs_linux_test.go index c0a31842cad..f86d7d92a97 100644 --- a/cmd/nerdctl/ipfs_linux_test.go +++ b/cmd/nerdctl/ipfs_linux_test.go @@ -18,7 +18,6 @@ package main import ( "fmt" - "os" "regexp" "testing" @@ -33,7 +32,7 @@ func TestIPFS(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage) - base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=overlayfs") + base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=overlayfs") base.Cmd("pull", ipfsCID).AssertOK() base.Cmd("run", "--rm", ipfsCID, "echo", "hello").AssertOK() @@ -66,7 +65,7 @@ func TestIPFSAddress(t *testing.T) { ipfsaddr, done := runIPFSDaemonContainer(t, base) defer done() ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, fmt.Sprintf("--ipfs-address=%s", ipfsaddr)) - base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=overlayfs") + base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=overlayfs") base.Cmd("pull", "--ipfs-address", ipfsaddr, ipfsCID).AssertOK() base.Cmd("run", "--ipfs-address", ipfsaddr, "--rm", ipfsCID, "echo", "hello").AssertOK() } @@ -103,7 +102,7 @@ func TestIPFSCommit(t *testing.T) { base := testutil.NewBase(t) ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage) - base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=overlayfs") + base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=overlayfs") base.Cmd("pull", ipfsCID).AssertOK() base.Cmd("run", "--rm", ipfsCID, "echo", "hello").AssertOK() tID := testutil.Identifier(t) @@ -124,7 +123,7 @@ func TestIPFSWithLazyPulling(t *testing.T) { requiresStargz(base) ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") - base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=stargz") + base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=stargz") base.Cmd("pull", ipfsCID).AssertOK() base.Cmd("run", "--rm", ipfsCID, "ls", "/.stargz-snapshotter").AssertOK() } @@ -139,7 +138,7 @@ func TestIPFSWithLazyPullingCommit(t *testing.T) { requiresStargz(base) ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") - base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=stargz") + base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=stargz") base.Cmd("pull", ipfsCID).AssertOK() base.Cmd("run", "--rm", ipfsCID, "ls", "/.stargz-snapshotter").AssertOK() tID := testutil.Identifier(t) diff --git a/cmd/nerdctl/ipfs_registry_linux_test.go b/cmd/nerdctl/ipfs_registry_linux_test.go index 70d7794fdc5..c47ad9f606b 100644 --- a/cmd/nerdctl/ipfs_registry_linux_test.go +++ b/cmd/nerdctl/ipfs_registry_linux_test.go @@ -17,7 +17,6 @@ package main import ( - "os" "strings" "testing" @@ -28,7 +27,7 @@ func TestIPFSRegistry(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=overlayfs") + base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=overlayfs") ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage) ipfsRegistryAddr := "localhost:5555" ipfsRegistryRef := ipfsRegistryReference(ipfsRegistryAddr, ipfsCID) @@ -44,7 +43,7 @@ func TestIPFSRegistryWithLazyPulling(t *testing.T) { base := testutil.NewBase(t) requiresStargz(base) - base.Env = append(os.Environ(), "CONTAINERD_SNAPSHOTTER=stargz") + base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=stargz") ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") ipfsRegistryAddr := "localhost:5555" ipfsRegistryRef := ipfsRegistryReference(ipfsRegistryAddr, ipfsCID) diff --git a/cmd/nerdctl/main_test.go b/cmd/nerdctl/main_test.go index 184b2d399be..5310ad1cb72 100644 --- a/cmd/nerdctl/main_test.go +++ b/cmd/nerdctl/main_test.go @@ -58,9 +58,6 @@ snapshotter = "dummy-snapshotter-via-toml" base.Cmd("info", "-f", "{{.Driver}}").AssertOutExactly(containerd.DefaultSnapshotter + "\n") // [TOML, Default] - if len(base.Env) == 0 { - base.Env = os.Environ() - } base.Env = append(base.Env, "NERDCTL_TOML="+tomlPath) base.Cmd("info", "-f", "{{.Driver}}").AssertOutExactly("dummy-snapshotter-via-toml\n") diff --git a/cmd/nerdctl/system_info_test.go b/cmd/nerdctl/system_info_test.go index dfe2665bf3d..7d7ec7a7c19 100644 --- a/cmd/nerdctl/system_info_test.go +++ b/cmd/nerdctl/system_info_test.go @@ -19,7 +19,6 @@ package main import ( "encoding/json" "fmt" - "os" "testing" "github.com/containerd/nerdctl/v2/pkg/infoutil" @@ -57,6 +56,6 @@ func TestInfoWithNamespace(t *testing.T) { base.Cmd("info").AssertOutContains("Namespace: default") - base.Env = append(os.Environ(), "CONTAINERD_NAMESPACE=test") + base.Env = append(base.Env, "CONTAINERD_NAMESPACE=test") base.Cmd("info").AssertOutContains("Namespace: test") } diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index accc5228d72..01fa7866467 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -685,6 +685,7 @@ func newBase(t *testing.T, ns string, ipv6Compatible bool) *Base { DaemonIsKillable: GetDaemonIsKillable(), EnableIPv6: GetEnableIPv6(), IPv6Compatible: ipv6Compatible, + Env: os.Environ(), } if base.EnableIPv6 && !base.IPv6Compatible { t.Skip("runner skips non-IPv6 compatible tests in the IPv6 environment") From 58f7720eb29ca26c2665e49e86ea6de205608193 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 22:21:31 +0000 Subject: [PATCH 0513/1066] build(deps): bump docker/build-push-action from 6.0.0 to 6.0.1 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.0.0 to 6.0.1. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.0.0...v6.0.1) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index c817d9e791e..a389e4a100f 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.0.0 + uses: docker/build-push-action@v6.0.1 with: context: . platforms: linux/amd64,linux/arm64 From 5dd36b60e17d71bdb97360cb1eca41bbd3933af8 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 15 Jun 2024 21:52:16 -0700 Subject: [PATCH 0514/1066] Implement network namespacing Signed-off-by: apostasie --- cmd/nerdctl/completion.go | 2 +- cmd/nerdctl/network_inspect_test.go | 25 ++++++++++++++++++ cmd/nerdctl/network_remove_linux_test.go | 24 ----------------- docs/cni.md | 13 ++++++++-- docs/dir.md | 4 +++ pkg/cmd/compose/compose.go | 2 +- pkg/cmd/container/kill.go | 2 +- pkg/cmd/network/create.go | 2 +- pkg/cmd/network/inspect.go | 2 +- pkg/cmd/network/list.go | 2 +- pkg/cmd/network/prune.go | 2 +- pkg/cmd/network/remove.go | 2 +- .../container_network_manager_linux.go | 2 +- .../container_network_manager_windows.go | 4 +-- pkg/netutil/netutil.go | 26 +++++++++++++++++-- pkg/ocihook/ocihook.go | 2 +- 16 files changed, 76 insertions(+), 40 deletions(-) diff --git a/cmd/nerdctl/completion.go b/cmd/nerdctl/completion.go index 15dd83a3260..ebd8d47c8bd 100644 --- a/cmd/nerdctl/completion.go +++ b/cmd/nerdctl/completion.go @@ -109,7 +109,7 @@ func shellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, excludeMap[ex] = struct{}{} } - e, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath) + e, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath, netutil.WithNamespace(globalOptions.Namespace)) if err != nil { return nil, cobra.ShellCompDirectiveError } diff --git a/cmd/nerdctl/network_inspect_test.go b/cmd/nerdctl/network_inspect_test.go index bab22c998eb..0582bb7fc3d 100644 --- a/cmd/nerdctl/network_inspect_test.go +++ b/cmd/nerdctl/network_inspect_test.go @@ -66,3 +66,28 @@ func TestNetworkInspect(t *testing.T) { } assert.DeepEqual(base.T, expectedIPAM, got.IPAM) } + +func TestNetworkWithNamespace(t *testing.T) { + testutil.DockerIncompatible(t) + + t.Parallel() + + tID := testutil.Identifier(t) + base := testutil.NewBase(t) + baseOther := testutil.NewBaseWithNamespace(t, tID) + + tearDown := func() { + base.Cmd("network", "rm", tID).Run() + baseOther.Cmd("namespace", "remove", tID).Run() + } + tearDown() + t.Cleanup(tearDown) + + base.Cmd("network", "create", tID).AssertOK() + + // Other namespace cannot inspect, prune, see, or remove this network + baseOther.Cmd("network", "inspect", tID).AssertFail() + baseOther.Cmd("network", "prune", "-f").AssertOutNotContains(tID) + baseOther.Cmd("network", "ls").AssertOutNotContains(tID) + baseOther.Cmd("network", "remove", tID).AssertFail() +} diff --git a/cmd/nerdctl/network_remove_linux_test.go b/cmd/nerdctl/network_remove_linux_test.go index 80ccc504069..9ac5267a46a 100644 --- a/cmd/nerdctl/network_remove_linux_test.go +++ b/cmd/nerdctl/network_remove_linux_test.go @@ -25,30 +25,6 @@ import ( "gotest.tools/v3/assert" ) -func TestNetworkRemoveInOtherNamespace(t *testing.T) { - if rootlessutil.IsRootless() { - t.Skip("test skipped for remove rootless network") - } - if testutil.GetTarget() == testutil.Docker { - t.Skip("test skipped for docker") - } - // --namespace=nerdctl-test - base := testutil.NewBase(t) - // --namespace=nerdctl-other - baseOther := testutil.NewBaseWithNamespace(t, "nerdctl-other") - networkName := testutil.Identifier(t) - - base.Cmd("network", "create", networkName).AssertOK() - defer base.Cmd("network", "rm", networkName).AssertOK() - - tID := testutil.Identifier(t) - base.Cmd("run", "-d", "--net", networkName, "--name", tID, testutil.AlpineImage, "sleep", "infinity").AssertOK() - defer base.Cmd("rm", "-f", tID).Run() - - // delete network in namespace nerdctl-other - baseOther.Cmd("network", "rm", networkName).AssertFail() -} - func TestNetworkRemove(t *testing.T) { if rootlessutil.IsRootless() { t.Skip("test skipped for remove rootless network") diff --git a/docs/cni.md b/docs/cni.md index 02ec79f1cce..67313891604 100644 --- a/docs/cni.md +++ b/docs/cni.md @@ -116,7 +116,16 @@ For example: ## Custom networks You can also customize your CNI network by providing configuration files. -For example you have one configuration file(`/etc/cni/net.d/10-mynet.conf`) + +When rootful, the expected root location is `/etc/cni/net.d`. +For rootless, the expected root location is `~/.config/cni/net.d/` + +Configuration files (like `10-mynet.conf`) can be placed either in the root location, +or under a subfolder. +If in the root location, this network will be available to all nerdctl namespaces. +If placed in a subfolder, it will be available only to the identically named namespace. + +For example, you have one configuration file(`/etc/cni/net.d/10-mynet.conf`) for `bridge` network: ```json @@ -138,7 +147,7 @@ for `bridge` network: ``` This will configure a new CNI network with the name `mynet`, and you can use -this network to create a container: +this network to create a container in any namespace: ```console # nerdctl run -it --net mynet --rm alpine ip addr show diff --git a/docs/dir.md b/docs/dir.md index 7bf5418a1e0..4843eadb6bc 100644 --- a/docs/dir.md +++ b/docs/dir.md @@ -65,5 +65,9 @@ Data volume Can be overridden with `nerdctl --cni-netconfpath=` flag and environment variable `$NETCONFPATH`. +At the top-level of , network (files) are shared accross all namespaces. +Sub-folders inside are only available to the namespace bearing the same name, +and its networks definitions are private. + Files: - `nerdctl-.conflist`: CNI conf list created by nerdctl diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 515a91a8a7f..b0ea6ac3ca9 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -41,7 +41,7 @@ import ( // New returns a new *composer.Composer. func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, options composer.Options, stdout, stderr io.Writer) (*composer.Composer, error) { - cniEnv, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath, netutil.WithDefaultNetwork()) + cniEnv, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath, netutil.WithNamespace(globalOptions.Namespace), netutil.WithDefaultNetwork()) if err != nil { return nil, err } diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index 20c9bd9efed..d185ff09be3 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -152,7 +152,7 @@ func cleanupNetwork(ctx context.Context, container containerd.Container, globalO case nettype.Host, nettype.None, nettype.Container: // NOP case nettype.CNI: - e, err := netutil.NewCNIEnv(globalOpts.CNIPath, globalOpts.CNINetConfPath, netutil.WithDefaultNetwork()) + e, err := netutil.NewCNIEnv(globalOpts.CNIPath, globalOpts.CNINetConfPath, netutil.WithNamespace(globalOpts.Namespace), netutil.WithDefaultNetwork()) if err != nil { return err } diff --git a/pkg/cmd/network/create.go b/pkg/cmd/network/create.go index 3115a127640..43f1f96d6ff 100644 --- a/pkg/cmd/network/create.go +++ b/pkg/cmd/network/create.go @@ -33,7 +33,7 @@ func Create(options types.NetworkCreateOptions, stdout io.Writer) error { options.Subnets = []string{""} } - e, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath) + e, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace)) if err != nil { return err } diff --git a/pkg/cmd/network/inspect.go b/pkg/cmd/network/inspect.go index 9ef9581b4a4..1d680642856 100644 --- a/pkg/cmd/network/inspect.go +++ b/pkg/cmd/network/inspect.go @@ -32,7 +32,7 @@ import ( func Inspect(ctx context.Context, options types.NetworkInspectOptions) error { globalOptions := options.GOptions - e, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath) + e, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace)) if err != nil { return err diff --git a/pkg/cmd/network/list.go b/pkg/cmd/network/list.go index ab7c2696ee2..b2075356d8c 100644 --- a/pkg/cmd/network/list.go +++ b/pkg/cmd/network/list.go @@ -65,7 +65,7 @@ func List(ctx context.Context, options types.NetworkListOptions) error { } } - e, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath) + e, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace)) if err != nil { return err } diff --git a/pkg/cmd/network/prune.go b/pkg/cmd/network/prune.go index 4595e6fe2b4..9294583947c 100644 --- a/pkg/cmd/network/prune.go +++ b/pkg/cmd/network/prune.go @@ -28,7 +28,7 @@ import ( ) func Prune(ctx context.Context, client *containerd.Client, options types.NetworkPruneOptions) error { - e, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath) + e, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace)) if err != nil { return err } diff --git a/pkg/cmd/network/remove.go b/pkg/cmd/network/remove.go index a2fc73c0e17..133a2b47bba 100644 --- a/pkg/cmd/network/remove.go +++ b/pkg/cmd/network/remove.go @@ -27,7 +27,7 @@ import ( ) func Remove(ctx context.Context, client *containerd.Client, options types.NetworkRemoveOptions) error { - e, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath) + e, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace)) if err != nil { return err } diff --git a/pkg/containerutil/container_network_manager_linux.go b/pkg/containerutil/container_network_manager_linux.go index e4d058f856f..534040f362d 100644 --- a/pkg/containerutil/container_network_manager_linux.go +++ b/pkg/containerutil/container_network_manager_linux.go @@ -39,7 +39,7 @@ type cniNetworkManagerPlatform struct { // Verifies that the internal network settings are correct. func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { - e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithDefaultNetwork()) + e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork()) if err != nil { return err } diff --git a/pkg/containerutil/container_network_manager_windows.go b/pkg/containerutil/container_network_manager_windows.go index ba7304c30f5..399ac70bacb 100644 --- a/pkg/containerutil/container_network_manager_windows.go +++ b/pkg/containerutil/container_network_manager_windows.go @@ -36,7 +36,7 @@ type cniNetworkManagerPlatform struct { // Verifies that the internal network settings are correct. func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { - e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithDefaultNetwork()) + e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork()) if err != nil { return err } @@ -67,7 +67,7 @@ func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { } func (m *cniNetworkManager) getCNI() (gocni.CNI, error) { - e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithDefaultNetwork()) + e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork()) if err != nil { return nil, fmt.Errorf("failed to instantiate CNI env: %s", err) } diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 5691e27e8d6..10a4b99148b 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -46,6 +46,7 @@ import ( type CNIEnv struct { Path string NetconfPath string + Namespace string } type CNIEnvOpt func(e *CNIEnv) error @@ -132,6 +133,16 @@ func WithDefaultNetwork() CNIEnvOpt { } } +func WithNamespace(namespace string) CNIEnvOpt { + return func(e *CNIEnv) error { + if err := os.MkdirAll(filepath.Join(e.NetconfPath, namespace), 0755); err != nil { + return err + } + e.Namespace = namespace + return nil + } +} + func NewCNIEnv(cniPath, cniConfPath string, opts ...CNIEnvOpt) (*CNIEnv, error) { e := CNIEnv{ Path: cniPath, @@ -193,7 +204,10 @@ func (e *CNIEnv) FilterNetworks(filterf func(*NetworkConfig) bool) ([]*NetworkCo } func (e *CNIEnv) getConfigPathForNetworkName(netName string) string { - return filepath.Join(e.NetconfPath, "nerdctl-"+netName+".conflist") + if netName == DefaultNetworkName || e.Namespace == "" { + return filepath.Join(e.NetconfPath, "nerdctl-"+netName+".conflist") + } + return filepath.Join(e.NetconfPath, e.Namespace, "nerdctl-"+netName+".conflist") } func (e *CNIEnv) usedSubnets() ([]*net.IPNet, error) { @@ -404,10 +418,18 @@ func (e *CNIEnv) writeNetworkConfig(net *NetworkConfig) error { // networkConfigList loads config from dir if dir exists. func (e *CNIEnv) networkConfigList() ([]*NetworkConfig, error) { l := []*NetworkConfig{} - fileNames, err := libcni.ConfFiles(e.NetconfPath, []string{".conf", ".conflist", ".json"}) + common, err := libcni.ConfFiles(e.NetconfPath, []string{".conf", ".conflist", ".json"}) if err != nil { return nil, err } + namespaced := []string{} + if e.Namespace != "" { + namespaced, err = libcni.ConfFiles(filepath.Join(e.NetconfPath, e.Namespace), []string{".conf", ".conflist", ".json"}) + if err != nil { + return nil, err + } + } + fileNames := append(common, namespaced...) sort.Strings(fileNames) for _, fileName := range fileNames { var lcl *libcni.NetworkConfigList diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 4ab13a7ce78..d023de39b40 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -152,7 +152,7 @@ func newHandlerOpts(state *specs.State, dataStore, cniPath, cniNetconfPath strin case nettype.Host, nettype.None, nettype.Container: // NOP case nettype.CNI: - e, err := netutil.NewCNIEnv(cniPath, cniNetconfPath, netutil.WithDefaultNetwork()) + e, err := netutil.NewCNIEnv(cniPath, cniNetconfPath, netutil.WithNamespace(namespace), netutil.WithDefaultNetwork()) if err != nil { return nil, err } From 15a8a8dc146716dfb1c51725de8cb1a34bb7501d Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 18 Jun 2024 23:32:38 -0700 Subject: [PATCH 0515/1066] Aftermath docker migration: fix racyness in tests Signed-off-by: apostasie --- cmd/nerdctl/container_create_linux_test.go | 26 +++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/cmd/nerdctl/container_create_linux_test.go b/cmd/nerdctl/container_create_linux_test.go index 960a2ff3222..871685e70a9 100644 --- a/cmd/nerdctl/container_create_linux_test.go +++ b/cmd/nerdctl/container_create_linux_test.go @@ -106,24 +106,25 @@ func TestCreateWithMACAddress(t *testing.T) { if expect == passedMac { expect = macAddress } - tt.Cleanup(func() { + tearDown := func() { base.Cmd("rm", "-f", containerName).Run() - }) + } + tearDown() + tt.Cleanup(tearDown) // This is currently blocked by https://github.com/containerd/nerdctl/pull/3104 // res := base.Cmd("create", "-i", "--network", network, "--mac-address", macAddress, testutil.CommonImage).Run() res := base.Cmd("create", "--network", network, "--name", containerName, "--mac-address", macAddress, testutil.CommonImage, - "sh", "-c", "--", "ip addr show eth0 | grep ether").Run() + "sh", "-c", "--", "ip addr show").Run() if !wantErr { assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res.Combined()) // This is currently blocked by: https://github.com/containerd/nerdctl/pull/3104 // res = base.Cmd("start", "-i", containerName). // CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))).Run() - base.Cmd("start", containerName).AssertOK() - res = base.Cmd("logs", containerName).Run() + res = base.Cmd("start", "-a", containerName).Run() assert.Assert(t, strings.Contains(res.Stdout(), expect), fmt.Sprintf("expected output to contain %q: %q", expect, res.Stdout())) - assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res.Combined()) + assert.Assert(t, res.ExitCode == 0, "Command should have succeeded") } else { if testutil.GetTarget() == testutil.Docker && (network == networkIPvlan || network == "container:whatever"+tID) { @@ -131,11 +132,20 @@ func TestCreateWithMACAddress(t *testing.T) { // when using network ipvlan or container in Docker // it delays fail on executing start command assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res.Combined()) - res = base.Cmd("start", "-i", containerName). + res = base.Cmd("start", "-i", "-a", containerName). CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))).Run() } - assert.Assert(t, strings.Contains(res.Combined(), expect), fmt.Sprintf("expected output to contain %q: %q", expect, res.Combined())) + // See https://github.com/containerd/nerdctl/issues/3101 + if testutil.GetTarget() == testutil.Docker && + (network == networkBridge) { + expect = "" + } + if expect != "" { + assert.Assert(t, strings.Contains(res.Combined(), expect), fmt.Sprintf("expected output to contain %q: %q", expect, res.Combined())) + } else { + assert.Assert(t, res.Combined() == "", fmt.Sprintf("expected output to be empty: %q", res.Combined())) + } assert.Assert(t, res.ExitCode != 0, "Command should have failed", res.Combined()) } }) From 0c300dca457096f8374469a01c4f22a1b5af17ce Mon Sep 17 00:00:00 2001 From: guoguangwu Date: Wed, 19 Jun 2024 16:19:33 +0800 Subject: [PATCH 0516/1066] fix: close the hosts file Signed-off-by: guoguangwu --- pkg/dnsutil/hostsstore/updater.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/dnsutil/hostsstore/updater.go b/pkg/dnsutil/hostsstore/updater.go index 2ce10385ca1..e52ef802e47 100644 --- a/pkg/dnsutil/hostsstore/updater.go +++ b/pkg/dnsutil/hostsstore/updater.go @@ -122,6 +122,7 @@ func (u *updater) phase2() error { if err != nil { return err } + defer r.Close() var buf bytes.Buffer if r != nil { if err := parseHostsButSkipMarkedRegion(&buf, r); err != nil { From 515c3adec11f63e5b69d8b99000deecf067b1efc Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 19 Jun 2024 12:57:48 -0700 Subject: [PATCH 0517/1066] Add HOSTNAME environment variable Signed-off-by: apostasie --- cmd/nerdctl/container_run_test.go | 13 +++++++++++++ pkg/cmd/container/create.go | 5 ++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index 1beaf6b0fc0..fcf4305bcad 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -217,6 +217,19 @@ func TestRunEnv(t *testing.T) { return nil }) } +func TestRunHostnameEnv(t *testing.T) { + t.Parallel() + base := testutil.NewBase(t) + + base.Cmd("run", "-i", "--rm", testutil.CommonImage). + CmdOption(testutil.WithStdin(strings.NewReader(`[[ "HOSTNAME=$(hostname)" == "$(env | grep HOSTNAME)" ]]`))). + AssertOK() + + if runtime.GOOS == "windows" { + t.Skip("run --hostname not implemented on Windows yet") + } + base.Cmd("run", "--rm", "--hostname", "foobar", testutil.CommonImage, "env").AssertOutContains("HOSTNAME=foobar") +} func TestRunStdin(t *testing.T) { t.Parallel() diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 081f5da88b5..2b347d890e1 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -139,7 +139,6 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa if err != nil { return nil, nil, err } - opts = append(opts, oci.WithEnv(envs)) if options.Interactive { if options.Detach { @@ -191,6 +190,10 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa if err != nil { return nil, nil, fmt.Errorf("failed to generate internal networking labels: %s", err) } + + envs = append(envs, "HOSTNAME="+netLabelOpts.Hostname) + opts = append(opts, oci.WithEnv(envs)) + // TODO(aznashwan): more formal way to load net opts into internalLabels: internalLabels.hostname = netLabelOpts.Hostname internalLabels.ports = netLabelOpts.PortMappings From e13ff68b9c300ad643d5efff615ae24ce5c48853 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 19 Jun 2024 16:53:22 -0700 Subject: [PATCH 0518/1066] Remove duplicate function Signed-off-by: apostasie --- cmd/nerdctl/completion_linux_test.go | 4 ++-- cmd/nerdctl/compose_pull_linux_test.go | 2 +- cmd/nerdctl/container_logs_test.go | 8 ++++---- cmd/nerdctl/image_prune_test.go | 8 ++++---- cmd/nerdctl/image_remove_linux_test.go | 10 +++++----- cmd/nerdctl/network_create_linux_test.go | 2 +- cmd/nerdctl/network_prune_linux_test.go | 2 +- cmd/nerdctl/system_prune_linux_test.go | 10 +++++----- cmd/nerdctl/volume_prune_linux_test.go | 4 ++-- pkg/testutil/testutil.go | 13 ++----------- 10 files changed, 27 insertions(+), 36 deletions(-) diff --git a/cmd/nerdctl/completion_linux_test.go b/cmd/nerdctl/completion_linux_test.go index 0cde9191ee3..13d96163d61 100644 --- a/cmd/nerdctl/completion_linux_test.go +++ b/cmd/nerdctl/completion_linux_test.go @@ -37,9 +37,9 @@ func TestCompletion(t *testing.T) { base.Cmd(gsc, "run", "-it", "--net", "").AssertOutContains("host\n") base.Cmd(gsc, "run", "-it", "--rm", "--net", "").AssertOutContains("host\n") base.Cmd(gsc, "run", "--restart", "").AssertOutContains("always\n") - base.Cmd(gsc, "network", "rm", "").AssertNoOut("host\n") // host is unremovable + base.Cmd(gsc, "network", "rm", "").AssertOutNotContains("host\n") // host is unremovable base.Cmd(gsc, "run", "--cap-add", "").AssertOutContains("sys_admin\n") - base.Cmd(gsc, "run", "--cap-add", "").AssertNoOut("CAP_SYS_ADMIN\n") // invalid form + base.Cmd(gsc, "run", "--cap-add", "").AssertOutNotContains("CAP_SYS_ADMIN\n") // invalid form // Tests with an image base.Cmd("pull", testutil.AlpineImage).AssertOK() diff --git a/cmd/nerdctl/compose_pull_linux_test.go b/cmd/nerdctl/compose_pull_linux_test.go index 4e86b053194..0040a4f84d9 100644 --- a/cmd/nerdctl/compose_pull_linux_test.go +++ b/cmd/nerdctl/compose_pull_linux_test.go @@ -62,5 +62,5 @@ volumes: projectName := comp.ProjectName() t.Logf("projectName=%q", projectName) - base.ComposeCmd("-f", comp.YAMLFullPath(), "pull", "db").AssertNoOut("wordpress") + base.ComposeCmd("-f", comp.YAMLFullPath(), "pull", "db").AssertOutNotContains("wordpress") } diff --git a/cmd/nerdctl/container_logs_test.go b/cmd/nerdctl/container_logs_test.go index 01fb2ab2790..397aa0c1ad6 100644 --- a/cmd/nerdctl/container_logs_test.go +++ b/cmd/nerdctl/container_logs_test.go @@ -40,9 +40,9 @@ bar` //test since / until flag time.Sleep(3 * time.Second) - base.Cmd("logs", "--since", "1s", containerName).AssertNoOut(expected) + base.Cmd("logs", "--since", "1s", containerName).AssertOutNotContains(expected) base.Cmd("logs", "--since", "10s", containerName).AssertOutContains(expected) - base.Cmd("logs", "--until", "10s", containerName).AssertNoOut(expected) + base.Cmd("logs", "--until", "10s", containerName).AssertOutNotContains(expected) base.Cmd("logs", "--until", "1s", containerName).AssertOutContains(expected) // Ensure follow flag works as expected: @@ -142,7 +142,7 @@ func TestLogsWithFailingContainer(t *testing.T) { // AssertOutContains also asserts that the exit code of the logs command == 0, // even when the container is failing base.Cmd("logs", "-f", containerName).AssertOutContains("bar") - base.Cmd("logs", "-f", containerName).AssertNoOut("baz") + base.Cmd("logs", "-f", containerName).AssertOutNotContains("baz") base.Cmd("rm", "-f", containerName).AssertOK() } @@ -203,7 +203,7 @@ func TestLogsWithForegroundContainers(t *testing.T) { base.Cmd("logs", containerName).AssertOutContains("foo") base.Cmd("logs", containerName).AssertOutContains("bar") - base.Cmd("logs", containerName).AssertNoOut("baz") + base.Cmd("logs", containerName).AssertOutNotContains("baz") }(t) } } diff --git a/cmd/nerdctl/image_prune_test.go b/cmd/nerdctl/image_prune_test.go index b7f0a02e833..560c0df8e37 100644 --- a/cmd/nerdctl/image_prune_test.go +++ b/cmd/nerdctl/image_prune_test.go @@ -40,8 +40,8 @@ func TestImagePrune(t *testing.T) { base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("images").AssertOutContainsAll(imageName, "") - base.Cmd("image", "prune", "--force").AssertNoOut(imageName) - base.Cmd("images").AssertNoOut("") + base.Cmd("image", "prune", "--force").AssertOutNotContains(imageName) + base.Cmd("images").AssertOutNotContains("") base.Cmd("images").AssertOutContains(imageName) } @@ -64,10 +64,10 @@ func TestImagePruneAll(t *testing.T) { tID := testutil.Identifier(t) base.Cmd("run", "--name", tID, imageName).AssertOK() - base.Cmd("image", "prune", "--force", "--all").AssertNoOut(imageName) + base.Cmd("image", "prune", "--force", "--all").AssertOutNotContains(imageName) base.Cmd("images").AssertOutContains(imageName) base.Cmd("rm", "-f", tID).AssertOK() base.Cmd("image", "prune", "--force", "--all").AssertOutContains(imageName) - base.Cmd("images").AssertNoOut(imageName) + base.Cmd("images").AssertOutNotContains(imageName) } diff --git a/cmd/nerdctl/image_remove_linux_test.go b/cmd/nerdctl/image_remove_linux_test.go index 0ad754cc596..55fbc0a898b 100644 --- a/cmd/nerdctl/image_remove_linux_test.go +++ b/cmd/nerdctl/image_remove_linux_test.go @@ -37,7 +37,7 @@ func TestRemoveImage(t *testing.T) { defer base.Cmd("rmi", "-f", testutil.CommonImage).Run() base.Cmd("rmi", "-f", testutil.CommonImage).AssertOK() - base.Cmd("images").AssertNoOut(testutil.ImageRepo(testutil.CommonImage)) + base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) } func TestRemoveRunningImage(t *testing.T) { @@ -58,7 +58,7 @@ func TestRemoveRunningImage(t *testing.T) { base.Cmd("kill", tID).AssertOK() base.Cmd("rmi", testutil.CommonImage).AssertFail() base.Cmd("rmi", "-f", testutil.CommonImage).AssertOK() - base.Cmd("images").AssertNoOut(testutil.ImageRepo(testutil.CommonImage)) + base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) } func TestRemovePausedImage(t *testing.T) { @@ -84,7 +84,7 @@ func TestRemovePausedImage(t *testing.T) { base.Cmd("kill", tID).AssertOK() base.Cmd("rmi", testutil.CommonImage).AssertFail() base.Cmd("rmi", "-f", testutil.CommonImage).AssertOK() - base.Cmd("images").AssertNoOut(testutil.ImageRepo(testutil.CommonImage)) + base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) } func TestRemoveImageWithCreatedContainer(t *testing.T) { @@ -99,9 +99,9 @@ func TestRemoveImageWithCreatedContainer(t *testing.T) { base.Cmd("rmi", testutil.AlpineImage).AssertFail() base.Cmd("rmi", "-f", testutil.AlpineImage).AssertOK() - base.Cmd("images").AssertNoOut(testutil.ImageRepo(testutil.AlpineImage)) + base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.AlpineImage)) // a created container with removed image doesn't impact other `rmi` command base.Cmd("rmi", "-f", testutil.NginxAlpineImage).AssertOK() - base.Cmd("images").AssertNoOut(testutil.ImageRepo(testutil.NginxAlpineImage)) + base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.NginxAlpineImage)) } diff --git a/cmd/nerdctl/network_create_linux_test.go b/cmd/nerdctl/network_create_linux_test.go index d27bf24dd4a..4936edf0991 100644 --- a/cmd/nerdctl/network_create_linux_test.go +++ b/cmd/nerdctl/network_create_linux_test.go @@ -55,7 +55,7 @@ func TestNetworkCreate(t *testing.T) { base.Cmd("network", "create", testNetwork+"-1").AssertOK() defer base.Cmd("network", "rm", testNetwork+"-1").AssertOK() - base.Cmd("run", "--rm", "--net", testNetwork+"-1", testutil.CommonImage, "ip", "route").AssertNoOut(net.IPAM.Config[0].Subnet) + base.Cmd("run", "--rm", "--net", testNetwork+"-1", testutil.CommonImage, "ip", "route").AssertOutNotContains(net.IPAM.Config[0].Subnet) } func TestNetworkCreateIPv6(t *testing.T) { diff --git a/cmd/nerdctl/network_prune_linux_test.go b/cmd/nerdctl/network_prune_linux_test.go index 68ad06efaa2..ae1b92d41a0 100644 --- a/cmd/nerdctl/network_prune_linux_test.go +++ b/cmd/nerdctl/network_prune_linux_test.go @@ -32,7 +32,7 @@ func TestNetworkPrune(t *testing.T) { base.Cmd("run", "-d", "--net", testNetwork, "--name", tID, testutil.NginxAlpineImage).AssertOK() defer base.Cmd("rm", "-f", tID).Run() - base.Cmd("network", "prune", "-f").AssertNoOut(testNetwork) + base.Cmd("network", "prune", "-f").AssertOutNotContains(testNetwork) base.Cmd("stop", tID).AssertOK() base.Cmd("network", "prune", "-f").AssertOutContains(testNetwork) } diff --git a/cmd/nerdctl/system_prune_linux_test.go b/cmd/nerdctl/system_prune_linux_test.go index 32fbf04c4c0..c1e91658f31 100644 --- a/cmd/nerdctl/system_prune_linux_test.go +++ b/cmd/nerdctl/system_prune_linux_test.go @@ -58,11 +58,11 @@ func TestSystemPrune(t *testing.T) { base.Cmd("images").AssertOutContains(testutil.ImageRepo(testutil.CommonImage)) base.Cmd("system", "prune", "-f", "--volumes", "--all").AssertOK() - base.Cmd("volume", "ls").AssertOutContains(vID) // docker system prune --all --volume does not prune named volume - base.Cmd("volume", "ls").AssertNoOut(vID2) // docker system prune --all --volume prune anonymous volume - base.Cmd("ps", "-a").AssertNoOut(tID) - base.Cmd("network", "ls").AssertNoOut(nID) - base.Cmd("images").AssertNoOut(testutil.ImageRepo(testutil.CommonImage)) + base.Cmd("volume", "ls").AssertOutContains(vID) // docker system prune --all --volume does not prune named volume + base.Cmd("volume", "ls").AssertOutNotContains(vID2) // docker system prune --all --volume prune anonymous volume + base.Cmd("ps", "-a").AssertOutNotContains(tID) + base.Cmd("network", "ls").AssertOutNotContains(nID) + base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) if testutil.GetTarget() != testutil.Nerdctl { t.Skip("test skipped for buildkitd is not available with docker-compatible tests") diff --git a/cmd/nerdctl/volume_prune_linux_test.go b/cmd/nerdctl/volume_prune_linux_test.go index a744de0f5fe..df610ca1a04 100644 --- a/cmd/nerdctl/volume_prune_linux_test.go +++ b/cmd/nerdctl/volume_prune_linux_test.go @@ -38,9 +38,9 @@ func TestVolumePrune(t *testing.T) { base.Cmd("volume", "prune", "-f").AssertOutContains(vID) base.Cmd("volume", "prune", "-a", "-f").AssertOutContains(tID + "-2") base.Cmd("volume", "ls").AssertOutContains(tID + "-1") - base.Cmd("volume", "ls").AssertNoOut(tID + "-2") + base.Cmd("volume", "ls").AssertOutNotContains(tID + "-2") base.Cmd("rm", "-f", tID).AssertOK() base.Cmd("volume", "prune", "-a", "-f").AssertOK() - base.Cmd("volume", "ls").AssertNoOut(tID + "-1") + base.Cmd("volume", "ls").AssertOutNotContains(tID + "-1") } diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 03eb3a1ce3a..600fdb29ebe 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -446,6 +446,7 @@ func (c *Cmd) AssertOutContainsAny(strs ...string) { } func (c *Cmd) AssertOutNotContains(s string) { + c.Base.T.Helper() c.AssertOutWithFunc(func(stdout string) error { if strings.Contains(stdout, s) { return fmt.Errorf("expected stdout to not contain %q", s) @@ -455,6 +456,7 @@ func (c *Cmd) AssertOutNotContains(s string) { } func (c *Cmd) AssertErrNotContains(s string) { + c.Base.T.Helper() c.AssertOutWithFunc(func(stderr string) error { if strings.Contains(stderr, s) { return fmt.Errorf("expected stdout to not contain %q", s) @@ -492,17 +494,6 @@ func (c *Cmd) AssertOutStreamsExactly(stdout, stderr string) { c.AssertOutStreamsWithFunc(fn) } -func (c *Cmd) AssertNoOut(s string) { - c.Base.T.Helper() - fn := func(stdout string) error { - if strings.Contains(stdout, s) { - return fmt.Errorf("expected not to contain %q, got %q", s, stdout) - } - return nil - } - c.AssertOutWithFunc(fn) -} - func (c *Cmd) AssertOutWithFunc(fn func(stdout string) error) { c.Base.T.Helper() res := c.runIfNecessary() From 97552985e7b954f18bb64b0c4bec2b1ef226973e Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 18 Jun 2024 20:02:52 -0700 Subject: [PATCH 0519/1066] Bump compose-go to v2 Signed-off-by: apostasie --- .golangci.yml | 1 - cmd/nerdctl/compose_up.go | 4 ++-- go.mod | 7 ++++--- go.sum | 12 +++++------ pkg/composer/build.go | 6 +++--- pkg/composer/composer.go | 20 ++++++++++++------- pkg/composer/config.go | 13 ++++++------ pkg/composer/create.go | 2 +- pkg/composer/down.go | 4 ++-- pkg/composer/logs.go | 4 ++-- pkg/composer/projectloader/projectloader.go | 7 ++++--- pkg/composer/pull.go | 6 +++--- pkg/composer/push.go | 6 +++--- pkg/composer/restart.go | 4 ++-- pkg/composer/run.go | 10 +++++----- pkg/composer/serviceparser/build.go | 2 +- pkg/composer/serviceparser/serviceparser.go | 12 ++++++----- .../serviceparser/serviceparser_test.go | 6 +++--- pkg/composer/up.go | 12 +++++------ pkg/composer/up_network.go | 2 +- pkg/composer/up_volume.go | 2 +- 21 files changed, 75 insertions(+), 67 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a902b9f03b7..5d57ceae6ea 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,7 +1,6 @@ --- run: concurrency: 6 - deadline: 5m linters: disable-all: true enable: diff --git a/cmd/nerdctl/compose_up.go b/cmd/nerdctl/compose_up.go index b36e4ede0bb..5d871dff3bf 100644 --- a/cmd/nerdctl/compose_up.go +++ b/cmd/nerdctl/compose_up.go @@ -100,7 +100,7 @@ func composeUpAction(cmd *cobra.Command, services []string) error { if err != nil { return err } - scale := make(map[string]uint64) + scale := make(map[string]int) for _, s := range scaleSlice { parts := strings.Split(s, "=") if len(parts) != 2 { @@ -110,7 +110,7 @@ func composeUpAction(cmd *cobra.Command, services []string) error { if err != nil { return err } - scale[parts[0]] = uint64(replicas) + scale[parts[0]] = replicas } client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) diff --git a/go.mod b/go.mod index 9d208acfa13..54ce0ca6fdc 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.4 github.com/awslabs/soci-snapshotter v0.6.1 - github.com/compose-spec/compose-go v1.20.2 + github.com/compose-spec/compose-go/v2 v2.1.3 github.com/containerd/accelerated-container-image v1.1.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 @@ -65,6 +65,8 @@ require ( gotest.tools/v3 v3.5.1 ) +require github.com/go-viper/mapstructure/v2 v2.0.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 @@ -92,7 +94,6 @@ require ( github.com/google/uuid v1.6.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 github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.17.9 github.com/klauspost/cpuid/v2 v2.2.3 // indirect @@ -134,7 +135,7 @@ require ( 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 - golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/grpc v1.62.0 // indirect diff --git a/go.sum b/go.sum index 9cb706ad61a..52bcb6c8c71 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y= github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/compose-spec/compose-go/v2 v2.1.3 h1:bD67uqLuL/XgkAK6ir3xZvNLFPxPScEi1KW7R5esrLE= +github.com/compose-spec/compose-go/v2 v2.1.3/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.1.3 h1:4fw0FsGB3YPHzth8H8WalJxnVuUU566+UCTXnoIZRCQ= github.com/containerd/accelerated-container-image v1.1.3/go.mod h1:9mpTpL4W4yAsq2giHgo4B7wTFJgE59qCPh7dZTSpGCA= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= @@ -121,6 +121,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc= +github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -163,8 +165,6 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= @@ -339,8 +339,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= +golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= diff --git a/pkg/composer/build.go b/pkg/composer/build.go index 8f34835bc3b..ff235e6f905 100644 --- a/pkg/composer/build.go +++ b/pkg/composer/build.go @@ -21,7 +21,7 @@ import ( "fmt" "os" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" ) @@ -33,8 +33,8 @@ type BuildOptions struct { } func (c *Composer) Build(ctx context.Context, bo BuildOptions, services []string) error { - return c.project.WithServices(services, func(svc types.ServiceConfig) error { - ps, err := serviceparser.Parse(c.project, svc) + return c.project.ForEachService(services, func(names string, svc *types.ServiceConfig) error { + ps, err := serviceparser.Parse(c.project, *svc) if err != nil { return err } diff --git a/pkg/composer/composer.go b/pkg/composer/composer.go index 2ebadc4407e..16f97efcc93 100644 --- a/pkg/composer/composer.go +++ b/pkg/composer/composer.go @@ -23,8 +23,8 @@ import ( "fmt" "os/exec" - composecli "github.com/compose-spec/compose-go/cli" - compose "github.com/compose-spec/compose-go/types" + composecli "github.com/compose-spec/compose-go/v2/cli" + compose "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/containerd" "github.com/containerd/containerd/identifiers" "github.com/containerd/log" @@ -79,6 +79,7 @@ func New(o Options, client *containerd.Client) (*Composer, error) { optionsFn = append(optionsFn, composecli.WithConfigFileEnv, composecli.WithDefaultConfigPath, + composecli.WithEnvFiles(), composecli.WithDotEnv, composecli.WithName(o.Project), ) @@ -87,7 +88,7 @@ func New(o Options, client *containerd.Client) (*Composer, error) { if err != nil { return nil, err } - project, err := composecli.ProjectFromOptions(projectOptions) + project, err := projectOptions.LoadProject(context.TODO()) if err != nil { return nil, err } @@ -99,7 +100,11 @@ func New(o Options, client *containerd.Client) (*Composer, error) { } o.Profiles = append(o.Profiles, s.GetProfiles()...) } - project.ApplyProfiles(o.Profiles) + + project, err = project.WithProfiles(o.Profiles) + if err != nil { + return nil, err + } if o.DebugPrintFull { projectJSON, _ := json.MarshalIndent(project, "", " ") @@ -153,8 +158,9 @@ func (c *Composer) runNerdctlCmd(ctx context.Context, args ...string) error { // Services returns the parsed Service objects in dependency order. func (c *Composer) Services(ctx context.Context, svcs ...string) ([]*serviceparser.Service, error) { var services []*serviceparser.Service - if err := c.project.WithServices(svcs, func(svc compose.ServiceConfig) error { - parsed, err := serviceparser.Parse(c.project, svc) + + if err := c.project.ForEachService(svcs, func(name string, svc *compose.ServiceConfig) error { + parsed, err := serviceparser.Parse(c.project, *svc) if err != nil { return err } @@ -169,7 +175,7 @@ func (c *Composer) Services(ctx context.Context, svcs ...string) ([]*servicepars // ServiceNames returns service names in dependency order. func (c *Composer) ServiceNames(svcs ...string) ([]string, error) { var names []string - if err := c.project.WithServices(svcs, func(svc compose.ServiceConfig) error { + if err := c.project.ForEachService(svcs, func(name string, svc *compose.ServiceConfig) error { names = append(names, svc.Name) return nil }); err != nil { diff --git a/pkg/composer/config.go b/pkg/composer/config.go index 24aa5eb845c..41a5320daf8 100644 --- a/pkg/composer/config.go +++ b/pkg/composer/config.go @@ -30,7 +30,7 @@ import ( "io" "strings" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/opencontainers/go-digest" "gopkg.in/yaml.v3" ) @@ -59,13 +59,13 @@ func (c *Composer) Config(ctx context.Context, w io.Writer, co ConfigOptions) er if co.Hash != "*" { services = strings.Split(co.Hash, ",") } - return c.project.WithServices(services, func(svc types.ServiceConfig) error { - hash, err := ServiceHash(svc) + return c.project.ForEachService(services, func(names string, svc *types.ServiceConfig) error { + hash, err := ServiceHash(*svc) if err != nil { return err } - fmt.Fprintf(w, "%s %s\n", svc.Name, hash) - return nil + _, err = fmt.Fprintf(w, "%s %s\n", svc.Name, hash) + return err }) } projectYAML, err := yaml.Marshal(c.project) @@ -81,7 +81,8 @@ func ServiceHash(o types.ServiceConfig) (string, error) { // remove the Build config when generating the service hash o.Build = nil o.PullPolicy = "" - o.Scale = 1 + o.Scale = new(int) + *(o.Scale) = 1 bytes, err := json.Marshal(o) if err != nil { return "", err diff --git a/pkg/composer/create.go b/pkg/composer/create.go index 97112f27744..f08ee0b50f3 100644 --- a/pkg/composer/create.go +++ b/pkg/composer/create.go @@ -23,7 +23,7 @@ import ( "path/filepath" "strings" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" diff --git a/pkg/composer/down.go b/pkg/composer/down.go index 3ea0221d209..70d1041365a 100644 --- a/pkg/composer/down.go +++ b/pkg/composer/down.go @@ -86,7 +86,7 @@ func (c *Composer) downNetwork(ctx context.Context, shortName string) error { if !ok { return fmt.Errorf("invalid network name %q", shortName) } - if net.External.External { + if net.External { // NOP return nil } @@ -117,7 +117,7 @@ func (c *Composer) downVolume(ctx context.Context, shortName string) error { if !ok { return fmt.Errorf("invalid volume name %q", shortName) } - if vol.External.External { + if vol.External { // NOP return nil } diff --git a/pkg/composer/logs.go b/pkg/composer/logs.go index d9c0cb93a00..f1493004d3a 100644 --- a/pkg/composer/logs.go +++ b/pkg/composer/logs.go @@ -24,7 +24,7 @@ import ( "os/signal" "strings" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/containerd" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/pipetagger" @@ -43,7 +43,7 @@ type LogsOptions struct { func (c *Composer) Logs(ctx context.Context, lo LogsOptions, services []string) error { var serviceNames []string - err := c.project.WithServices(services, func(svc types.ServiceConfig) error { + err := c.project.ForEachService(services, func(name string, svc *types.ServiceConfig) error { serviceNames = append(serviceNames, svc.Name) return nil }, types.IgnoreDependencies) diff --git a/pkg/composer/projectloader/projectloader.go b/pkg/composer/projectloader/projectloader.go index ef979c0d69b..680eb2842d6 100644 --- a/pkg/composer/projectloader/projectloader.go +++ b/pkg/composer/projectloader/projectloader.go @@ -17,11 +17,12 @@ package projectloader import ( + "context" "os" "path/filepath" - "github.com/compose-spec/compose-go/loader" - compose "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/loader" + compose "github.com/compose-spec/compose-go/v2/types" ) // Load is used only for unit testing. @@ -41,7 +42,7 @@ func Load(fileName, projectName string, envMap map[string]string) (*compose.Proj } var files []compose.ConfigFile files = append(files, compose.ConfigFile{Filename: fileName, Content: b}) - return loader.Load(compose.ConfigDetails{ + return loader.LoadWithContext(context.TODO(), compose.ConfigDetails{ WorkingDir: wd, ConfigFiles: files, Environment: envMap, diff --git a/pkg/composer/pull.go b/pkg/composer/pull.go index 1036df783ba..1ada8cadddf 100644 --- a/pkg/composer/pull.go +++ b/pkg/composer/pull.go @@ -21,7 +21,7 @@ import ( "fmt" "os" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" ) @@ -31,8 +31,8 @@ type PullOptions struct { } func (c *Composer) Pull(ctx context.Context, po PullOptions, services []string) error { - return c.project.WithServices(services, func(svc types.ServiceConfig) error { - ps, err := serviceparser.Parse(c.project, svc) + return c.project.ForEachService(services, func(name string, svc *types.ServiceConfig) error { + ps, err := serviceparser.Parse(c.project, *svc) if err != nil { return err } diff --git a/pkg/composer/push.go b/pkg/composer/push.go index ae8f580a6bb..b9bc9a04336 100644 --- a/pkg/composer/push.go +++ b/pkg/composer/push.go @@ -21,7 +21,7 @@ import ( "fmt" "os" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" ) @@ -30,8 +30,8 @@ type PushOptions struct { } func (c *Composer) Push(ctx context.Context, po PushOptions, services []string) error { - return c.project.WithServices(services, func(svc types.ServiceConfig) error { - ps, err := serviceparser.Parse(c.project, svc) + return c.project.ForEachService(services, func(name string, svc *types.ServiceConfig) error { + ps, err := serviceparser.Parse(c.project, *svc) if err != nil { return err } diff --git a/pkg/composer/restart.go b/pkg/composer/restart.go index a2d430b3603..7768bb5e20d 100644 --- a/pkg/composer/restart.go +++ b/pkg/composer/restart.go @@ -21,7 +21,7 @@ import ( "fmt" "sync" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/containerd" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/labels" @@ -36,7 +36,7 @@ type RestartOptions struct { // `nerdctl restart CONTAINER_ID` to do the actual job. func (c *Composer) Restart(ctx context.Context, opt RestartOptions, services []string) error { // in dependency order - return c.project.WithServices(services, func(svc types.ServiceConfig) error { + return c.project.ForEachService(services, func(name string, svc *types.ServiceConfig) error { containers, err := c.Containers(ctx, svc.Name) if err != nil { return err diff --git a/pkg/composer/run.go b/pkg/composer/run.go index 58c8fc13727..c7e73df9cb0 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -22,8 +22,8 @@ import ( "fmt" "sync" - "github.com/compose-spec/compose-go/loader" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/format" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/idgen" @@ -93,8 +93,8 @@ func (c *Composer) Run(ctx context.Context, ro RunOptions) error { } svcs = append(svcs, svc) } else { - if err := c.project.WithServices([]string{ro.ServiceName}, func(svc types.ServiceConfig) error { - svcs = append(svcs, svc) + if err := c.project.ForEachService([]string{ro.ServiceName}, func(name string, svc *types.ServiceConfig) error { + svcs = append(svcs, *svc) return nil }); err != nil { return err @@ -128,7 +128,7 @@ func (c *Composer) Run(ctx context.Context, ro RunOptions) error { } if ro.Volume != nil && len(ro.Volume) > 0 { for _, v := range ro.Volume { - vc, err := loader.ParseVolume(v) + vc, err := format.ParseVolume(v) if err != nil { return err } diff --git a/pkg/composer/serviceparser/build.go b/pkg/composer/serviceparser/build.go index ed0046a95ed..48bd5f88e30 100644 --- a/pkg/composer/serviceparser/build.go +++ b/pkg/composer/serviceparser/build.go @@ -22,7 +22,7 @@ import ( "path/filepath" "strings" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" "github.com/containerd/log" diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index 05c829d4212..b84fac42ede 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -28,7 +28,7 @@ import ( "strings" "time" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/containerd/contrib/nvidia" "github.com/containerd/containerd/identifiers" "github.com/containerd/log" @@ -213,7 +213,7 @@ func getReplicas(svc types.ServiceConfig) (int, error) { // https://github.com/compose-spec/compose-go/commit/958cb4f953330a3d1303961796d826b7f79132d7 if svc.Deploy != nil && svc.Deploy.Replicas != nil { - replicas = int(*svc.Deploy.Replicas) + replicas = int(*svc.Deploy.Replicas) // nolint:unconvert } if replicas < 0 { @@ -229,11 +229,11 @@ func getCPULimit(svc types.ServiceConfig) (string, error) { limit = fmt.Sprintf("%f", svc.CPUS) } if svc.Deploy != nil && svc.Deploy.Resources.Limits != nil { - if nanoCPUs := svc.Deploy.Resources.Limits.NanoCPUs; nanoCPUs != "" { + if nanoCPUs := svc.Deploy.Resources.Limits.NanoCPUs; nanoCPUs != 0 { if svc.CPUS > 0 { log.L.Warnf("deploy.resources.limits.cpus and cpus (deprecated) must not be set together, ignoring cpus=%f", svc.CPUS) } - limit = nanoCPUs + limit = strconv.FormatFloat(float64(nanoCPUs), 'f', 2, 32) } } return limit, nil @@ -538,7 +538,9 @@ func newContainer(project *types.Project, parsed *Service, i int) (*Container, e } } for k, v := range svc.ExtraHosts { - c.RunArgs = append(c.RunArgs, fmt.Sprintf("--add-host=%s:%s", k, v)) + for _, h := range v { + c.RunArgs = append(c.RunArgs, fmt.Sprintf("--add-host=%s:%s", k, h)) + } } if svc.Init != nil && *svc.Init { diff --git a/pkg/composer/serviceparser/serviceparser_test.go b/pkg/composer/serviceparser/serviceparser_test.go index ca363e7c49b..b3aa2008f99 100644 --- a/pkg/composer/serviceparser/serviceparser_test.go +++ b/pkg/composer/serviceparser/serviceparser_test.go @@ -23,7 +23,7 @@ import ( "strconv" "testing" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/nerdctl/v2/pkg/composer/projectloader" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/testutil" @@ -202,7 +202,7 @@ func TestParseDeprecated(t *testing.T) { services: foo: image: nginx:alpine - # scale is deprecated in favor of deploy.replicas, but still valid + # scale was deprecated in favor of deploy.replicas, and is now ignored scale: 2 # cpus is deprecated in favor of deploy.resources.limits.cpu, but still valid cpus: 0.42 @@ -222,7 +222,7 @@ services: assert.NilError(t, err) t.Logf("foo: %+v", foo) - assert.Assert(t, len(foo.Containers) == 2) + assert.Assert(t, len(foo.Containers) == 1) for i, c := range foo.Containers { assert.Assert(t, c.Name == DefaultContainerName(project.Name, "foo", strconv.Itoa(i+1))) assert.Assert(t, in(c.RunArgs, "--name="+c.Name)) diff --git a/pkg/composer/up.go b/pkg/composer/up.go index 4b6fc48a844..fe6bd6a5081 100644 --- a/pkg/composer/up.go +++ b/pkg/composer/up.go @@ -21,7 +21,7 @@ import ( "fmt" "os" - "github.com/compose-spec/compose-go/types" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/reflectutil" @@ -37,7 +37,7 @@ type UpOptions struct { IPFS bool QuietPull bool RemoveOrphans bool - Scale map[string]uint64 // map of service name to replicas + Scale map[string]int // map of service name to replicas } func (c *Composer) Up(ctx context.Context, uo UpOptions, services []string) error { @@ -69,14 +69,14 @@ func (c *Composer) Up(ctx context.Context, uo UpOptions, services []string) erro var parsedServices []*serviceparser.Service // use WithServices to sort the services in dependency order - if err := c.project.WithServices(services, func(svc types.ServiceConfig) error { + if err := c.project.ForEachService(services, func(name string, svc *types.ServiceConfig) error { if replicas, ok := uo.Scale[svc.Name]; ok { if svc.Deploy == nil { svc.Deploy = &types.DeployConfig{} } svc.Deploy.Replicas = &replicas } - ps, err := serviceparser.Parse(c.project, svc) + ps, err := serviceparser.Parse(c.project, *svc) if err != nil { return err } @@ -109,9 +109,7 @@ func validateFileObjectConfig(obj types.FileObjectConfig, shortName, objType str if unknown := reflectutil.UnknownNonEmptyFields(&obj, "Name", "External", "File"); len(unknown) > 0 { log.L.Warnf("Ignoring: %s %s: %+v", objType, shortName, unknown) } - if obj.External.External || obj.External.Name != "" { - return fmt.Errorf("%s %q: external object is not supported", objType, shortName) - } + if obj.File == "" { return fmt.Errorf("%s %q: lacks file path", objType, shortName) } diff --git a/pkg/composer/up_network.go b/pkg/composer/up_network.go index 65ffdd7dd1d..25f86593b8d 100644 --- a/pkg/composer/up_network.go +++ b/pkg/composer/up_network.go @@ -30,7 +30,7 @@ func (c *Composer) upNetwork(ctx context.Context, shortName string) error { if !ok { return fmt.Errorf("invalid network name %q", shortName) } - if net.External.External { + if net.External { // NOP return nil } diff --git a/pkg/composer/up_volume.go b/pkg/composer/up_volume.go index 11f0417b5dc..436c85c51c5 100644 --- a/pkg/composer/up_volume.go +++ b/pkg/composer/up_volume.go @@ -30,7 +30,7 @@ func (c *Composer) upVolume(ctx context.Context, shortName string) error { if !ok { return fmt.Errorf("invalid volume name %q", shortName) } - if vol.External.External { + if vol.External { // NOP return nil } From a28dbf29258dd001099d46e7f4be96ebb84a8f24 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 14:54:11 +0900 Subject: [PATCH 0520/1066] Dockerfile: use Go 1.22 for runc Signed-off-by: Akihiro Suda --- Dockerfile | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/Dockerfile b/Dockerfile index d0a9a16536c..5a8f8193b5e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,18 +65,6 @@ ARG TARGETARCH RUN xx-apt-get update && \ xx-apt-get install -y binutils gcc libc6-dev libbtrfs-dev libseccomp-dev -# runc still requires Go 1.21 -# https://github.com/opencontainers/runc/issues/4233 -FROM --platform=$BUILDPLATFORM golang:1.21-bullseye AS build-base-debian-go121 -COPY --from=xx / / -ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && \ - apt-get install -y git pkg-config dpkg-dev -ARG TARGETARCH -# libseccomp: for runc -RUN xx-apt-get update && \ - xx-apt-get install -y binutils gcc libc6-dev libseccomp-dev - FROM build-base-debian AS build-containerd ARG TARGETARCH ARG CONTAINERD_VERSION @@ -88,9 +76,7 @@ RUN git checkout ${CONTAINERD_VERSION} && \ RUN GO=xx-go make STATIC=1 && \ cp -a bin/containerd bin/containerd-shim-runc-v2 bin/ctr /out/$TARGETARCH -# runc still requires Go 1.21 -# https://github.com/opencontainers/runc/issues/4233 -FROM build-base-debian-go121 AS build-runc +FROM build-base-debian AS build-runc ARG RUNC_VERSION ARG TARGETARCH RUN git clone https://github.com/opencontainers/runc.git /go/src/github.com/opencontainers/runc From ead5ce6c8a6a8b6636659780747f0bbceaa641fd Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 19 Jun 2024 20:48:13 -0700 Subject: [PATCH 0521/1066] Volume QA: remove (fixes and tests) Signed-off-by: apostasie --- cmd/nerdctl/volume_remove_linux_test.go | 189 +++++++++++++++++- pkg/cmd/container/remove.go | 2 +- pkg/cmd/volume/prune.go | 2 +- pkg/cmd/volume/rm.go | 21 +- .../mountutilmock/volumestore.mock.go | 4 +- pkg/mountutil/volumestore/volumestore.go | 26 ++- 6 files changed, 217 insertions(+), 27 deletions(-) diff --git a/cmd/nerdctl/volume_remove_linux_test.go b/cmd/nerdctl/volume_remove_linux_test.go index 35a478e530e..6023381c782 100644 --- a/cmd/nerdctl/volume_remove_linux_test.go +++ b/cmd/nerdctl/volume_remove_linux_test.go @@ -21,18 +21,193 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "gotest.tools/v3/icmd" ) func TestVolumeRemove(t *testing.T) { t.Parallel() + base := testutil.NewBase(t) - tID := testutil.Identifier(t) - base.Cmd("volume", "create", tID).AssertOK() - base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID), "--name", tID, testutil.CommonImage).AssertOK() - defer base.Cmd("rm", "-f", tID).Run() + malformed := "malformed volume name" + notFound := "no such volume" + requireArg := "requires at least 1 arg" + inUse := "is in use" + if base.Target == testutil.Docker { + malformed = "no such volume" + } + + testCases := []struct { + description string + command func(tID string) *testutil.Cmd + tearUp func(tID string) + tearDown func(tID string) + expected func(tID string) icmd.Expected + }{ + { + description: "arg missing", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "rm") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: requireArg, + } + }, + }, + { + description: "invalid identifier", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "rm", "∞") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: malformed, + } + }, + }, + { + description: "non existent volume", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "rm", "doesnotexist") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: notFound, + } + }, + }, + { + description: "busy volume", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "rm", tID) + }, + tearUp: func(tID string) { + base.Cmd("volume", "create", tID).AssertOK() + base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID), "--name", tID, testutil.CommonImage).AssertOK() + }, + tearDown: func(tID string) { + base.Cmd("rm", "-f", tID).Run() + base.Cmd("volume", "rm", "-f", tID).Run() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: inUse, + } + + }, + }, + { + description: "freed volume", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "rm", tID) + }, + tearUp: func(tID string) { + base.Cmd("volume", "create", tID).AssertOK() + base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID), "--name", tID, testutil.CommonImage).AssertOK() + base.Cmd("rm", "-f", tID).AssertOK() + }, + tearDown: func(tID string) { + base.Cmd("rm", "-f", tID).Run() + base.Cmd("volume", "rm", "-f", tID).Run() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + Out: tID, + } + }, + }, + { + description: "dangling volume", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "rm", tID) + }, + tearUp: func(tID string) { + base.Cmd("volume", "create", tID).AssertOK() + }, + tearDown: func(tID string) { + base.Cmd("volume", "rm", "-f", tID).Run() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + Out: tID, + } + }, + }, + { + "part success multi remove", + func(tID string) *testutil.Cmd { + return base.Cmd("volume", "rm", "invalid∞", "nonexistent", tID) + }, + func(tID string) { + base.Cmd("volume", "create", tID).AssertOK() + }, + func(tID string) { + base.Cmd("volume", "rm", "-f", tID).Run() + }, + func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Out: tID, + Err: notFound, + } + }, + }, + { + description: "success multi-remove", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "rm", tID+"-1", tID+"-2") + }, + tearUp: func(tID string) { + base.Cmd("volume", "create", tID+"-1").AssertOK() + base.Cmd("volume", "create", tID+"-2").AssertOK() + }, + tearDown: func(tID string) { + base.Cmd("volume", "rm", "-f", tID+"-1", tID+"-2").Run() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + Out: tID + "-1\n" + tID + "-2", + } + }, + }, + { + description: "failing multi-remove", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "rm", "nonexist1", "nonexist2") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: notFound, + } + }, + }, + } + + for _, test := range testCases { + currentTest := test + t.Run(currentTest.description, func(tt *testing.T) { + tt.Parallel() + + tID := testutil.Identifier(tt) + + if currentTest.tearDown != nil { + currentTest.tearDown(tID) + tt.Cleanup(func() { + currentTest.tearDown(tID) + }) + } + if currentTest.tearUp != nil { + currentTest.tearUp(tID) + } - base.Cmd("volume", "rm", tID).AssertFail() - base.Cmd("rm", "-f", tID).AssertOK() - base.Cmd("volume", "rm", tID).AssertOK() + cmd := currentTest.command(tID) + cmd.Assert(currentTest.expected(tID)) + }) + } } diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 04c022e719b..b6fb87c93bb 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -157,7 +157,7 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions return err } defer func() { - if _, err := volStore.Remove(anonVolumes); err != nil { + if _, errs, err := volStore.Remove(anonVolumes); err != nil || len(errs) > 0 { log.G(ctx).WithError(err).Warnf("failed to remove anonymous volumes %v", anonVolumes) } }() diff --git a/pkg/cmd/volume/prune.go b/pkg/cmd/volume/prune.go index d8161be8bfa..f9dff99f428 100644 --- a/pkg/cmd/volume/prune.go +++ b/pkg/cmd/volume/prune.go @@ -57,7 +57,7 @@ func Prune(ctx context.Context, client *containerd.Client, options types.VolumeP } removeNames = append(removeNames, volume.Name) } - removedNames, err := volStore.Remove(removeNames) + removedNames, _, err := volStore.Remove(removeNames) if err != nil { return err } diff --git a/pkg/cmd/volume/rm.go b/pkg/cmd/volume/rm.go index e25a3ff19a8..509957bb978 100644 --- a/pkg/cmd/volume/rm.go +++ b/pkg/cmd/volume/rm.go @@ -19,9 +19,11 @@ package volume import ( "context" "encoding/json" + "errors" "fmt" "github.com/containerd/containerd" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/labels" @@ -44,23 +46,28 @@ func Remove(ctx context.Context, client *containerd.Client, volumes []string, op var volumenames []string // nolint: prealloc for _, name := range volumes { - volume, err := volStore.Get(name, false) - if err != nil { - return err - } - if _, ok := usedVolumes[volume.Name]; ok { + if _, ok := usedVolumes[name]; ok { return fmt.Errorf("volume %q is in use", name) } volumenames = append(volumenames, name) } - removedNames, err := volStore.Remove(volumenames) + // if err is set, this is a hard filesystem error + removedNames, warns, err := volStore.Remove(volumenames) if err != nil { return err } + // Otherwise, output on stdout whatever was successful for _, name := range removedNames { fmt.Fprintln(options.Stdout, name) } - return err + // Log the rest + for _, volErr := range warns { + log.G(ctx).Warn(volErr) + } + if len(warns) > 0 { + return errors.New("some volumes could not be removed") + } + return nil } func usedVolumes(ctx context.Context, containers []containerd.Container) (map[string]struct{}, error) { diff --git a/pkg/mountutil/mountutilmock/volumestore.mock.go b/pkg/mountutil/mountutilmock/volumestore.mock.go index b5c933cd125..efed1cfc219 100644 --- a/pkg/mountutil/mountutilmock/volumestore.mock.go +++ b/pkg/mountutil/mountutilmock/volumestore.mock.go @@ -92,12 +92,12 @@ func (m *MockVolumeStoreMockRecorder) List(size any) *gomock.Call { } // Remove mocks the Remove method of VolumeStore -func (m *MockVolumeStore) Remove(names []string) ([]string, error) { +func (m *MockVolumeStore) Remove(names []string) (removed []string, warns []error, err error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Remove", names) ret0, _ := ret[0].([]string) ret1, _ := ret[1].(error) - return ret0, ret1 + return ret0, []error{}, ret1 } // Remove indicates an expected call of Remove diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index 430791223be..8093212a7b7 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -18,6 +18,7 @@ package volumestore import ( "encoding/json" + "errors" "fmt" "os" "path/filepath" @@ -65,7 +66,7 @@ type VolumeStore interface { // Get may return ErrNotFound Get(name string, size bool) (*native.Volume, error) List(size bool) (map[string]native.Volume, error) - Remove(names []string) (removedNames []string, err error) + Remove(names []string) (removed []string, warns []error, err error) } type volumeStore struct { @@ -80,7 +81,7 @@ func (vs *volumeStore) Dir() string { func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, error) { if err := identifiers.Validate(name); err != nil { - return nil, fmt.Errorf("malformed name %s: %w", name, err) + return nil, fmt.Errorf("malformed volume name: %w", err) } volPath := filepath.Join(vs.dir, name) volDataPath := filepath.Join(volPath, DataDirName) @@ -131,12 +132,11 @@ func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, err return os.WriteFile(volFilePath, labelsJSON, 0644) } - if err := lockutil.WithDirLock(vs.dir, fn); err != nil { + if err := lockutil.WithDirLock(vs.dir, fn); err != nil && !errors.Is(err, os.ErrExist) { return nil, err } // If other new actions that might fail are added below, we should move the cleanup function out of fn. - vol := &native.Volume{ Name: name, Mountpoint: volDataPath, @@ -196,14 +196,19 @@ func (vs *volumeStore) List(size bool) (map[string]native.Volume, error) { return res, nil } -func (vs *volumeStore) Remove(names []string) ([]string, error) { - var removed []string +func (vs *volumeStore) Remove(names []string) (removed []string, warns []error, err error) { fn := func() error { for _, name := range names { if err := identifiers.Validate(name); err != nil { - return fmt.Errorf("malformed name %s: %w", name, err) + warns = append(warns, fmt.Errorf("malformed volume name: %w", err)) + continue } dir := filepath.Join(vs.dir, name) + if _, err := os.Stat(dir); os.IsNotExist(err) { + warns = append(warns, fmt.Errorf("no such volume: %s", name)) + continue + } + // This is a hard filesystem error. Exit on this. if err := os.RemoveAll(dir); err != nil { return err } @@ -211,8 +216,11 @@ func (vs *volumeStore) Remove(names []string) ([]string, error) { } return nil } - err := lockutil.WithDirLock(vs.dir, fn) - return removed, err + + if err := lockutil.WithDirLock(vs.dir, fn); err != nil { + return nil, nil, err + } + return removed, warns, nil } func Labels(b []byte) *map[string]string { From bccfdc825b1e6f340b60b9d639ce2c6e6e9307f4 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 14:56:00 +0900 Subject: [PATCH 0522/1066] update containerd (2.0.0-rc.3) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 6 +++--- Dockerfile | 2 +- hack/generate-release-note.sh | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1258aaa0a52..b7525d62e15 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -85,7 +85,7 @@ jobs: - ubuntu: 22.04 containerd: v1.7.18 - ubuntu: 22.04 - containerd: main + containerd: main # v2.0.0-rc.X env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -181,7 +181,7 @@ jobs: rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 - containerd: main + containerd: main # v2.0.0-rc.X rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 20.04 @@ -197,7 +197,7 @@ jobs: rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 22.04 - containerd: main + containerd: main # v2.0.0-rc.X rootlesskit: v2.1.0 target: test-integration-rootless-port-slirp4netns env: diff --git a/Dockerfile b/Dockerfile index 5a8f8193b5e..f4ef8b0a07a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v1.7.18 +ARG CONTAINERD_VERSION=v2.0.0-rc.3 ARG RUNC_VERSION=v1.1.13 ARG CNI_PLUGINS_VERSION=v1.5.0 diff --git a/hack/generate-release-note.sh b/hack/generate-release-note.sh index 877853566e5..87ce76b3f55 100755 --- a/hack/generate-release-note.sh +++ b/hack/generate-release-note.sh @@ -25,7 +25,7 @@ cat <<-EOX (To be documented) ## Compatible containerd versions -This release of nerdctl is expected to be used with containerd v1.6 or v1.7. +This release of nerdctl is expected to be used with containerd v1.6, v1.7, or v2.0. ## About the binaries - Minimal (\`${minimal_amd64tgz_basename}\`): nerdctl only From 465365a0f8375bd64670b77f60b7f2502de62710 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 14:58:50 +0900 Subject: [PATCH 0523/1066] update CNI plugins (1.5.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.0 | 2 -- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.1 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.1 diff --git a/Dockerfile b/Dockerfile index f4ef8b0a07a..4d2b3fb1426 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ # Basic deps ARG CONTAINERD_VERSION=v2.0.0-rc.3 ARG RUNC_VERSION=v1.1.13 -ARG CNI_PLUGINS_VERSION=v1.5.0 +ARG CNI_PLUGINS_VERSION=v1.5.1 # Extra deps: Build ARG BUILDKIT_VERSION=v0.13.2 diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.0 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.0 deleted file mode 100644 index 729e73a90fb..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.0 +++ /dev/null @@ -1,2 +0,0 @@ -57a18478422cb321370e30a5ee6ce026321289cd9c94353ca697dddd7714f1a5 cni-plugins-linux-amd64-v1.5.0.tgz -ab38507efe50c34bc2242a25c5783c19fdfe0376c65a2a91d48174d4f39f1fc2 cni-plugins-linux-arm64-v1.5.0.tgz 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 From 85a8bf86bb272a8cc5a7d5b2af20f6716c825637 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 14:59:53 +0900 Subject: [PATCH 0524/1066] update BuildKit (0.14.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.2 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.14.1 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.2 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.14.1 diff --git a/Dockerfile b/Dockerfile index 4d2b3fb1426..889824fd8cc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.13 ARG CNI_PLUGINS_VERSION=v1.5.1 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.13.2 +ARG BUILDKIT_VERSION=v0.14.1 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.2 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.2 deleted file mode 100644 index cd252075f04..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.13.2 +++ /dev/null @@ -1,2 +0,0 @@ -9cd121931b015f05d7e4337f08272e36a83f69724c40141947eb11246ca0bb9d buildkit-v0.13.2.linux-amd64.tar.gz -bcc4cb4fec79847682fbb2ce8f612e5e854636ae6c262cee4b657d2b5c2fd46c buildkit-v0.13.2.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.14.1 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.14.1 new file mode 100644 index 00000000000..e059cbf6e7a --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.14.1 @@ -0,0 +1,2 @@ +836208f50ab8856a91aa5bba455b8451bbe261318cbc92e9c0ca3e786135756c buildkit-v0.14.1.linux-amd64.tar.gz +e1caad39f0bc5848a5687d7a0e8e344d20724133365596e5d881d8fbe5594b32 buildkit-v0.14.1.linux-arm64.tar.gz From f35e4251afbc73a1437738240f1e8b2b6e3b88fc Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 15:09:23 +0900 Subject: [PATCH 0525/1066] update golangci-lint (1.59.1) Fix: > Error: pkg/cmd/container/stats.go:84:60: var-naming: func parameter containerIds should be containerIDs (revive) > func Stats(ctx context.Context, client *containerd.Client, containerIds []string, options types.ContainerStatsOptions) error { > ^ > Error: cmd/nerdctl/image_inspect_test.go:79:2: var-naming: var allIds should be allIDs (revive) > allIds := strings.Split(ids, "\n") > ^ Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 2 +- cmd/nerdctl/image_inspect_test.go | 4 ++-- pkg/cmd/container/stats.go | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1258aaa0a52..0a3cc21fe07 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -50,7 +50,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v6.0.1 with: - version: v1.55.2 + version: v1.59.1 args: --verbose - name: yamllint-lint run: yamllint . diff --git a/cmd/nerdctl/image_inspect_test.go b/cmd/nerdctl/image_inspect_test.go index dd28da16df8..4b54c6bbb13 100644 --- a/cmd/nerdctl/image_inspect_test.go +++ b/cmd/nerdctl/image_inspect_test.go @@ -76,8 +76,8 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { // More specifically, because we trigger https://github.com/containerd/nerdctl/issues/3016 // we cannot do selective rmi, so, just nuke everything ids := base.Cmd("image", "list", "-q").Out() - allIds := strings.Split(ids, "\n") - for _, id := range allIds { + allIDs := strings.Split(ids, "\n") + for _, id := range allIDs { id = strings.TrimSpace(id) if id != "" { base.Cmd("rmi", "-f", id).Run() diff --git a/pkg/cmd/container/stats.go b/pkg/cmd/container/stats.go index 537e6a54193..c81165a4773 100644 --- a/pkg/cmd/container/stats.go +++ b/pkg/cmd/container/stats.go @@ -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 } From f16b79c287d3813af5bd79b3aa9941cb55287225 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 15:22:07 +0900 Subject: [PATCH 0526/1066] CI: cross: do not use Go 1.21 for nerdctl-full deps The latest kubo is no longer compilable with Go 1.21 Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b7525d62e15..1577cd91c99 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -237,7 +237,7 @@ jobs: cache: true check-latest: true - name: "Cross" - run: GO_VERSION="$(echo ${{ matrix.go-version }} | sed -e s/.x//)" make artifacts + run: GO_VERSION="$(echo ${{ matrix.go-version }} | sed -e s/.x//)" make binaries test-integration-docker-compatibility: runs-on: ubuntu-22.04 From 6cc63162edd98bbd48ef84a0036fce972d3979b5 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 15:01:46 +0900 Subject: [PATCH 0527/1066] update Kubo (0.29.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 889824fd8cc..07a7d3d3ad8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ ARG BYPASS4NETNS_VERSION=v0.4.1 ARG FUSE_OVERLAYFS_VERSION=v1.13 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 # Extra deps: IPFS -ARG KUBO_VERSION=v0.27.0 +ARG KUBO_VERSION=v0.29.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug From 480fc999d338ba269d19f19f38bde9082dff4321 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 15:03:55 +0900 Subject: [PATCH 0528/1066] update gotestsum (1.12.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 07a7d3d3ad8..73ac059d37e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ ARG BUILDG_VERSION=v0.4.1 ARG GO_VERSION=1.22 ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 -ARG GOTESTSUM_VERSION=v1.11.0 +ARG GOTESTSUM_VERSION=v1.12.0 ARG NYDUS_VERSION=v2.2.4 ARG SOCI_SNAPSHOTTER_VERSION=0.4.0 From 820f74047d931dc8345056dc6c2fd4feaada8b0d Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 15:04:41 +0900 Subject: [PATCH 0529/1066] update Nydus (2.2.5) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 73ac059d37e..22a0016a565 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,7 +48,7 @@ ARG GO_VERSION=1.22 ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.12.0 -ARG NYDUS_VERSION=v2.2.4 +ARG NYDUS_VERSION=v2.2.5 ARG SOCI_SNAPSHOTTER_VERSION=0.4.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.4.0 AS xx From c2fa1ed915b0df5bfc4daaf5e3f0d40814c1a2fd Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 15:05:02 +0900 Subject: [PATCH 0530/1066] update soci-snapshotter (0.6.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 22a0016a565..81da164d935 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,7 +49,7 @@ ARG UBUNTU_VERSION=22.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.12.0 ARG NYDUS_VERSION=v2.2.5 -ARG SOCI_SNAPSHOTTER_VERSION=0.4.0 +ARG SOCI_SNAPSHOTTER_VERSION=0.6.1 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.4.0 AS xx From 02d5329af550091986f7aa78a8fdd94015146ce8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Jun 2024 22:37:40 +0000 Subject: [PATCH 0531/1066] build(deps): bump docker/build-push-action from 6.0.1 to 6.0.2 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.0.1 to 6.0.2. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.0.1...v6.0.2) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index a389e4a100f..5f9ea0e1e07 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.0.1 + uses: docker/build-push-action@v6.0.2 with: context: . platforms: linux/amd64,linux/arm64 From 8a5137b0db92956ff994c6e4ecf68eaa70d1726e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Jun 2024 22:49:03 +0000 Subject: [PATCH 0532/1066] build(deps): bump docker/build-push-action from 6.0.2 to 6.1.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.0.2 to 6.1.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.0.2...v6.1.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 5f9ea0e1e07..4fe76a9ce23 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.0.2 + uses: docker/build-push-action@v6.1.0 with: context: . platforms: linux/amd64,linux/arm64 From b997648a847ddcb62d60f52c48c2d23ca7ccc013 Mon Sep 17 00:00:00 2001 From: Anatoli Babenia Date: Sat, 22 Jun 2024 11:00:21 +0300 Subject: [PATCH 0533/1066] Fix check for empty $HOME and $XDG_RUNTIME_DIR If $XDG_RUNTIME_DIR is not set, then [ -w $XDG_RUNTIME_DIR ] passes. Quotes fix the issue. Signed-off-by: Anatoli Babenia --- extras/rootless/containerd-rootless.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/rootless/containerd-rootless.sh b/extras/rootless/containerd-rootless.sh index 4338af510d7..eff0e4241ea 100755 --- a/extras/rootless/containerd-rootless.sh +++ b/extras/rootless/containerd-rootless.sh @@ -49,11 +49,11 @@ # See also: https://github.com/containerd/nerdctl/blob/main/docs/rootless.md#configuring-rootlesskit set -e -if ! [ -w $XDG_RUNTIME_DIR ]; then +if ! [ -w "$XDG_RUNTIME_DIR" ]; then echo "XDG_RUNTIME_DIR needs to be set and writable" exit 1 fi -if ! [ -w $HOME ]; then +if ! [ -w "$HOME" ]; then echo "HOME needs to be set and writable" exit 1 fi From c493afcd13f8c6a6ca7011cdd41d5f843ed34fbb Mon Sep 17 00:00:00 2001 From: David Son Date: Sun, 23 Jun 2024 07:33:23 +0000 Subject: [PATCH 0534/1066] pkg/defaults: add defaults_darwin.go Before this change, people using nerdctl as a library could not build if their dependency tree took pkg/defaults. This adds a dummy file that implements the missing necesssary variables so that it can compile on Mac. Signed-off-by: David Son --- pkg/defaults/defaults_darwin.go | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 pkg/defaults/defaults_darwin.go diff --git a/pkg/defaults/defaults_darwin.go b/pkg/defaults/defaults_darwin.go new file mode 100644 index 00000000000..38db7823db1 --- /dev/null +++ b/pkg/defaults/defaults_darwin.go @@ -0,0 +1,45 @@ +/* + 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. +*/ + +// This is a dummy file to allow usage of library functions +// on Darwin-based systems. +// All functions and variables are empty/no-ops + +package defaults + +func CNIPath() string { + return "" +} + +func CNINetConfPath() string { + return "" +} + +func DataRoot() string { + return "" +} + +func CgroupManager() string { + return "" +} + +func HostsDirs() []string { + return []string{} +} + +func HostGatewayIP() string { + return "" +} From 6c1e9618e5b1ab12b136a7249dd676948f15ff3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 22:07:19 +0000 Subject: [PATCH 0535/1066] build(deps): bump github.com/containernetworking/cni from 1.2.1 to 1.2.2 Bumps [github.com/containernetworking/cni](https://github.com/containernetworking/cni) from 1.2.1 to 1.2.2. - [Release notes](https://github.com/containernetworking/cni/releases) - [Commits](https://github.com/containernetworking/cni/compare/v1.2.1...v1.2.2) --- updated-dependencies: - dependency-name: github.com/containernetworking/cni dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 54ce0ca6fdc..bfd137a49b3 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/containerd/stargz-snapshotter/estargz v0.15.1 github.com/containerd/stargz-snapshotter/ipfs v0.15.1 github.com/containerd/typeurl/v2 v2.1.1 - github.com/containernetworking/cni v1.2.1 + github.com/containernetworking/cni v1.2.2 github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 diff --git a/go.sum b/go.sum index 52bcb6c8c71..ddcc694ba06 100644 --- a/go.sum +++ b/go.sum @@ -64,8 +64,8 @@ github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67 h1:rQvjv7gRi6 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= github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= -github.com/containernetworking/cni v1.2.1 h1:PU9lIBbXNqdPIEuIxWGbtznlecv4Y+ZYqjX/j/2S7ug= -github.com/containernetworking/cni v1.2.1/go.mod h1:m2nkpHY4lRZx89NUXHj4jahE5JCgaJuygB8cSwj0CTU= +github.com/containernetworking/cni v1.2.2 h1:9IbP6KJQQxVKo4hhnm8r50YcVKrJbJu3Dqw+Rbt1vYk= +github.com/containernetworking/cni v1.2.2/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= github.com/containers/ocicrypt v1.1.10 h1:r7UR6o8+lyhkEywetubUUgcKFjOWOaWz8cEBrCPX0ic= From ae277688f170827c4db0a975152d6a9090e86dfe Mon Sep 17 00:00:00 2001 From: CodeChanning Date: Wed, 12 Jun 2024 15:07:32 -0700 Subject: [PATCH 0536/1066] feat: support for --sig-proxy in run Signed-off-by: CodeChanning --- cmd/nerdctl/container_run.go | 11 +++- cmd/nerdctl/container_run_linux_test.go | 75 +++++++++++++++++++++++++ docs/command-reference.md | 3 +- pkg/api/types/container_types.go | 2 + pkg/composer/run.go | 1 + pkg/testutil/testutil.go | 5 ++ pkg/testutil/testutil_linux.go | 19 +++++++ 7 files changed, 113 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 036b1f57da6..9344cd2b2c1 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -79,6 +79,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) { @@ -287,6 +288,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 @@ -394,8 +399,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_linux_test.go b/cmd/nerdctl/container_run_linux_test.go index 63943258677..15b17ab614c 100644 --- a/cmd/nerdctl/container_run_linux_test.go +++ b/cmd/nerdctl/container_run_linux_test.go @@ -29,6 +29,7 @@ import ( "runtime" "strconv" "strings" + "syscall" "testing" "time" @@ -311,6 +312,80 @@ func TestRunTTY(t *testing.T) { assert.Equal(t, 0, res.ExitCode, res.Combined()) } +func runSigProxy(t *testing.T, args ...string) (string, bool, bool) { + t.Parallel() + base := testutil.NewBase(t) + testContainerName := testutil.Identifier(t) + defer base.Cmd("rm", "-f", testContainerName).Run() + + fullArgs := []string{"run"} + fullArgs = append(fullArgs, args...) + fullArgs = append(fullArgs, + "--name", + testContainerName, + testutil.CommonImage, + "sh", + "-c", + testutil.SigProxyTestScript, + ) + + result := base.Cmd(fullArgs...).Start() + process := result.Cmd.Process + + // Waits until we reach the trap command in the shell script, then sends SIGINT. + time.Sleep(3 * time.Second) + syscall.Kill(process.Pid, syscall.SIGINT) + + // Waits until SIGINT is sent and responded to, then kills process to avoid timeout + time.Sleep(3 * time.Second) + process.Kill() + + sigIntRecieved := strings.Contains(result.Stdout(), testutil.SigProxyTrueOut) + timedOut := strings.Contains(result.Stdout(), testutil.SigProxyTimeoutMsg) + + return result.Stdout(), sigIntRecieved, timedOut +} + +func TestRunSigProxy(t *testing.T) { + + type testCase struct { + name string + args []string + want bool + expectedOut string + } + testCases := []testCase{ + { + name: "SigProxyDefault", + args: []string{}, + want: true, + expectedOut: testutil.SigProxyTrueOut, + }, + { + name: "SigProxyTrue", + args: []string{"--sig-proxy=true"}, + want: true, + expectedOut: testutil.SigProxyTrueOut, + }, + { + name: "SigProxyFalse", + args: []string{"--sig-proxy=false"}, + want: false, + expectedOut: "", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + stdout, sigIntRecieved, timedOut := runSigProxy(t, tc.args...) + errorMsg := fmt.Sprintf("%s failed;\nExpected: '%s'\nActual: '%s'", tc.name, tc.expectedOut, stdout) + assert.Equal(t, false, timedOut, errorMsg) + assert.Equal(t, tc.want, sigIntRecieved, errorMsg) + }) + } +} + func TestRunWithFluentdLogDriver(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("fluentd log driver is not yet implemented on Windows") diff --git a/docs/command-reference.md b/docs/command-reference.md index 2540264bc95..7c0c8c3ad76 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -140,6 +140,7 @@ Basic flags: - :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" @@ -388,7 +389,7 @@ IPFS flags: Unimplemented `docker run` flags: `--attach`, `--blkio-weight-device`, `--cpu-rt-*`, `--device-*`, `--disable-content-trust`, `--domainname`, `--expose`, `--health-*`, `--isolation`, `--no-healthcheck`, - `--link*`, `--publish-all`, `--sig-proxy`, `--storage-opt`, + `--link*`, `--publish-all`, `--storage-opt`, `--userns`, `--volume-driver` ### :whale: :blue_square: nerdctl exec diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index 4759eb29678..16fd41301d7 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -62,6 +62,8 @@ 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. diff --git a/pkg/composer/run.go b/pkg/composer/run.go index c7e73df9cb0..d63b388aa01 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 diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 600fdb29ebe..25d315d5781 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -366,6 +366,11 @@ func (c *Cmd) runIfNecessary() *icmd.Result { return c.runResult } +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) diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index 41266be6109..b6573b122a5 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -56,6 +56,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 ( From dd52560fa2ad790869eb9963294f7c9540a93455 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 20 Jun 2024 15:13:14 +0900 Subject: [PATCH 0537/1066] CI: update Ubuntu (24.04) Signed-off-by: Akihiro Suda --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 75 +++++++++++-------- Dockerfile | 4 +- Dockerfile.d/test-integration-rootless.sh | 4 +- pkg/testutil/testutil.go | 7 ++ 6 files changed, 56 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 4fe76a9ce23..103778eb92c 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -25,7 +25,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 50f4bab6650..5cd401df273 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ env: GO111MODULE: on jobs: release: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 40 steps: - uses: actions/checkout@v4.1.7 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3d1e2d58d7c..92ee4c5da91 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ env: jobs: project: name: Project Checks - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v4.1.7 @@ -36,7 +36,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.7 @@ -56,7 +56,7 @@ jobs: run: yamllint . test-unit: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v4.1.7 @@ -76,7 +76,7 @@ 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.33 @@ -85,7 +85,11 @@ jobs: - ubuntu: 22.04 containerd: v1.7.18 - ubuntu: 22.04 - containerd: main # v2.0.0-rc.X + containerd: main # v2.0.0-rc.X + - ubuntu: 24.04 + containerd: v1.7.18 + - ubuntu: 24.04 + containerd: main # v2.0.0-rc.X env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -117,9 +121,9 @@ 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 + - ubuntu: 24.04 containerd: v1.7.18 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" @@ -166,7 +170,7 @@ 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.33 @@ -181,7 +185,15 @@ jobs: rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 - containerd: main # v2.0.0-rc.X + containerd: main # v2.0.0-rc.X + rootlesskit: v2.1.0 + target: test-integration-rootless + - ubuntu: 24.04 + containerd: v1.7.18 + rootlesskit: v1.1.1 + target: test-integration-rootless + - ubuntu: 24.04 + containerd: main # v2.0.0-rc.X rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 20.04 @@ -192,12 +204,12 @@ jobs: containerd: v1.7.18 rootlesskit: v2.1.0 target: test-integration-rootless-port-slirp4netns - - ubuntu: 22.04 + - ubuntu: 24.04 containerd: v1.7.18 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - - ubuntu: 22.04 - containerd: main # v2.0.0-rc.X + - ubuntu: 24.04 + containerd: main # v2.0.0-rc.X rootlesskit: v2.1.0 target: test-integration-rootless-port-slirp4netns env: @@ -206,6 +218,21 @@ jobs: ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" TEST_TARGET: "${{ matrix.target }}" steps: + - 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 @@ -222,7 +249,7 @@ jobs: command: 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: @@ -240,7 +267,7 @@ jobs: run: GO_VERSION="$(echo ${{ matrix.go-version }} | sed -e s/.x//)" make binaries test-integration-docker-compatibility: - runs-on: ubuntu-22.04 + runs-on: ubuntu-22.04 # TODO: ubuntu-24.04 timeout-minutes: 45 steps: - uses: actions/checkout@v4.1.7 @@ -251,26 +278,9 @@ jobs: go-version: ${{ env.GO_VERSION }} cache: true check-latest: true - - name: "Install Docker v26" + - name: "Print docker info" 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/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/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 25d315d5781..d2612271285 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -32,6 +32,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/containerd/containerd/defaults" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/infoutil" @@ -561,6 +562,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 } From 6d97c6e9ed2de53b9b7f50cbd8a2cf0491e2afc3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 22:42:36 +0000 Subject: [PATCH 0538/1066] build(deps): bump github.com/containerd/go-cni from 1.1.9 to 1.1.10 Bumps [github.com/containerd/go-cni](https://github.com/containerd/go-cni) from 1.1.9 to 1.1.10. - [Release notes](https://github.com/containerd/go-cni/releases) - [Commits](https://github.com/containerd/go-cni/compare/v1.1.9...v1.1.10) --- updated-dependencies: - dependency-name: github.com/containerd/go-cni dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bfd137a49b3..1a8bafe16d5 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/containerd/containerd v1.7.18 github.com/containerd/continuity v0.4.3 github.com/containerd/fifo v1.1.0 - github.com/containerd/go-cni v1.1.9 + github.com/containerd/go-cni v1.1.10 github.com/containerd/imgcrypt v1.1.11 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.13.13 diff --git a/go.sum b/go.sum index ddcc694ba06..a22aa0265de 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5Z 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= -github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= +github.com/containerd/go-cni v1.1.10 h1:c2U73nld7spSWfiJwSh/8W9DK+/qQwYM2rngIhCyhyg= +github.com/containerd/go-cni v1.1.10/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0= github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= github.com/containerd/imgcrypt v1.1.11 h1:3RULIeLouE7B5l9NzMq0HdPWG0DP5deEVxB5UKxyUoU= From d56f7a71682e23217955a21073af788d5cbbf80f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jun 2024 22:35:17 +0000 Subject: [PATCH 0539/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.1.4+incompatible to 27.0.2+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v26.1.4...v27.0.2) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1a8bafe16d5..75336422fce 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 github.com/docker/cli v26.1.4+incompatible - github.com/docker/docker v26.1.4+incompatible + github.com/docker/docker v27.0.2+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index a22aa0265de..42bade937bd 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwenxRM7/rLu8= github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= -github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.0.2+incompatible h1:mNhCtgXNV1fIRns102grG7rdzIsGGCq1OlOD0KunZos= +github.com/docker/docker v27.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 2ed85e4f2c022da5d53a6375ea53b0adf8c0154c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jun 2024 22:58:46 +0000 Subject: [PATCH 0540/1066] build(deps): bump docker/build-push-action from 6.1.0 to 6.2.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.1.0 to 6.2.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.1.0...v6.2.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 103778eb92c..1c335b22ea2 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.1.0 + uses: docker/build-push-action@v6.2.0 with: context: . platforms: linux/amd64,linux/arm64 From 3cece1b1f92d73ac682460fc1db42c03f727900b Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Tue, 25 Jun 2024 23:09:14 +0200 Subject: [PATCH 0541/1066] fix missing name container stats Signed-off-by: fahed dorgaa --- pkg/cmd/container/list.go | 22 ++-------------------- pkg/cmd/container/list_util.go | 4 ++-- pkg/cmd/container/stats.go | 10 +++++----- pkg/containerutil/containerutil.go | 19 +++++++++++++++++++ pkg/statsutil/stats.go | 23 +++++++++++++++-------- 5 files changed, 43 insertions(+), 35 deletions(-) diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index c7dc778d5de..c4279ad40d6 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -31,10 +31,10 @@ import ( "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerdutil" + "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" - "github.com/containerd/nerdctl/v2/pkg/labels/k8slabels" ) // List prints containers according to `options`. @@ -138,7 +138,7 @@ func prepareContainers(ctx context.Context, client *containerd.Client, container ID: id, Image: info.Image, Platform: info.Labels[labels.Platform], - Names: getContainerName(info.Labels), + Names: containerutil.GetContainerName(info.Labels), Ports: formatter.FormatPorts(info.Labels), Status: formatter.ContainerStatus(ctx, c), Runtime: info.Runtime.Name, @@ -162,24 +162,6 @@ func prepareContainers(ctx context.Context, client *containerd.Client, container return listItems, nil } -func getContainerName(containerLabels map[string]string) string { - if name, ok := containerLabels[labels.Name]; ok { - return name - } - - if ns, ok := containerLabels[k8slabels.PodNamespace]; ok { - if podName, ok := containerLabels[k8slabels.PodName]; ok { - if containerName, ok := containerLabels[k8slabels.ContainerName]; ok { - // Container - return fmt.Sprintf("k8s://%s/%s/%s", ns, podName, containerName) - } - // Pod sandbox - return fmt.Sprintf("k8s://%s/%s", ns, podName) - } - } - return "" -} - func getContainerNetworks(containerLables map[string]string) []string { var networks []string if names, ok := containerLables[labels.Networks]; ok { diff --git a/pkg/cmd/container/list_util.go b/pkg/cmd/container/list_util.go index 4647faa213a..50f1f8b7251 100644 --- a/pkg/cmd/container/list_util.go +++ b/pkg/cmd/container/list_util.go @@ -289,7 +289,7 @@ func (cl *containerFilterContext) matchesNameFilter(info containers.Container) b if len(cl.nameFilterFuncs) == 0 { return true } - cName := getContainerName(info.Labels) + cName := containerutil.GetContainerName(info.Labels) for _, nameFilterFunc := range cl.nameFilterFuncs { if !nameFilterFunc(cName) { continue @@ -368,7 +368,7 @@ func idOrNameFilter(ctx context.Context, containers []containerd.Container, valu if err != nil { return nil, err } - if strings.HasPrefix(info.ID, value) || strings.Contains(getContainerName(info.Labels), value) { + if strings.HasPrefix(info.ID, value) || strings.Contains(containerutil.GetContainerName(info.Labels), value) { return &info, nil } } diff --git a/pkg/cmd/container/stats.go b/pkg/cmd/container/stats.go index c81165a4773..de44e7226e0 100644 --- a/pkg/cmd/container/stats.go +++ b/pkg/cmd/container/stats.go @@ -35,11 +35,11 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/containerinspector" + "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/eventutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/infoutil" - "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/statsutil" "github.com/containerd/typeurl/v2" @@ -54,7 +54,7 @@ type stats struct { func (s *stats) add(cs *statsutil.Stats) bool { s.mu.Lock() defer s.mu.Unlock() - if _, exists := s.isKnownContainer(cs.Container); !exists { + if _, exists := s.isKnownContainer(cs.ID); !exists { s.cs = append(s.cs, cs) return true } @@ -73,7 +73,7 @@ func (s *stats) remove(id string) { // isKnownContainer is from https://github.com/docker/cli/blob/3fb4fb83dfb5db0c0753a8316f21aea54dab32c5/cli/command/container/stats_helpers.go#L44-L51 func (s *stats) isKnownContainer(cid string) (int, bool) { for i, c := range s.cs { - if c.Container == cid { + if c.ID == cid { return i, true } } @@ -325,7 +325,7 @@ func Stats(ctx context.Context, client *containerd.Client, containerIDs []string } func collect(ctx context.Context, globalOptions types.GlobalCommandOptions, s *statsutil.Stats, waitFirst *sync.WaitGroup, id string, noStream bool) { - log.G(ctx).Debugf("collecting stats for %s", s.Container) + log.G(ctx).Debugf("collecting stats for %s", s.ID) var ( getFirst = true u = make(chan error, 1) @@ -394,7 +394,7 @@ func collect(ctx context.Context, globalOptions types.GlobalCommandOptions, s *s u <- err continue } - statsEntry.Name = clabels[labels.Name] + statsEntry.Name = containerutil.GetContainerName(clabels) statsEntry.ID = container.ID() if firstSet { diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 85a4ddc53c9..d61a478ccd3 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -40,6 +40,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/labels/k8slabels" "github.com/containerd/nerdctl/v2/pkg/nsutil" "github.com/containerd/nerdctl/v2/pkg/portutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" @@ -562,3 +563,21 @@ func GetContainerVolumes(containerLabels map[string]string) []*ContainerVolume { } return vols } + +func GetContainerName(containerLabels map[string]string) string { + if name, ok := containerLabels[labels.Name]; ok { + return name + } + + if ns, ok := containerLabels[k8slabels.PodNamespace]; ok { + if podName, ok := containerLabels[k8slabels.PodName]; ok { + if containerName, ok := containerLabels[k8slabels.ContainerName]; ok { + // Container + return fmt.Sprintf("k8s://%s/%s/%s", ns, podName, containerName) + } + // Pod sandbox + return fmt.Sprintf("k8s://%s/%s", ns, podName) + } + } + return "" +} diff --git a/pkg/statsutil/stats.go b/pkg/statsutil/stats.go index 05436b84f45..bfbf8b6e1c0 100644 --- a/pkg/statsutil/stats.go +++ b/pkg/statsutil/stats.go @@ -19,6 +19,7 @@ package statsutil import ( "fmt" "strconv" + "strings" "sync" "time" @@ -27,7 +28,6 @@ import ( // StatsEntry represents the statistics data collected from a container type StatsEntry struct { - Container string Name string ID string CPUPercentage float64 @@ -69,15 +69,14 @@ type ContainerStats struct { } // NewStats is from https://github.com/docker/cli/blob/3fb4fb83dfb5db0c0753a8316f21aea54dab32c5/cli/command/container/formatter_stats.go#L113-L116 -func NewStats(container string) *Stats { - return &Stats{StatsEntry: StatsEntry{Container: container}} +func NewStats(containerID string) *Stats { + return &Stats{StatsEntry: StatsEntry{ID: containerID}} } // SetStatistics is from https://github.com/docker/cli/blob/3fb4fb83dfb5db0c0753a8316f21aea54dab32c5/cli/command/container/formatter_stats.go#L87-L93 func (cs *Stats) SetStatistics(s StatsEntry) { cs.mutex.Lock() defer cs.mutex.Unlock() - s.Container = cs.Container cs.StatsEntry = s } @@ -134,7 +133,7 @@ func calculateMemPercent(limit float64, usedNo float64) float64 { // Rendering a FormattedStatsEntry from StatsEntry func RenderEntry(in *StatsEntry, noTrunc bool) FormattedStatsEntry { return FormattedStatsEntry{ - Name: in.EntryName(), + Name: in.EntryName(noTrunc), ID: in.EntryID(noTrunc), CPUPerc: in.CPUPerc(), MemUsage: in.MemUsage(), @@ -148,10 +147,18 @@ func RenderEntry(in *StatsEntry, noTrunc bool) FormattedStatsEntry { /* a set of functions to format container stats */ -func (s *StatsEntry) EntryName() string { +func (s *StatsEntry) EntryName(noTrunc bool) string { if len(s.Name) > 1 { - if len(s.Name) > 12 { - return s.Name[:12] + if !noTrunc { + var truncLen int + if strings.HasPrefix(s.Name, "k8s://") { + truncLen = 24 + } else { + truncLen = 12 + } + if len(s.Name) > truncLen { + return s.Name[:truncLen] + } } return s.Name } From 91c0b7f65d39bdc23b3cd9dd83577730a6c5154c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 20:53:08 +0000 Subject: [PATCH 0542/1066] build(deps): bump github.com/docker/cli Bumps [github.com/docker/cli](https://github.com/docker/cli) from 26.1.4+incompatible to 27.0.3+incompatible. - [Commits](https://github.com/docker/cli/compare/v26.1.4...v27.0.3) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 75336422fce..d270d08ff26 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 - github.com/docker/cli v26.1.4+incompatible + github.com/docker/cli v27.0.3+incompatible github.com/docker/docker v27.0.2+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 diff --git a/go.sum b/go.sum index 42bade937bd..54770394994 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwenxRM7/rLu8= -github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v27.0.3+incompatible h1:usGs0/BoBW8MWxGeEtqPMkzOY56jZ6kYlSN5BLDioCQ= +github.com/docker/cli v27.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v27.0.2+incompatible h1:mNhCtgXNV1fIRns102grG7rdzIsGGCq1OlOD0KunZos= github.com/docker/docker v27.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= From db152b91435c7792c5acee8068f9617058658663 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 01:55:04 +0000 Subject: [PATCH 0543/1066] build(deps): bump github.com/docker/docker Bumps [github.com/docker/docker](https://github.com/docker/docker) from 27.0.2+incompatible to 27.0.3+incompatible. - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.0.2...v27.0.3) --- updated-dependencies: - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d270d08ff26..91855ce1f09 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.2.5 github.com/docker/cli v27.0.3+incompatible - github.com/docker/docker v27.0.2+incompatible + github.com/docker/docker v27.0.3+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 54770394994..832c0ba7923 100644 --- a/go.sum +++ b/go.sum @@ -88,8 +88,8 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/docker/cli v27.0.3+incompatible h1:usGs0/BoBW8MWxGeEtqPMkzOY56jZ6kYlSN5BLDioCQ= github.com/docker/cli v27.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.0.2+incompatible h1:mNhCtgXNV1fIRns102grG7rdzIsGGCq1OlOD0KunZos= -github.com/docker/docker v27.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= +github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 356b88dcfd58fa4367ef64fb5f490a64384b04a4 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 1 Jul 2024 16:10:27 -0700 Subject: [PATCH 0544/1066] Rewrite container remove Signed-off-by: apostasie --- cmd/nerdctl/container_prune_linux_test.go | 21 ++- pkg/cmd/container/remove.go | 211 +++++++++++++--------- 2 files changed, 140 insertions(+), 92 deletions(-) diff --git a/cmd/nerdctl/container_prune_linux_test.go b/cmd/nerdctl/container_prune_linux_test.go index 0aec844714f..47560af3acb 100644 --- a/cmd/nerdctl/container_prune_linux_test.go +++ b/cmd/nerdctl/container_prune_linux_test.go @@ -26,16 +26,29 @@ func TestPruneContainer(t *testing.T) { base := testutil.NewBase(t) tID := testutil.Identifier(t) - base.Cmd("run", "-d", "--name", tID+"-1", testutil.CommonImage, "sleep", "infinity").AssertOK() - defer base.Cmd("rm", "-f", tID+"-1").Run() - base.Cmd("create", "--name", tID+"-2", testutil.CommonImage, "sleep", "infinity").AssertOK() - defer base.Cmd("rm", "-f", tID+"-2").Run() + tearDown := func() { + defer base.Cmd("rm", "-f", tID+"-1").Run() + defer base.Cmd("rm", "-f", tID+"-2").Run() + } + + tearUp := func() { + base.Cmd("run", "-d", "--name", tID+"-1", "-v", "/anonymous", testutil.CommonImage, "sleep", "infinity").AssertOK() + base.Cmd("exec", tID+"-1", "touch", "/anonymous/foo").AssertOK() + base.Cmd("create", "--name", tID+"-2", testutil.CommonImage, "sleep", "infinity").AssertOK() + } + + tearDown() + t.Cleanup(tearDown) + tearUp() base.Cmd("container", "prune", "-f").AssertOK() // tID-1 is still running, tID-2 is not base.Cmd("inspect", tID+"-1").AssertOK() base.Cmd("inspect", tID+"-2").AssertFail() + // https://github.com/containerd/nerdctl/issues/3134 + base.Cmd("exec", tID+"-1", "ls", "-lA", "/anonymous/foo").AssertOK() + base.Cmd("kill", tID+"-1").AssertOK() base.Cmd("container", "prune", "-f").AssertOK() base.Cmd("inspect", tID+"-1").AssertFail() diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index b6fb87c93bb..56cdcc3ebea 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -90,6 +90,15 @@ func Remove(ctx context.Context, client *containerd.Client, containers []string, } // RemoveContainer removes a container from containerd store. +// It will first retrieve system objects (namestore, etcetera), then assess whether we should remove the container or not +// based of "force" and the status of the task. +// If we are to delete, it then kills and delete the task. +// If task removal fails, we stop (except if it was just "NotFound"). +// We then enter the defer cleanup function that will: +// - remove the network config (windows only) +// - delete the container +// - then and ONLY then, on a successful container remove, clean things-up on our side (volume store, etcetera) +// If you do need to add more cleanup, please do so at the bottom of the defer function func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions types.GlobalCommandOptions, force bool, removeAnonVolumes bool, client *containerd.Client) (retErr error) { // defer the storage of remove error in the dedicated label defer func() { @@ -97,151 +106,177 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions containerutil.UpdateErrorLabel(ctx, c, retErr) } }() - ns, err := namespaces.NamespaceRequired(ctx) + + // Get namespace + containerNamespace, err := namespaces.NamespaceRequired(ctx) if err != nil { return err } - id := c.ID() - l, err := c.Labels(ctx) + // Get labels + containerLabels, err := c.Labels(ctx) if err != nil { return err } - ipc, err := ipcutil.DecodeIPCLabel(l[labels.IPC]) + // Get datastore + dataStore, err := clientutil.DataStore(globalOptions.DataRoot, globalOptions.Address) if err != nil { return err } - err = ipcutil.CleanUp(ipc) + // Get namestore + nameStore, err := namestore.New(dataStore, containerNamespace) if err != nil { return err } - stateDir := l[labels.StateDir] - name := l[labels.Name] - dataStore, err := clientutil.DataStore(globalOptions.DataRoot, globalOptions.Address) + // Get volume store + volStore, err := volume.Store(globalOptions.Namespace, globalOptions.DataRoot, globalOptions.Address) if err != nil { return err } - namst, err := namestore.New(dataStore, ns) + // Decode IPC + ipc, err := ipcutil.DecodeIPCLabel(containerLabels[labels.IPC]) if err != nil { return err } + // Get the container id, stateDir and name + id := c.ID() + stateDir := containerLabels[labels.StateDir] + name := containerLabels[labels.Name] + + // This will evaluate retErr to decide if we proceed with removal or not defer func() { - if errdefs.IsNotFound(retErr) { - retErr = nil - } - if retErr != nil { + // If there was an error, and it was not "NotFound", this is a hard error, we stop here and do nothing. + if retErr != nil && !errdefs.IsNotFound(retErr) { return } - if err := os.RemoveAll(stateDir); err != nil { + + // Otherwise, nil the error so that we do not write the error label on the container + retErr = nil + + // Now, delete the actual container + var delOpts []containerd.DeleteOpts + if _, err := c.Image(ctx); err == nil { + delOpts = append(delOpts, containerd.WithSnapshotCleanup) + } + + // NOTE: on non-Windows platforms, network cleanup is performed by OCI hooks. + // Seeing as though Windows does not currently support OCI hooks, we must explicitly + // perform the network cleanup from the main nerdctl executable. + if runtime.GOOS == "windows" { + spec, err := c.Spec(ctx) + if err != nil { + retErr = err + return + } + + netOpts, err := containerutil.NetworkOptionsFromSpec(spec) + if err != nil { + retErr = fmt.Errorf("failed to load container networking options from specs: %s", err) + return + } + + networkManager, err := containerutil.NewNetworkingOptionsManager(globalOptions, netOpts, client) + if err != nil { + retErr = fmt.Errorf("failed to instantiate network options manager: %s", err) + return + } + + if err := networkManager.CleanupNetworking(ctx, c); err != nil { + log.G(ctx).WithError(err).Warnf("failed to clean up container networking: %q", id) + } + } + + // Delete the container now. If it fails, try again without snapshot cleanup + // If it still fails, time to stop. + if c.Delete(ctx, delOpts...) != nil { + retErr = c.Delete(ctx) + if retErr != nil { + return + } + } + + // Container has been removed successfully. Now we just finish the cleanup on our side. + + // Cleanup IPC - soft failure + if err = ipcutil.CleanUp(ipc); err != nil { + log.G(ctx).WithError(err).Warnf("failed to cleanup IPC for container %q", id) + } + + // Remove state dir - soft failure + if err = os.RemoveAll(stateDir); err != nil { log.G(ctx).WithError(err).Warnf("failed to remove container state dir %s", stateDir) } - // enforce release name here in case the poststop hook name release fails + + // Enforce release name here in case the poststop hook name release fails - soft failure if name != "" { - if err := namst.Release(name, id); err != nil { + if err = nameStore.Release(name, id); err != nil { log.G(ctx).WithError(err).Warnf("failed to release container name %s", name) } } - if err := hostsstore.DeallocHostsFile(dataStore, ns, id); err != nil { + + // De-allocate hosts file - soft failure + if err = hostsstore.DeallocHostsFile(dataStore, containerNamespace, id); err != nil { log.G(ctx).WithError(err).Warnf("failed to remove hosts file for container %q", id) } - }() - // volume removal is not handled by the poststop hook lifecycle because it depends on removeAnonVolumes option - if anonVolumesJSON, ok := l[labels.AnonymousVolumes]; ok && removeAnonVolumes { - var anonVolumes []string - if err := json.Unmarshal([]byte(anonVolumesJSON), &anonVolumes); err != nil { - return err - } - volStore, err := volume.Store(globalOptions.Namespace, globalOptions.DataRoot, globalOptions.Address) - if err != nil { - return err - } - defer func() { - if _, errs, err := volStore.Remove(anonVolumes); err != nil || len(errs) > 0 { - log.G(ctx).WithError(err).Warnf("failed to remove anonymous volumes %v", anonVolumes) + // Volume removal is not handled by the poststop hook lifecycle because it depends on removeAnonVolumes option + if anonVolumesJSON, ok := containerLabels[labels.AnonymousVolumes]; ok && removeAnonVolumes { + var anonVolumes []string + if err = json.Unmarshal([]byte(anonVolumesJSON), &anonVolumes); err != nil { + log.G(ctx).WithError(err).Warnf("failed to unmarshall anonvolume information for container %q", id) + } else { + var errs []error + _, errs, err = volStore.Remove(anonVolumes) + if err != nil || len(errs) > 0 { + log.G(ctx).WithError(err).Warnf("failed to remove anonymous volumes %v", anonVolumes) + } } - }() - } + } + }() + // Get the task. task, err := c.Task(ctx, cio.Load) if err != nil { - if errdefs.IsNotFound(err) { - if c.Delete(ctx, containerd.WithSnapshotCleanup) != nil { - return c.Delete(ctx) - } - } return err } + // Task was here, get the status status, err := task.Status(ctx) if err != nil { - if errdefs.IsNotFound(err) { - return nil - } return err } - // NOTE: on non-Windows platforms, network cleanup is performed by OCI hooks. - // Seeing as though Windows does not currently support OCI hooks, we must explicitly - // perform the network cleanup from the main nerdctl executable. - if runtime.GOOS == "windows" { - spec, err := c.Spec(ctx) - if err != nil { - return err - } - - netOpts, err := containerutil.NetworkOptionsFromSpec(spec) - if err != nil { - return fmt.Errorf("failed to load container networking options from specs: %s", err) - } - - networkManager, err := containerutil.NewNetworkingOptionsManager(globalOptions, netOpts, client) - if err != nil { - return fmt.Errorf("failed to instantiate network options manager: %s", err) - } - - if err := networkManager.CleanupNetworking(ctx, c); err != nil { - log.G(ctx).WithError(err).Warnf("failed to clean up container networking: %s", err) - } - } - + // Now, we have a live task with a status. switch status.Status { - case containerd.Created, containerd.Stopped: - if _, err := task.Delete(ctx); err != nil && !errdefs.IsNotFound(err) { - return fmt.Errorf("failed to delete task %v: %w", id, err) - } case containerd.Paused: + // Paused containers only get removed if we force if !force { return NewStatusError(id, status.Status) } - _, err := task.Delete(ctx, containerd.WithProcessKill) - if err != nil && !errdefs.IsNotFound(err) { - return fmt.Errorf("failed to delete task %v: %w", id, err) - } - // default is the case, when status.Status = containerd.Running - default: + case containerd.Running: + // Running containers only get removed if we force if !force { return NewStatusError(id, status.Status) } - if err := task.Kill(ctx, syscall.SIGKILL); err != nil { - log.G(ctx).WithError(err).Warnf("failed to send SIGKILL") + // Kill the task. Soft error. + if err = task.Kill(ctx, syscall.SIGKILL); err != nil && !errdefs.IsNotFound(err) { + log.G(ctx).WithError(err).Warnf("failed to send SIGKILL to task %v", id) } es, err := task.Wait(ctx) if err == nil { <-es } - _, err = task.Delete(ctx, containerd.WithProcessKill) - if err != nil && !errdefs.IsNotFound(err) { - log.G(ctx).WithError(err).Warnf("failed to delete task %v", id) - } - } - var delOpts []containerd.DeleteOpts - if _, err := c.Image(ctx); err == nil { - delOpts = append(delOpts, containerd.WithSnapshotCleanup) - } - - if err := c.Delete(ctx, delOpts...); err != nil { + case containerd.Created, containerd.Stopped: + // Created and stopped containers always get removed + // Delete the task, without forcing kill + _, err = task.Delete(ctx) return err + default: + // Unknown status error out + return fmt.Errorf("unknown container status %s", status.Status) } + + // Delete the task + _, err = task.Delete(ctx, containerd.WithProcessKill) return err } From d627713bb4a820ea32c9044e2eea9a42e00c3b1c Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Wed, 3 Jul 2024 02:30:43 +0000 Subject: [PATCH 0545/1066] update containerd (1.7.19) Signed-off-by: Kay Yan --- .github/workflows/test.yml | 22 ++++++++--------- go.mod | 5 ++-- go.sum | 10 ++++---- pkg/cmd/builder/build.go | 10 ++++---- pkg/cmd/builder/build_test.go | 38 +++++++++++++++--------------- pkg/cmd/image/push.go | 6 ++--- pkg/imgutil/filtering.go | 8 +++---- pkg/imgutil/imgutil.go | 16 ++++++------- pkg/referenceutil/referenceutil.go | 10 ++++---- 9 files changed, 64 insertions(+), 61 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 92ee4c5da91..4be68fd297d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -81,13 +81,13 @@ jobs: - ubuntu: 20.04 containerd: v1.6.33 - ubuntu: 20.04 - containerd: v1.7.18 + containerd: v1.7.19 - ubuntu: 22.04 - containerd: v1.7.18 + containerd: v1.7.19 - ubuntu: 22.04 containerd: main # v2.0.0-rc.X - ubuntu: 24.04 - containerd: v1.7.18 + containerd: v1.7.19 - ubuntu: 24.04 containerd: main # v2.0.0-rc.X env: @@ -124,7 +124,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04 and later: cgroup v2 include: - ubuntu: 24.04 - containerd: v1.7.18 + containerd: v1.7.19 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -177,11 +177,11 @@ jobs: rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 20.04 - containerd: v1.7.18 + containerd: v1.7.19 rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.18 + containerd: v1.7.19 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 22.04 @@ -189,7 +189,7 @@ jobs: rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 24.04 - containerd: v1.7.18 + containerd: v1.7.19 rootlesskit: v1.1.1 target: test-integration-rootless - ubuntu: 24.04 @@ -201,11 +201,11 @@ jobs: rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 20.04 - containerd: v1.7.18 + containerd: v1.7.19 rootlesskit: v2.1.0 target: test-integration-rootless-port-slirp4netns - ubuntu: 24.04 - containerd: v1.7.18 + containerd: v1.7.19 rootlesskit: v1.1.1 target: test-integration-rootless-port-slirp4netns - ubuntu: 24.04 @@ -322,7 +322,7 @@ jobs: - uses: actions/checkout@v4.1.7 with: repository: containerd/containerd - ref: v1.7.18 + ref: v1.7.19 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -330,7 +330,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.18 + ctrdVersion: 1.7.19 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" diff --git a/go.mod b/go.mod index 91855ce1f09..3a1fae5d515 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,8 @@ require ( github.com/containerd/accelerated-container-image v1.1.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd v1.7.18 + github.com/containerd/containerd v1.7.19 + 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.10 @@ -75,7 +76,7 @@ require ( github.com/cilium/ebpf v0.11.0 // indirect github.com/containerd/errdefs v0.1.0 // indirect github.com/containerd/go-runc v1.0.0 // indirect - github.com/containerd/ttrpc v1.2.4 // indirect + 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.10 // indirect github.com/distribution/reference v0.6.0 diff --git a/go.sum b/go.sum index 832c0ba7923..1f82deb2ae6 100644 --- a/go.sum +++ b/go.sum @@ -32,8 +32,10 @@ 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.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= -github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= +github.com/containerd/containerd v1.7.19 h1:/xQ4XRJ0tamDkdzrrBAUy/LE5nCcxFKdBm4EcPrSMEE= +github.com/containerd/containerd v1.7.19/go.mod h1:h4FtNYUUMB4Phr6v+xG89RYKj9XccvbNSCKjdufCrkc= +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= @@ -58,8 +60,8 @@ github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G 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.4 h1:eQCQK4h9dxDmpOb9QOOMh2NHTfzroH1IkmHiKZi05Oo= -github.com/containerd/ttrpc v1.2.4/go.mod h1:ojvb8SJBSch0XkqNO0L0YX/5NxR3UnVk2LzFKBK0upc= +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= diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 070779a0b2e..0e9e39fbc53 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -32,7 +32,6 @@ import ( "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" "github.com/containerd/containerd/images/archive" - dockerreference "github.com/containerd/containerd/reference/docker" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" @@ -40,6 +39,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/platforms" + distributionref "github.com/distribution/reference" ) type PlatformParser interface { @@ -230,19 +230,19 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option } if tags = strutil.DedupeStrSlice(options.Tag); len(tags) > 0 { ref := tags[0] - named, err := dockerreference.ParseNormalizedNamed(ref) + named, err := distributionref.ParseNormalizedNamed(ref) if err != nil { return "", nil, false, "", nil, nil, err } - output += ",name=" + dockerreference.TagNameOnly(named).String() + output += ",name=" + distributionref.TagNameOnly(named).String() // pick the first tag and add it to output for idx, tag := range tags { - named, err := dockerreference.ParseNormalizedNamed(tag) + named, err := distributionref.ParseNormalizedNamed(tag) if err != nil { return "", nil, false, "", nil, nil, err } - tags[idx] = dockerreference.TagNameOnly(named).String() + tags[idx] = distributionref.TagNameOnly(named).String() } } else if len(tags) == 0 { output = output + ",dangling-name-prefix=" diff --git a/pkg/cmd/builder/build_test.go b/pkg/cmd/builder/build_test.go index c1fa0caba36..f7fb00e539f 100644 --- a/pkg/cmd/builder/build_test.go +++ b/pkg/cmd/builder/build_test.go @@ -20,7 +20,7 @@ import ( "reflect" "testing" - "github.com/containerd/containerd/platforms" + specs "github.com/opencontainers/image-spec/specs-go/v1" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" ) @@ -44,10 +44,10 @@ func (m *MockParse) EXPECT() *MockParseRecorder { return m.recorder } -func (m *MockParse) Parse(platform string) (platforms.Platform, error) { +func (m *MockParse) Parse(platform string) (specs.Platform, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Parse") - ret0, _ := ret[0].(platforms.Platform) + ret0, _ := ret[0].(specs.Platform) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -57,10 +57,10 @@ func (m *MockParseRecorder) Parse(platform string) *gomock.Call { return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Parse", reflect.TypeOf((*MockParse)(nil).Parse)) } -func (m *MockParse) DefaultSpec() platforms.Platform { +func (m *MockParse) DefaultSpec() specs.Platform { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "DefaultSpec") - ret0, _ := ret[0].(platforms.Platform) + ret0, _ := ret[0].(specs.Platform) return ret0 } @@ -80,40 +80,40 @@ func TestIsMatchingRuntimePlatform(t *testing.T) { { name: "Image is shareable when Runtime and build platform match for os, arch and variant", mock: func(mockParser *MockParse) { - mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}, nil) - mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + mockParser.EXPECT().Parse("test").Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}, nil) + mockParser.EXPECT().DefaultSpec().Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) }, want: true, }, { name: "Image is shareable when Runtime and build platform match for os, arch. Variant is not defined", mock: func(mockParser *MockParse) { - mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: ""}, nil) - mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + mockParser.EXPECT().Parse("test").Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: ""}, nil) + mockParser.EXPECT().DefaultSpec().Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) }, want: true, }, { name: "Image is not shareable when Runtime and build platform donot math OS", mock: func(mockParser *MockParse) { - mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "OS", Architecture: "mockArch", Variant: ""}, nil) - mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + mockParser.EXPECT().Parse("test").Return(specs.Platform{OS: "OS", Architecture: "mockArch", Variant: ""}, nil) + mockParser.EXPECT().DefaultSpec().Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) }, want: false, }, { name: "Image is not shareable when Runtime and build platform donot math Arch", mock: func(mockParser *MockParse) { - mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "mockOS", Architecture: "Arch", Variant: ""}, nil) - mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + mockParser.EXPECT().Parse("test").Return(specs.Platform{OS: "mockOS", Architecture: "Arch", Variant: ""}, nil) + mockParser.EXPECT().DefaultSpec().Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) }, want: false, }, { name: "Image is not shareable when Runtime and build platform donot math Variant", mock: func(mockParser *MockParse) { - mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "Variant"}, nil) - mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + mockParser.EXPECT().Parse("test").Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "Variant"}, nil) + mockParser.EXPECT().DefaultSpec().Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) }, want: false, }, @@ -151,8 +151,8 @@ func TestIsBuildPlatformDefault(t *testing.T) { name: "Image is shareable when Runtime and build platform match for os, arch and variant", platform: []string{"test"}, mock: func(mockParser *MockParse) { - mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}, nil) - mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + mockParser.EXPECT().Parse("test").Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}, nil) + mockParser.EXPECT().DefaultSpec().Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) }, want: true, }, @@ -160,8 +160,8 @@ func TestIsBuildPlatformDefault(t *testing.T) { name: "Image is not shareable when Runtime build platform dont match", platform: []string{"test"}, mock: func(mockParser *MockParse) { - mockParser.EXPECT().Parse("test").Return(platforms.Platform{OS: "OS", Architecture: "mockArch", Variant: "mockVariant"}, nil) - mockParser.EXPECT().DefaultSpec().Return(platforms.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) + mockParser.EXPECT().Parse("test").Return(specs.Platform{OS: "OS", Architecture: "mockArch", Variant: "mockVariant"}, nil) + mockParser.EXPECT().DefaultSpec().Return(specs.Platform{OS: "mockOS", Architecture: "mockArch", Variant: "mockVariant"}) }, want: false, }, diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index 0970a6972fe..f8f2348b683 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" + distributionref "github.com/distribution/reference" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -83,12 +83,12 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options return nil } - named, err := refdocker.ParseDockerRef(rawRef) + named, err := distributionref.ParseDockerRef(rawRef) if err != nil { return err } ref := named.String() - refDomain := refdocker.Domain(named) + refDomain := distributionref.Domain(named) platMC, err := platformutil.NewMatchComparer(options.AllPlatforms, options.Platforms) if err != nil { diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index ad31d0617e4..ea01e781211 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/v2/pkg/referenceutil" + distributionref "github.com/distribution/reference" ) // Filter types supported to filter images. @@ -141,14 +141,14 @@ func FilterByReference(imageList []images.Image, filters []string) ([]images.Ima log.L.Debug(image.Name) var matches int for _, f := range filters { - var ref dockerreference.Reference + var ref distributionref.Reference var err error - ref, err = dockerreference.ParseAnyReference(image.Name) + ref, err = distributionref.ParseAnyReference(image.Name) if err != nil { return nil, fmt.Errorf("unable to parse image name: %s while filtering by reference because of %s", image.Name, err.Error()) } - familiarMatch, err := dockerreference.FamiliarMatch(f, ref) + familiarMatch, err := distributionref.FamiliarMatch(f, ref) if err != nil { return nil, err } diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 71e010459aa..f632004093f 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -26,7 +26,6 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" - refdocker "github.com/containerd/containerd/reference/docker" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/snapshots" "github.com/containerd/imgcrypt" @@ -38,6 +37,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" "github.com/containerd/platforms" + distributionref "github.com/distribution/reference" "github.com/docker/docker/errdefs" "github.com/opencontainers/image-spec/identity" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -125,12 +125,12 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr return nil, fmt.Errorf("image not available: %q", rawRef) } - named, err := refdocker.ParseDockerRef(rawRef) + named, err := distributionref.ParseDockerRef(rawRef) if err != nil { return nil, err } ref := named.String() - refDomain := refdocker.Domain(named) + refDomain := distributionref.Domain(named) var dOpts []dockerconfigresolver.Opt if insecure { @@ -168,12 +168,12 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr // ResolveDigest resolves `rawRef` and returns its descriptor digest. func ResolveDigest(ctx context.Context, rawRef string, insecure bool, hostsDirs []string) (string, error) { - named, err := refdocker.ParseDockerRef(rawRef) + named, err := distributionref.ParseDockerRef(rawRef) if err != nil { return "", err } ref := named.String() - refDomain := refdocker.Domain(named) + refDomain := distributionref.Domain(named) var dOpts []dockerconfigresolver.Opt if insecure { @@ -361,7 +361,7 @@ func ReadImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image, func ParseRepoTag(imgName string) (string, string) { log.L.Debugf("raw image name=%q", imgName) - ref, err := refdocker.ParseDockerRef(imgName) + ref, err := distributionref.ParseDockerRef(imgName) if err != nil { log.L.WithError(err).Debugf("unparsable image name %q", imgName) return "", "" @@ -369,10 +369,10 @@ func ParseRepoTag(imgName string) (string, string) { var tag string - if tagged, ok := ref.(refdocker.Tagged); ok { + if tagged, ok := ref.(distributionref.Tagged); ok { tag = tagged.Tag() } - repository := refdocker.FamiliarName(ref) + repository := distributionref.FamiliarName(ref) return repository, tag } diff --git a/pkg/referenceutil/referenceutil.go b/pkg/referenceutil/referenceutil.go index 9507bad23eb..928b3648923 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" + distributionref "github.com/distribution/reference" "github.com/ipfs/go-cid" ) @@ -42,7 +42,7 @@ func ParseAnyReference(rawRef string) (Reference, error) { if c, err := cid.Decode(rawRef); err == nil { return c, nil } - return refdocker.ParseAnyReference(rawRef) + return distributionref.ParseAnyReference(rawRef) } // ParseAny parses the passed reference with allowing it to be non-docker reference. @@ -59,8 +59,8 @@ func ParseAny(rawRef string) (Reference, error) { } // ParseDockerRef parses the passed reference with assuming it's a docker reference. -func ParseDockerRef(rawRef string) (refdocker.Named, error) { - return refdocker.ParseDockerRef(rawRef) +func ParseDockerRef(rawRef string) (distributionref.Named, error) { + return distributionref.ParseDockerRef(rawRef) } // ParseIPFSRefWithScheme parses the passed reference with assuming it's an IPFS reference with scheme prefix. @@ -92,7 +92,7 @@ func SuggestContainerName(rawRef, containerID string) string { r, err := ParseAny(rawRef) if err == nil { switch rr := r.(type) { - case refdocker.Named: + case distributionref.Named: if rrName := rr.Name(); rrName != "" { imageNameBased := path.Base(rrName) if imageNameBased != "" { From 150f9cbdecfd5e61d7a7d22bd6207400b1734659 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 3 Jul 2024 14:22:17 -0700 Subject: [PATCH 0546/1066] Fix wrong assumption about container availability Signed-off-by: apostasie --- pkg/cmd/volume/rm.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/cmd/volume/rm.go b/pkg/cmd/volume/rm.go index 509957bb978..2c74df9f1b2 100644 --- a/pkg/cmd/volume/rm.go +++ b/pkg/cmd/volume/rm.go @@ -23,6 +23,7 @@ import ( "fmt" "github.com/containerd/containerd" + "github.com/containerd/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" @@ -75,6 +76,11 @@ func usedVolumes(ctx context.Context, containers []containerd.Container) (map[st for _, c := range containers { l, err := c.Labels(ctx) if err != nil { + // Containerd note: there is no guarantee that the containers we got from the list still exist at this point + // If that is the case, just ignore and move on + if errors.Is(err, errdefs.ErrNotFound) { + continue + } return nil, err } mountsJSON, ok := l[labels.Mounts] From 294caa661cc5ecad2d0614cc1d7996c6ba0da6f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jul 2024 22:30:32 +0000 Subject: [PATCH 0547/1066] build(deps): bump docker/build-push-action from 6.2.0 to 6.3.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.2.0 to 6.3.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.2.0...v6.3.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 1c335b22ea2..6a2f93c2061 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.2.0 + uses: docker/build-push-action@v6.3.0 with: context: . platforms: linux/amd64,linux/arm64 From 60dc94213a9566ab490df8d0573b69ec4b5fe7ba Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 3 Jul 2024 17:09:07 -0700 Subject: [PATCH 0548/1066] Cleanup login command (remove global var and normalize to other commands Signed-off-by: apostasie --- cmd/nerdctl/login.go | 84 +++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/cmd/nerdctl/login.go b/cmd/nerdctl/login.go index 4cff2458bb8..07e03253f50 100644 --- a/cmd/nerdctl/login.go +++ b/cmd/nerdctl/login.go @@ -28,15 +28,6 @@ import ( "github.com/spf13/cobra" ) -type loginOptions struct { - serverAddress string - username string - password string - passwordStdin bool -} - -var options = new(loginOptions) - func newLoginCommand() *cobra.Command { var loginCommand = &cobra.Command{ Use: "login [flags] [SERVER]", @@ -46,54 +37,67 @@ func newLoginCommand() *cobra.Command { SilenceUsage: true, SilenceErrors: true, } - loginCommand.Flags().StringVarP(&options.username, "username", "u", "", "Username") - loginCommand.Flags().StringVarP(&options.password, "password", "p", "", "Password") - loginCommand.Flags().BoolVar(&options.passwordStdin, "password-stdin", false, "Take the password from stdin") + loginCommand.Flags().StringP("username", "u", "", "Username") + loginCommand.Flags().StringP("password", "p", "", "Password") + loginCommand.Flags().Bool("password-stdin", false, "Take the password from stdin") return loginCommand } -func loginAction(cmd *cobra.Command, args []string) error { - if len(args) == 1 { - options.serverAddress = args[0] - } - if err := verifyLoginOptions(cmd, options); err != nil { - return err - } - +func processLoginOptions(cmd *cobra.Command) (types.LoginCommandOptions, error) { globalOptions, err := processRootCmdFlags(cmd) if err != nil { - return err + return types.LoginCommandOptions{}, err } - return login.Login(cmd.Context(), types.LoginCommandOptions{ - GOptions: globalOptions, - ServerAddress: options.serverAddress, - Username: options.username, - Password: options.password, - }, cmd.OutOrStdout()) -} + username, err := cmd.Flags().GetString("username") + if err != nil { + return types.LoginCommandOptions{}, err + } + password, err := cmd.Flags().GetString("password") + if err != nil { + return types.LoginCommandOptions{}, err + } + passwordStdin, err := cmd.Flags().GetBool("password-stdin") + if err != nil { + return types.LoginCommandOptions{}, err + } -// copied from github.com/docker/cli/cli/command/registry/login.go (v20.10.3) -func verifyLoginOptions(cmd *cobra.Command, options *loginOptions) error { - if options.password != "" { + if password != "" { log.L.Warn("WARNING! Using --password via the CLI is insecure. Use --password-stdin.") - if options.passwordStdin { - return errors.New("--password and --password-stdin are mutually exclusive") + if passwordStdin { + return types.LoginCommandOptions{}, errors.New("--password and --password-stdin are mutually exclusive") } } - if options.passwordStdin { - if options.username == "" { - return errors.New("must provide --username with --password-stdin") + if passwordStdin { + if username == "" { + return types.LoginCommandOptions{}, errors.New("must provide --username with --password-stdin") } contents, err := io.ReadAll(cmd.InOrStdin()) if err != nil { - return err + return types.LoginCommandOptions{}, err } - options.password = strings.TrimSuffix(string(contents), "\n") - options.password = strings.TrimSuffix(options.password, "\r") + password = strings.TrimSuffix(string(contents), "\n") + password = strings.TrimSuffix(password, "\r") } - return nil + return types.LoginCommandOptions{ + GOptions: globalOptions, + Username: username, + Password: password, + }, nil +} + +func loginAction(cmd *cobra.Command, args []string) error { + options, err := processLoginOptions(cmd) + if err != nil { + return err + } + + if len(args) == 1 { + options.ServerAddress = args[0] + } + + return login.Login(cmd.Context(), options, cmd.OutOrStdout()) } From e32d75c4d895cf199504b071d06c25ccfdf6e133 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 4 Jul 2024 18:06:32 +0900 Subject: [PATCH 0549/1066] Add logo Fix issue 1542 Signed-off-by: Akihiro Suda --- README.md | 2 ++ docs/images/nerdctl.svg | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 docs/images/nerdctl.svg diff --git a/README.md b/README.md index 82fb8741216..3067c3c2bab 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ # nerdctl: Docker-compatible CLI for containerd +![logo](docs/images/nerdctl.svg) + `nerdctl` is a Docker-compatible CLI for [contai**nerd**](https://containerd.io). ✅ Same UI/UX as `docker` diff --git a/docs/images/nerdctl.svg b/docs/images/nerdctl.svg new file mode 100644 index 00000000000..e4d9789beed --- /dev/null +++ b/docs/images/nerdctl.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From 4455d73ad5e6e6875526738e71d701bc2aa4e857 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jul 2024 22:41:56 +0000 Subject: [PATCH 0550/1066] build(deps): bump golang.org/x/term from 0.21.0 to 0.22.0 Bumps [golang.org/x/term](https://github.com/golang/term) from 0.21.0 to 0.22.0. - [Commits](https://github.com/golang/term/compare/v0.21.0...v0.22.0) --- updated-dependencies: - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3a1fae5d515..3ab2255a049 100644 --- a/go.mod +++ b/go.mod @@ -59,8 +59,8 @@ require ( golang.org/x/crypto v0.24.0 golang.org/x/net v0.26.0 golang.org/x/sync v0.7.0 - golang.org/x/sys v0.21.0 - golang.org/x/term v0.21.0 + golang.org/x/sys v0.22.0 + golang.org/x/term v0.22.0 golang.org/x/text v0.16.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 diff --git a/go.sum b/go.sum index 1f82deb2ae6..3a0a4efa641 100644 --- a/go.sum +++ b/go.sum @@ -398,15 +398,15 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= From 1b96d8de018362e82ae6c36780072553b7e100d5 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 4 Jul 2024 18:45:27 -0700 Subject: [PATCH 0551/1066] Make systemctl happy by not passing an explicit signal for kill Signed-off-by: apostasie --- pkg/testutil/testutil.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index d2612271285..62d81a0799e 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -32,7 +32,6 @@ import ( "github.com/Masterminds/semver/v3" "github.com/containerd/containerd/defaults" - "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/infoutil" @@ -153,7 +152,7 @@ func (b *Base) KillDaemon() { b.T.Logf("killing %q", target) cmdKill := exec.Command("systemctl", append(b.systemctlArgs(), - []string{"kill", "-s", "KILL", target}...)...) + []string{"kill", target}...)...) if out, err := cmdKill.CombinedOutput(); err != nil { err = fmt.Errorf("cannot kill %q: %q: %w", target, string(out), err) b.T.Fatal(err) @@ -562,12 +561,6 @@ 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 } From 5267e4ef5d2abf6c7cb332d2b76efe0fa87bd7b5 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 3 Jul 2024 22:23:58 -0700 Subject: [PATCH 0552/1066] Separate and expand information for newcomers on testing Signed-off-by: apostasie --- README.md | 27 +------------- docs/testing.md | 97 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 25 deletions(-) create mode 100644 docs/testing.md diff --git a/README.md b/README.md index 82fb8741216..6950a76745f 100644 --- a/README.md +++ b/README.md @@ -249,32 +249,9 @@ See the header of [`go.mod`](./go.mod) for the minimum supported version of Go. Using `go install github.com/containerd/nerdctl/v2/cmd/nerdctl` is possible, but unrecommended because it does not fill version strings printed in `nerdctl version` -### Test suite +### Testing -#### Running unit tests - -Run `go test -v ./pkg/...` - -#### Running integration test suite against nerdctl - -Run `go test -exec sudo -v ./cmd/nerdctl/...` after `make && sudo make install`. - -For testing rootless mode, `-exec sudo` is not needed. - -To run tests in a container: - -```bash -docker build -t test-integration --target test-integration . -docker run -t --rm --privileged test-integration -``` - -To run a single integration test (in this case, `image_inspect_test`): - -`go test -exec sudo -v ./cmd/nerdctl/main_test.go ./cmd/nerdctl/image_inspect_test.go ` - -#### Running integration test suite against Docker - -Run `go test -exec sudo -v ./cmd/nerdctl/... -args -test.target=docker` to ensure that the test suite is compatible with Docker. +See [testing nerdctl](docs/testing.md). ### Contributing to nerdctl diff --git a/docs/testing.md b/docs/testing.md new file mode 100644 index 00000000000..60fa131a7c4 --- /dev/null +++ b/docs/testing.md @@ -0,0 +1,97 @@ +# Testing nerdctl + +## Lint + +``` +go mod tidy +golangci-lint run ./... +``` + +This works on macOS as well - just pass along `GOOS=linux`. + +## Unit testing + +Run `go test -v ./pkg/...` + +## Integration testing + +### TL;DR + +Be sure to first `make && sudo make install` + +```bash +# Test all with nerdctl (rootless mode, if running go as a non-root user) +go test ./cmd/nerdctl/... + +# Test all with nerdctl rootful +go test -exec sudo ./cmd/nerdctl/... + +# Test all with docker +go test ./cmd/nerdctl/... -args -test.target=docker + +# Test just the tests(s) which names match TestVolume.* +go test ./cmd/nerdctl/... -run "TestVolume.*" +``` + +### Or test in a container + +```bash +docker build -t test-integration --target test-integration . +docker run -t --rm --privileged test-integration +``` + +### Principles + +#### Tests should be parallelized (with best effort) + +##### General case + +It should be possible to parallelize all tests - as such, please make sure you: +- name all resources your test is manipulating after the test identifier (`testutil.Identifier(t)`) +to guarantee your test will not interact with other tests +- do NOT use `os.Setenv` - instead, add into `base.Env` +- use `t.Parallel()` at the beginning of your test (and subtests as well of course) +- in the very exceptional case where your test for some reason can NOT be parallelized, be sure to mark it explicitly as such +with a comment explaining why + +##### For "blanket" destructive operations + +If you are going to use blanket destructive operations (like `prune`), please: +- use a dedicated namespace: instead of calling `testutil.Base`, call `testutil.BaseWithNamespace` +and be sure that your namespace is named after the test id +- remove the namespace in your test `Cleanup` +- since docker does not support namespaces, be sure to: + - only enable `Parallel` if the target is NOT docker: ` if testutil.GetTarget() != testutil.Docker { t.Parallel() }` + - double check that what you do in the default namespace is safe + +#### Clean-up after (and before) yourself + +- do NOT use `defer`, use `t.Cleanup` +- do NOT test the result of commands doing the cleanup - it is fine if they fail, +and they are not test failure per-se - they are here to garbage collect +- you should call your cleanup routine BEFORE doing anything, in case there is any +leftovers from previous runs, typically: +``` +tearDown := func(){ + // Do some cleanup +} + +tearDown() +t.Cleanup(tearDown) +``` + +#### Test what you are testing, and not something else + +You should only test atomically. + +If you are testing `nerdctl volume create`, make sure that your test will not fail +because of changes in `nerdctl volume inspect`. + +That obviously means there are certain things you cannot test "yet". +Just put the right test in the right place with this simple rule of thumb: +if your test requires another nerdctl command to validate the result, then it does +not belong here. Instead, it should be a test for that other command. + +Of course, this is not perfect, and changes in `create` may now fail in `inspect` tests +while `create` could be faulty, but it does beat the alternative, because of this principle: +it is easier to walk *backwards* from a failure. \ No newline at end of file From 35424992d469cf244fc1b80780ffffbbe8ca25bd Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 4 Jul 2024 23:13:40 -0700 Subject: [PATCH 0553/1066] Re-enable project checks for .md only changes Signed-off-by: apostasie --- .github/workflows/project.yml | 31 +++++++++++++++++++++++++++++++ .github/workflows/test.yml | 22 ---------------------- 2 files changed, 31 insertions(+), 22 deletions(-) create mode 100644 .github/workflows/project.yml diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml new file mode 100644 index 00000000000..fa53effc688 --- /dev/null +++ b/.github/workflows/project.yml @@ -0,0 +1,31 @@ +name: project + +on: + push: + branches: + - main + - 'release/**' + pull_request: + +jobs: + project: + name: Project Checks + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4.1.7 + with: + path: src/github.com/containerd/nerdctl + fetch-depth: 100 + - uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + cache-dependency-path: src/github.com/containerd/nerdctl + - uses: containerd/project-checks@v1.1.0 + with: + working-directory: src/github.com/containerd/nerdctl + repo-access-token: ${{ secrets.GITHUB_TOKEN }} + - run: ./hack/verify-no-patent.sh + working-directory: src/github.com/containerd/nerdctl + - run: ./hack/verify-pkg-isolation.sh + working-directory: src/github.com/containerd/nerdctl diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4be68fd297d..fa8b68ca2be 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,28 +13,6 @@ env: GO_VERSION: 1.22.x jobs: - project: - name: Project Checks - runs-on: ubuntu-24.04 - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4.1.7 - with: - path: src/github.com/containerd/nerdctl - fetch-depth: 100 - - uses: actions/setup-go@v5 - with: - go-version: ${{ env.GO_VERSION }} - cache-dependency-path: src/github.com/containerd/nerdctl - - uses: containerd/project-checks@v1.1.0 - with: - working-directory: src/github.com/containerd/nerdctl - repo-access-token: ${{ secrets.GITHUB_TOKEN }} - - run: ./hack/verify-no-patent.sh - working-directory: src/github.com/containerd/nerdctl - - run: ./hack/verify-pkg-isolation.sh - working-directory: src/github.com/containerd/nerdctl - lint: runs-on: ubuntu-24.04 timeout-minutes: 20 From faa28f89f872c7df9c70aef5722c76f9088bdc86 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 4 Jul 2024 20:50:24 -0700 Subject: [PATCH 0554/1066] Workaround flaky save Signed-off-by: apostasie --- cmd/nerdctl/container_run_linux_test.go | 14 +++++++++++++- cmd/nerdctl/image_save_linux_test.go | 6 +++++- cmd/nerdctl/image_save_test.go | 12 ++++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/container_run_linux_test.go b/cmd/nerdctl/container_run_linux_test.go index 15b17ab614c..f85c5618c79 100644 --- a/cmd/nerdctl/container_run_linux_test.go +++ b/cmd/nerdctl/container_run_linux_test.go @@ -42,8 +42,20 @@ import ( func TestRunCustomRootfs(t *testing.T) { testutil.DockerIncompatible(t) - base := testutil.NewBase(t) + // FIXME: root issue is undiagnosed and this is very likely a containerd bug + // It appears that in certain conditions, the proxy content store info method will fail on the layer of the image + // Search for func (pcs *proxyContentStore) ReaderAt(ctx context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) { + // Note that: + // - the problem is still here with containerd and nerdctl v2 + // - it seems to affect images that are tagged multiple times, or that share a layer with another image + // - this test is not parallelized - but the fact that namespacing it solves the problem suggest that something + // happening in the default namespace BEFORE this test is run is SOMETIMES setting conditions that will make this fail + // Possible suspects would be concurrent pulls somehow effing things up w. namespaces. + base := testutil.NewBaseWithNamespace(t, testutil.Identifier(t)) rootfs := prepareCustomRootfs(base, testutil.AlpineImage) + t.Cleanup(func() { + base.Cmd("namespace", "remove", testutil.Identifier(t)).Run() + }) defer os.RemoveAll(rootfs) base.Cmd("run", "--rm", "--rootfs", rootfs, "/bin/cat", "/proc/self/environ").AssertOutContains("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") base.Cmd("run", "--rm", "--entrypoint", "/bin/echo", "--rootfs", rootfs, "echo", "foo").AssertOutExactly("echo foo\n") diff --git a/cmd/nerdctl/image_save_linux_test.go b/cmd/nerdctl/image_save_linux_test.go index be9504ca5d4..82072f46623 100644 --- a/cmd/nerdctl/image_save_linux_test.go +++ b/cmd/nerdctl/image_save_linux_test.go @@ -32,7 +32,11 @@ import ( ) func TestSave(t *testing.T) { - base := testutil.NewBase(t) + // See detailed comment in TestRunCustomRootfs for why we need a separate namespace. + base := testutil.NewBaseWithNamespace(t, testutil.Identifier(t)) + t.Cleanup(func() { + base.Cmd("namespace", "remove", testutil.Identifier(t)).Run() + }) base.Cmd("pull", testutil.AlpineImage).AssertOK() archiveTarPath := filepath.Join(t.TempDir(), "a.tar") base.Cmd("save", "-o", archiveTarPath, testutil.AlpineImage).AssertOK() diff --git a/cmd/nerdctl/image_save_test.go b/cmd/nerdctl/image_save_test.go index 2bfdeeeb2c1..4b37a497b93 100644 --- a/cmd/nerdctl/image_save_test.go +++ b/cmd/nerdctl/image_save_test.go @@ -25,7 +25,11 @@ import ( ) func TestSaveById(t *testing.T) { - base := testutil.NewBase(t) + // See detailed comment in TestRunCustomRootfs for why we need a separate namespace. + base := testutil.NewBaseWithNamespace(t, testutil.Identifier(t)) + t.Cleanup(func() { + base.Cmd("namespace", "remove", testutil.Identifier(t)).Run() + }) base.Cmd("pull", testutil.CommonImage).AssertOK() inspect := base.InspectImage(testutil.CommonImage) var id string @@ -42,7 +46,11 @@ func TestSaveById(t *testing.T) { } func TestSaveByIdWithDifferentNames(t *testing.T) { - base := testutil.NewBase(t) + // See detailed comment in TestRunCustomRootfs for why we need a separate namespace. + base := testutil.NewBaseWithNamespace(t, testutil.Identifier(t)) + t.Cleanup(func() { + base.Cmd("namespace", "remove", testutil.Identifier(t)).Run() + }) base.Cmd("pull", testutil.CommonImage).AssertOK() inspect := base.InspectImage(testutil.CommonImage) var id string From 19ae34b0a8e554cfff63d987897a172377472cc4 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 5 Jul 2024 20:04:26 +0900 Subject: [PATCH 0555/1066] nerdctl run -v: dismiss warning "expected an absolute path, got a relative path" `docker run -v .:/mnt` is allowed since Docker v23 Signed-off-by: Akihiro Suda --- pkg/mountutil/mountutil.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index f8e184033b0..323dacaf980 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -169,7 +169,6 @@ func handleBindMounts(source string, createDir bool) (volumeSpec, error) { // Handle relative paths if !filepath.IsAbs(source) { - log.L.Warnf("expected an absolute path, got a relative path %q (allowed for nerdctl, but disallowed for Docker, so unrecommended)", source) absPath, err := filepath.Abs(source) if err != nil { return res, fmt.Errorf("failed to get the absolute path of %q: %w", source, err) From e0248a4dd0f92ebf8c328c35faf1c53a30e1092b Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 5 Jul 2024 21:10:29 +0900 Subject: [PATCH 0556/1066] Dependabot: add groups Groupify relevant repos to reduce the number of the PRs Signed-off-by: Akihiro Suda --- .github/dependabot.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0fedec74806..0c21fa19f87 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,6 +14,26 @@ updates: directory: "/" # Location of package manifests schedule: interval: "daily" + groups: + golang-x: + patterns: + - "golang.org/x/*" + moby-sys: + patterns: + - "github.com/moby/sys/*" + docker: + patterns: + - "github.com/docker/docker" + - "github.com/docker/cli" + containerd: + patterns: + - "github.com/containerd/containerd" + - "github.com/containerd/containerd/api" + stargz: + patterns: + - "github.com/containerd/stargz-snapshotter" + - "github.com/containerd/stargz-snapshotter/estargz" + - "github.com/containerd/stargz-snapshotter/ipfs" # Dependencies listed in .github/workflows/*.yml - package-ecosystem: "github-actions" From 019cd003b0f9d626d8c87c5e7e35cbf5b177feba Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Fri, 5 Jul 2024 19:53:34 +0900 Subject: [PATCH 0557/1066] test-integration-rootless: enable BuildKit for RootlessKit v2 BuildKit has been disabled in test-integration-rootless due to the issue 622, but this should not happen with RootlessKit v2 (detach-netns mode). Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 10 +++++++++- cmd/nerdctl/builder_linux_test.go | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fa8b68ca2be..b6693a2f6a7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -218,13 +218,21 @@ jobs: run: docker run --privileged --rm tonistiigi/binfmt --install all - name: "Prepare (network driver=slirp4netns, port driver=builtin)" run: DOCKER_BUILDKIT=1 docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} --build-arg ROOTLESSKIT_VERSION=${ROOTLESSKIT_VERSION} . + - name: "Disable BuildKit for RootlessKit v1 (workaround for issue #622)" + run: | + # https://github.com/containerd/nerdctl/issues/622 + WORKAROUND_ISSUE_622= + if echo "${ROOTLESSKIT_VERSION}" | grep -q v1; then + WORKAROUND_ISSUE_622=1 + fi + echo "WORKAROUND_ISSUE_622=${WORKAROUND_ISSUE_622}" >>$GITHUB_ENV - name: "Test (network driver=slirp4netns, port driver=builtin)" uses: nick-fields/retry@v3 with: timeout_minutes: 30 max_attempts: 2 retry_on: error - command: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=1 ${TEST_TARGET} + command: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=${WORKAROUND_ISSUE_622} ${TEST_TARGET} cross: runs-on: ubuntu-24.04 diff --git a/cmd/nerdctl/builder_linux_test.go b/cmd/nerdctl/builder_linux_test.go index ef86ede7047..42ae8376945 100644 --- a/cmd/nerdctl/builder_linux_test.go +++ b/cmd/nerdctl/builder_linux_test.go @@ -24,6 +24,7 @@ import ( "path/filepath" "testing" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) @@ -43,6 +44,9 @@ CMD ["echo", "nerdctl-builder-debug-test-string"] func TestBuildWithPull(t *testing.T) { testutil.DockerIncompatible(t) + if rootlessutil.IsRootless() { + t.Skipf("skipped because the test needs a custom buildkitd config") + } testutil.RequiresBuild(t) oldImage := testutil.BusyboxImage From 15191775af9edfd40882440ef6fb4e29f1aa32a6 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 20 Jun 2024 16:37:58 -0700 Subject: [PATCH 0558/1066] Volume QA: inspect, prune, create and other volume fixes Signed-off-by: apostasie --- cmd/nerdctl/namespace.go | 4 +- cmd/nerdctl/system_prune_linux_test.go | 4 + cmd/nerdctl/volume_create.go | 9 + cmd/nerdctl/volume_create_test.go | 161 ++++- cmd/nerdctl/volume_inspect.go | 2 +- cmd/nerdctl/volume_inspect_test.go | 275 +++++++- cmd/nerdctl/volume_list_test.go | 661 ++++++++++-------- cmd/nerdctl/volume_namespace_test.go | 150 ++++ cmd/nerdctl/volume_prune_linux_test.go | 135 +++- cmd/nerdctl/volume_remove_linux_test.go | 119 +++- pkg/cmd/container/create.go | 14 +- pkg/cmd/container/remove.go | 8 + pkg/cmd/container/run_mount.go | 10 +- pkg/cmd/volume/create.go | 4 - pkg/cmd/volume/inspect.go | 29 +- pkg/cmd/volume/prune.go | 25 +- pkg/cmd/volume/rm.go | 40 +- pkg/composer/up_volume.go | 3 + pkg/lockutil/lockutil_unix.go | 30 +- pkg/lockutil/lockutil_windows.go | 21 + pkg/mountutil/mountutil.go | 15 +- .../mountutilmock/volumestore.mock.go | 26 +- pkg/mountutil/volumestore/volumestore.go | 297 +++++--- 23 files changed, 1505 insertions(+), 537 deletions(-) create mode 100644 cmd/nerdctl/volume_namespace_test.go diff --git a/cmd/nerdctl/namespace.go b/cmd/nerdctl/namespace.go index b60e89ccd37..20d188f3f57 100644 --- a/cmd/nerdctl/namespace.go +++ b/cmd/nerdctl/namespace.go @@ -113,11 +113,11 @@ func namespaceLsAction(cmd *cobra.Command, args []string) error { } numImages = len(images) - volStore, err := volumestore.Path(dataStore, ns) + volStore, err := volumestore.New(dataStore, ns) if err != nil { log.L.Warn(err) } else { - volEnts, err := os.ReadDir(volStore) + volEnts, err := volStore.List(false) if err != nil { if !os.IsNotExist(err) { log.L.Warn(err) diff --git a/cmd/nerdctl/system_prune_linux_test.go b/cmd/nerdctl/system_prune_linux_test.go index c1e91658f31..8356ccd3adc 100644 --- a/cmd/nerdctl/system_prune_linux_test.go +++ b/cmd/nerdctl/system_prune_linux_test.go @@ -32,6 +32,10 @@ import ( func TestSystemPrune(t *testing.T) { testutil.RequiresBuild(t) + // FIXME: using a dedicated namespace does not work with rootful (because of buildkit running) + // t.Parallel() + // namespaceID := testutil.Identifier(t) + // base := testutil.NewBaseWithNamespace(t, namespaceID) base := testutil.NewBase(t) base.Cmd("container", "prune", "-f").AssertOK() base.Cmd("network", "prune", "-f").AssertOK() diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume_create.go index 972d5fc0359..9c8bfda26f1 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume_create.go @@ -17,6 +17,9 @@ package main import ( + "fmt" + + "github.com/containerd/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" @@ -45,6 +48,12 @@ func processVolumeCreateOptions(cmd *cobra.Command) (types.VolumeCreateOptions, if err != nil { return types.VolumeCreateOptions{}, err } + for _, label := range labels { + if label == "" { + return types.VolumeCreateOptions{}, fmt.Errorf("labels cannot be empty (%w)", errdefs.ErrInvalidArgument) + } + } + return types.VolumeCreateOptions{ GOptions: globalOptions, Labels: labels, diff --git a/cmd/nerdctl/volume_create_test.go b/cmd/nerdctl/volume_create_test.go index f8f5997b501..6e599ec2567 100644 --- a/cmd/nerdctl/volume_create_test.go +++ b/cmd/nerdctl/volume_create_test.go @@ -19,40 +19,151 @@ package main import ( "testing" + "github.com/containerd/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" ) -// Test TestVolumeCreate for creating volume with given name. func TestVolumeCreate(t *testing.T) { - base := testutil.NewBase(t) - testVolume := testutil.Identifier(t) + t.Parallel() - base.Cmd("volume", "create", testVolume).AssertOK() - defer base.Cmd("volume", "rm", "-f", testVolume).Run() + base := testutil.NewBase(t) - base.Cmd("volume", "list").AssertOutContains(testVolume) -} + malformed := errdefs.ErrInvalidArgument.Error() + atMost := "at most 1 arg" + exitCodeVariant := 1 + if base.Target == testutil.Docker { + malformed = "invalid" + exitCodeVariant = 125 + } -// Test TestVolumeCreateTooManyArgs for creating volume with too many args. -func TestVolumeCreateTooManyArgs(t *testing.T) { - base := testutil.NewBase(t) + testCases := []struct { + description string + command func(tID string) *testutil.Cmd + tearUp func(tID string) + tearDown func(tID string) + expected func(tID string) icmd.Expected + inspect func(t *testing.T, stdout string, stderr string) + dockerIncompatible bool + }{ + { + description: "arg missing should create anonymous volume", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "create") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + } + }, + }, + { + description: "invalid identifier should fail", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "create", "∞") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: malformed, + } + }, + }, + { + description: "too many args should fail", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "create", "too", "many") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: atMost, + } + }, + }, + { + description: "success", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "create", tID) + }, + tearDown: func(tID string) { + base.Cmd("volume", "rm", "-f", tID).Run() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + Out: tID, + } + }, + }, + { + description: "success with labels", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "create", "--label", "foo1=baz1", "--label", "foo2=baz2", tID) + }, + tearDown: func(tID string) { + base.Cmd("volume", "rm", "-f", tID).Run() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + Out: tID, + } + }, + }, + { + description: "invalid labels", + command: func(tID string) *testutil.Cmd { + // See https://github.com/containerd/nerdctl/issues/3126 + return base.Cmd("volume", "create", "--label", "a", "--label", "", tID) + }, + tearDown: func(tID string) { + base.Cmd("volume", "rm", "-f", tID).Run() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: exitCodeVariant, + Err: malformed, + } + }, + }, + { + description: "creating already existing volume should succeed", + command: func(tID string) *testutil.Cmd { + base.Cmd("volume", "create", tID).AssertOK() + return base.Cmd("volume", "create", tID) + }, + tearDown: func(tID string) { + base.Cmd("volume", "rm", "-f", tID).Run() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + Out: tID, + } + }, + }, + } - base.Cmd("volume", "create", "too", "many").AssertFail() -} + for _, test := range testCases { + currentTest := test + t.Run(currentTest.description, func(tt *testing.T) { + tt.Parallel() -// Test TestVolumeCreateWithLabels for creating volume with given labels. -func TestVolumeCreateWithLabels(t *testing.T) { - base := testutil.NewBase(t) - testVolume := testutil.Identifier(t) + tID := testutil.Identifier(tt) - base.Cmd("volume", "create", testVolume, "--label", "foo1=baz1", "--label", "foo2=baz2").AssertOK() - defer base.Cmd("volume", "rm", "-f", testVolume).Run() + if currentTest.tearDown != nil { + currentTest.tearDown(tID) + tt.Cleanup(func() { + currentTest.tearDown(tID) + }) + } + if currentTest.tearUp != nil { + currentTest.tearUp(tID) + } - inspect := base.InspectVolume(testVolume) - inspectNerdctlLabels := *inspect.Labels - expected := make(map[string]string, 2) - expected["foo1"] = "baz1" - expected["foo2"] = "baz2" - assert.DeepEqual(base.T, expected, inspectNerdctlLabels) + cmd := currentTest.command(tID) + cmd.Assert(currentTest.expected(tID)) + }) + } } diff --git a/cmd/nerdctl/volume_inspect.go b/cmd/nerdctl/volume_inspect.go index 0eee9c41231..302b047f734 100644 --- a/cmd/nerdctl/volume_inspect.go +++ b/cmd/nerdctl/volume_inspect.go @@ -66,7 +66,7 @@ func volumeInspectAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - return volume.Inspect(args, options) + return volume.Inspect(cmd.Context(), args, options) } func volumeInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { diff --git a/cmd/nerdctl/volume_inspect_test.go b/cmd/nerdctl/volume_inspect_test.go index 24fff144a77..13dde1e8585 100644 --- a/cmd/nerdctl/volume_inspect_test.go +++ b/cmd/nerdctl/volume_inspect_test.go @@ -18,48 +18,265 @@ package main import ( "crypto/rand" + "encoding/json" + "fmt" "os" "path/filepath" + "strings" "testing" + "github.com/containerd/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" ) -func TestVolumeInspectContainsLabels(t *testing.T) { - t.Parallel() - testVolume := testutil.Identifier(t) - - base := testutil.NewBase(t) - base.Cmd("volume", "create", "--label", "tag=testVolume", testVolume).AssertOK() - defer base.Cmd("volume", "rm", "-f", testVolume).Run() - - inspect := base.InspectVolume(testVolume) - inspectNerdctlLabels := (*inspect.Labels) - expected := make(map[string]string, 1) - expected["tag"] = "testVolume" - assert.DeepEqual(base.T, expected, inspectNerdctlLabels) +func createFileWithSize(base *testutil.Base, vol string, size int64) { + v := base.InspectVolume(vol) + token := make([]byte, size) + _, _ = rand.Read(token) + err := os.WriteFile(filepath.Join(v.Mountpoint, "test-file"), token, 0644) + assert.NilError(base.T, err) } -func TestVolumeInspectSize(t *testing.T) { - testutil.DockerIncompatible(t) +func TestVolumeInspect(t *testing.T) { t.Parallel() - testVolume := testutil.Identifier(t) + base := testutil.NewBase(t) - base.Cmd("volume", "create", testVolume).AssertOK() - defer base.Cmd("volume", "rm", "-f", testVolume).Run() + tID := testutil.Identifier(t) var size int64 = 1028 - createFileWithSize(t, testVolume, size) - volumeWithSize := base.InspectVolume(testVolume, []string{"--size"}...) - assert.Equal(t, volumeWithSize.Size, size) -} -func createFileWithSize(t *testing.T, volume string, bytes int64) { - base := testutil.NewBase(t) - v := base.InspectVolume(volume) - token := make([]byte, bytes) - rand.Read(token) - err := os.WriteFile(filepath.Join(v.Mountpoint, "test-file"), token, 0644) - assert.NilError(t, err) + malformed := errdefs.ErrInvalidArgument.Error() + notFound := errdefs.ErrNotFound.Error() + requireArg := "requires at least 1 arg" + if base.Target == testutil.Docker { + malformed = "no such volume" + notFound = "no such volume" + } + + tearUp := func(t *testing.T) { + base.Cmd("volume", "create", tID).AssertOK() + base.Cmd("volume", "create", "--label", "foo=fooval", "--label", "bar=barval", tID+"-second").AssertOK() + + // Obviously note here that if inspect code gets totally hosed, this entire suite will + // probably fail right here on the tearUp instead of actually testing something + createFileWithSize(base, tID, size) + } + + tearDown := func(t *testing.T) { + base.Cmd("volume", "rm", "-f", tID).Run() + base.Cmd("volume", "rm", "-f", tID+"-second").Run() + } + + tearDown(t) + t.Cleanup(func() { + tearDown(t) + }) + tearUp(t) + + testCases := []struct { + description string + command func(tID string) *testutil.Cmd + tearUp func(tID string) + tearDown func(tID string) + expected func(tID string) icmd.Expected + inspect func(t *testing.T, stdout string, stderr string) + dockerIncompatible bool + }{ + { + description: "arg missing should fail", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "inspect") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: requireArg, + } + }, + }, + { + description: "invalid identifier should fail", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "inspect", "∞") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: malformed, + } + }, + }, + { + description: "non existent volume should fail", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "inspect", "doesnotexist") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: notFound, + } + }, + }, + { + description: "success", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "inspect", tID) + }, + tearDown: func(tID string) { + base.Cmd("volume", "rm", "-f", tID) + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + Out: tID, + } + }, + inspect: func(t *testing.T, stdout string, stderr string) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))) + assert.Assert(t, dc[0].Name == tID, fmt.Sprintf("expected name to be %q (was %q)", tID, dc[0].Name)) + assert.Assert(t, dc[0].Labels == nil, fmt.Sprintf("expected labels to be nil and were %v", dc[0].Labels)) + }, + }, + { + description: "inspect labels", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "inspect", tID+"-second") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + Out: tID, + } + }, + inspect: func(t *testing.T, stdout string, stderr string) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + + labels := *dc[0].Labels + assert.Assert(t, len(labels) == 2, fmt.Sprintf("two results, not %d", len(labels))) + assert.Assert(t, labels["foo"] == "fooval", fmt.Sprintf("label foo should be fooval, not %s", labels["foo"])) + assert.Assert(t, labels["bar"] == "barval", fmt.Sprintf("label bar should be barval, not %s", labels["bar"])) + }, + }, + { + description: "inspect size", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "inspect", "--size", tID) + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + Out: tID, + } + }, + inspect: func(t *testing.T, stdout string, stderr string) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, dc[0].Size == size, fmt.Sprintf("expected size to be %d (was %d)", size, dc[0].Size)) + }, + dockerIncompatible: true, + }, + { + description: "multi success", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "inspect", tID, tID+"-second") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + } + }, + inspect: func(t *testing.T, stdout string, stderr string) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, len(dc) == 2, fmt.Sprintf("two results, not %d", len(dc))) + assert.Assert(t, dc[0].Name == tID, fmt.Sprintf("expected name to be %q (was %q)", tID, dc[0].Name)) + assert.Assert(t, dc[1].Name == tID+"-second", fmt.Sprintf("expected name to be %q (was %q)", tID+"-second", dc[1].Name)) + }, + }, + { + description: "part success multi", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "inspect", "invalid∞", "nonexistent", tID) + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Out: tID, + Err: notFound, + } + }, + inspect: func(t *testing.T, stdout string, stderr string) { + assert.Assert(t, strings.Contains(stderr, notFound)) + assert.Assert(t, strings.Contains(stderr, malformed)) + + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))) + assert.Assert(t, dc[0].Name == tID, fmt.Sprintf("expected name to be %q (was %q)", tID, dc[0].Name)) + }, + }, + { + description: "multi failure", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "inspect", "invalid∞", "nonexistent") + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + } + }, + inspect: func(t *testing.T, stdout string, stderr string) { + assert.Assert(t, strings.Contains(stderr, notFound)) + assert.Assert(t, strings.Contains(stderr, malformed)) + }, + }, + } + + for _, test := range testCases { + currentTest := test + t.Run(currentTest.description, func(tt *testing.T) { + if currentTest.dockerIncompatible { + testutil.DockerIncompatible(tt) + } + + tt.Parallel() + + // We use the main test tID here + if currentTest.tearDown != nil { + currentTest.tearDown(tID) + tt.Cleanup(func() { + currentTest.tearDown(tID) + }) + } + if currentTest.tearUp != nil { + currentTest.tearUp(tID) + } + + // See https://github.com/containerd/nerdctl/issues/3130 + // We run first to capture the underlying icmd command and output + cmd := currentTest.command(tID) + res := cmd.Run() + cmd.Assert(currentTest.expected(tID)) + if currentTest.inspect != nil { + currentTest.inspect(tt, res.Stdout(), res.Stderr()) + } + }) + } } diff --git a/cmd/nerdctl/volume_list_test.go b/cmd/nerdctl/volume_list_test.go index 9b88e13eac9..cbab079ef5c 100644 --- a/cmd/nerdctl/volume_list_test.go +++ b/cmd/nerdctl/volume_list_test.go @@ -33,17 +33,26 @@ func TestVolumeLs(t *testing.T) { testutil.DockerIncompatible(t) var vol1, vol2, vol3 = tID + "vol-1", tID + "vol-2", tID + "empty" - base.Cmd("volume", "create", vol1).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol1).Run() - base.Cmd("volume", "create", vol2).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol2).Run() - - base.Cmd("volume", "create", vol3).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol3).Run() - - createFileWithSize(t, vol1, 102400) - createFileWithSize(t, vol2, 204800) + tearDown := func() { + base.Cmd("volume", "rm", "-f", vol1).Run() + base.Cmd("volume", "rm", "-f", vol2).Run() + base.Cmd("volume", "rm", "-f", vol3).Run() + } + + tearUp := func() { + base.Cmd("volume", "create", vol1).AssertOK() + base.Cmd("volume", "create", vol2).AssertOK() + base.Cmd("volume", "create", vol3).AssertOK() + createFileWithSize(base, vol1, 102400) + createFileWithSize(base, vol2, 204800) + } + + tearDown() + t.Cleanup(func() { + tearDown() + }) + tearUp() base.Cmd("volume", "ls", "--size").AssertOutWithFunc(func(stdout string) error { var lines = strings.Split(strings.TrimSpace(stdout), "\n") @@ -89,175 +98,238 @@ func TestVolumeLsFilter(t *testing.T) { var vol1, vol2, vol3, vol4 = tID + "vol-1", tID + "vol-2", tID + "vol-3", tID + "vol-4" var label1, label2, label3, label4 = tID + "=label-1", tID + "=label-2", tID + "=label-3", tID + "-group=label-4" - base.Cmd("volume", "create", "--label="+label1, "--label="+label4, vol1).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol1).Run() - - base.Cmd("volume", "create", "--label="+label2, "--label="+label4, vol2).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol2).Run() - - base.Cmd("volume", "create", "--label="+label3, vol3).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol3).Run() - - base.Cmd("volume", "create", vol4).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol4).Run() - - base.Cmd("volume", "ls", "--quiet").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 4 { - return errors.New("expected at least 4 lines") - } - volNames := map[string]struct{}{ - vol1: {}, - vol2: {}, - vol3: {}, - vol4: {}, - } - - var numMatches = 0 - for _, name := range lines { - _, ok := volNames[name] - if !ok { - continue - } - numMatches++ - } - if len(volNames) != numMatches { - return fmt.Errorf("expected %d volumes, got: %d", len(volNames), numMatches) - } - return nil - }) - - base.Cmd("volume", "ls", "--quiet", "--filter", "label="+tID).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 3 { - return errors.New("expected at least 3 lines") - } - volNames := map[string]struct{}{ - vol1: {}, - vol2: {}, - vol3: {}, - } - - for _, name := range lines { - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil - }) - - base.Cmd("volume", "ls", "--quiet", "--filter", "label="+label2).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 1 { - return errors.New("expected at least 1 lines") - } - volNames := map[string]struct{}{ - vol2: {}, - } - - for _, name := range lines { - if name == "" { - continue - } - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil - }) - - base.Cmd("volume", "ls", "--quiet", "--filter", "label="+tID+"=").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) > 0 { - for _, name := range lines { - if name != "" { - return fmt.Errorf("unexpected volumes %d found", len(lines)) - } - } - } - return nil - }) - - base.Cmd("volume", "ls", "--quiet", "--filter", "label="+label1, "--filter", "label="+label2).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) > 0 { - for _, name := range lines { - if name != "" { - return fmt.Errorf("unexpected volumes %d found", len(lines)) - } - } - } - return nil - }) - - base.Cmd("volume", "ls", "--quiet", "--filter", "label="+tID, "--filter", "label="+label4).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 2 { - return errors.New("expected at least 2 lines") - } - volNames := map[string]struct{}{ - vol1: {}, - vol2: {}, - } - for _, name := range lines { - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil + tearDown := func() { + base.Cmd("volume", "rm", "-f", vol1).Run() + base.Cmd("volume", "rm", "-f", vol2).Run() + base.Cmd("volume", "rm", "-f", vol3).Run() + base.Cmd("volume", "rm", "-f", vol4).Run() + } + + tearUp := func() { + base.Cmd("volume", "create", "--label="+label1, "--label="+label4, vol1).AssertOK() + base.Cmd("volume", "create", "--label="+label2, "--label="+label4, vol2).AssertOK() + base.Cmd("volume", "create", "--label="+label3, vol3).AssertOK() + base.Cmd("volume", "create", vol4).AssertOK() + } + + tearDown() + t.Cleanup(func() { + tearDown() }) + tearUp() + + testCases := []struct { + description string + command func(tID string) + }{ + { + description: "no filter", + command: func(tID string) { + base.Cmd("volume", "ls", "--quiet").AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 4 { + return errors.New("expected at least 4 lines") + } + volNames := map[string]struct{}{ + vol1: {}, + vol2: {}, + vol3: {}, + vol4: {}, + } + + var numMatches = 0 + for _, name := range lines { + _, ok := volNames[name] + if !ok { + continue + } + numMatches++ + } + if len(volNames) != numMatches { + return fmt.Errorf("expected %d volumes, got: %d", len(volNames), numMatches) + } + return nil + }) + }, + }, + { + description: "label=" + tID, + command: func(tID string) { + base.Cmd("volume", "ls", "--quiet", "--filter", "label="+tID).AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 3 { + return errors.New("expected at least 3 lines") + } + volNames := map[string]struct{}{ + vol1: {}, + vol2: {}, + vol3: {}, + } + + for _, name := range lines { + _, ok := volNames[name] + if !ok { + return fmt.Errorf("unexpected volume %s found", name) + } + } + return nil + }) + }, + }, + { + description: "label=" + label2, + command: func(tID string) { + base.Cmd("volume", "ls", "--quiet", "--filter", "label="+label2).AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 1 { + return errors.New("expected at least 1 lines") + } + volNames := map[string]struct{}{ + vol2: {}, + } + + for _, name := range lines { + if name == "" { + continue + } + _, ok := volNames[name] + if !ok { + return fmt.Errorf("unexpected volume %s found", name) + } + } + return nil + }) + }, + }, + { + description: "label=" + tID + "=", + command: func(tID string) { + base.Cmd("volume", "ls", "--quiet", "--filter", "label="+tID+"=").AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) > 0 { + for _, name := range lines { + if name != "" { + return fmt.Errorf("unexpected volumes %d found", len(lines)) + } + } + } + return nil + }) + }, + }, + { + description: "label=" + label1 + " label=" + label2, + command: func(tID string) { + base.Cmd("volume", "ls", "--quiet", "--filter", "label="+label1, "--filter", "label="+label2).AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) > 0 { + for _, name := range lines { + if name != "" { + return fmt.Errorf("unexpected volumes %d found", len(lines)) + } + } + } + return nil + }) + + }, + }, + { + description: "label=" + tID + " label=" + label4, + command: func(tID string) { + base.Cmd("volume", "ls", "--quiet", "--filter", "label="+tID, "--filter", "label="+label4).AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 2 { + return errors.New("expected at least 2 lines") + } + volNames := map[string]struct{}{ + vol1: {}, + vol2: {}, + } + + for _, name := range lines { + _, ok := volNames[name] + if !ok { + return fmt.Errorf("unexpected volume %s found", name) + } + } + return nil + }) + }, + }, + { + description: "name=" + vol1, + command: func(tID string) { + base.Cmd("volume", "ls", "--quiet", "--filter", "name="+vol1).AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 1 { + return errors.New("expected at least 1 lines") + } + volNames := map[string]struct{}{ + vol1: {}, + } + + for _, name := range lines { + _, ok := volNames[name] + if !ok { + return fmt.Errorf("unexpected volume %s found", name) + } + } + return nil + }) + }, + }, + { + description: "name=vol-3", + command: func(tID string) { + base.Cmd("volume", "ls", "--quiet", "--filter", "name=vol-3"). + AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 1 { + return errors.New("expected at least 1 lines") + } + volNames := map[string]struct{}{ + vol3: {}, + } + + for _, name := range lines { + _, ok := volNames[name] + if !ok { + return fmt.Errorf("unexpected volume %s found", name) + } + } + return nil + }) + }, + }, + { + description: "name=vol2 name=vol1", + command: func(tID string) { + base.Cmd("volume", "ls", "--quiet", "--filter", "name=vol2", "--filter", "name=vol1"). + AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) > 0 { + for _, name := range lines { + if name != "" { + return fmt.Errorf("unexpected volumes %d found", len(lines)) + } + } + } + return nil + }) + }, + }, + } + + for _, test := range testCases { + currentTest := test + t.Run(currentTest.description, func(tt *testing.T) { + tt.Parallel() + currentTest.command(tID) + }) + } - base.Cmd("volume", "ls", "--quiet", "--filter", "name="+vol1).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 1 { - return errors.New("expected at least 1 lines") - } - volNames := map[string]struct{}{ - vol1: {}, - } - - for _, name := range lines { - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil - }) - - base.Cmd("volume", "ls", "--quiet", "--filter", "name=vol-3").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 1 { - return errors.New("expected at least 1 lines") - } - volNames := map[string]struct{}{ - vol3: {}, - } - - for _, name := range lines { - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil - }) - - base.Cmd("volume", "ls", "--quiet", "--filter", "name=vol2", "--filter", "name=vol1").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) > 0 { - for _, name := range lines { - if name != "" { - return fmt.Errorf("unexpected volumes %d found", len(lines)) - } - } - } - return nil - }) } func TestVolumeLsFilterSize(t *testing.T) { @@ -267,107 +339,142 @@ func TestVolumeLsFilterSize(t *testing.T) { var vol1, vol2, vol3, vol4 = tID + "volsize-1", tID + "volsize-2", tID + "volsize-3", tID + "volsize-4" var label1, label2, label3, label4 = tID + "=label-1", tID + "=label-2", tID + "=label-3", tID + "-group=label-4" - base.Cmd("volume", "create", "--label="+label1, "--label="+label4, vol1).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol1).Run() - - base.Cmd("volume", "create", "--label="+label2, "--label="+label4, vol2).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol2).Run() - - base.Cmd("volume", "create", "--label="+label3, vol3).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol3).Run() - - base.Cmd("volume", "create", vol4).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol4).Run() - - createFileWithSize(t, vol1, 409600) - createFileWithSize(t, vol2, 1024000) - createFileWithSize(t, vol3, 409600) - createFileWithSize(t, vol4, 1024000) - - base.Cmd("volume", "ls", "--size", "--filter", "size=1024000").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 3 { - return errors.New("expected at least 3 lines") - } - - var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") - var err = tab.ParseHeader(lines[0]) - if err != nil { - return err - } - volNames := map[string]struct{}{ - vol2: {}, - vol4: {}, - } - for _, line := range lines { - name, _ := tab.ReadRow(line, "VOLUME NAME") - if name == "VOLUME NAME" { - continue - } - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil - }) - - base.Cmd("volume", "ls", "--size", "--filter", "size>=1024000", "--filter", "size<=2048000").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 3 { - return errors.New("expected at least 3 lines") - } - - var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") - var err = tab.ParseHeader(lines[0]) - if err != nil { - return err - } - volNames := map[string]struct{}{ - vol2: {}, - vol4: {}, - } - - for _, line := range lines { - name, _ := tab.ReadRow(line, "VOLUME NAME") - if name == "VOLUME NAME" { - continue - } - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil - }) - - base.Cmd("volume", "ls", "--size", "--filter", "size>204800", "--filter", "size<1024000").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 3 { - return errors.New("expected at least 3 lines") - } - - var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") - var err = tab.ParseHeader(lines[0]) - if err != nil { - return err - } - volNames := map[string]struct{}{ - vol1: {}, - vol3: {}, - } - - for _, line := range lines { - name, _ := tab.ReadRow(line, "VOLUME NAME") - if name == "VOLUME NAME" { - continue - } - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil + tearDown := func() { + base.Cmd("volume", "rm", "-f", vol1).Run() + base.Cmd("volume", "rm", "-f", vol2).Run() + base.Cmd("volume", "rm", "-f", vol3).Run() + base.Cmd("volume", "rm", "-f", vol4).Run() + } + + tearUp := func() { + base.Cmd("volume", "create", "--label="+label1, "--label="+label4, vol1).AssertOK() + base.Cmd("volume", "create", "--label="+label2, "--label="+label4, vol2).AssertOK() + base.Cmd("volume", "create", "--label="+label3, vol3).AssertOK() + base.Cmd("volume", "create", vol4).AssertOK() + + createFileWithSize(base, vol1, 409600) + createFileWithSize(base, vol2, 1024000) + createFileWithSize(base, vol3, 409600) + createFileWithSize(base, vol4, 1024000) + } + + tearDown() + t.Cleanup(func() { + tearDown() }) + tearUp() + + testCases := []struct { + description string + command func(tID string) + }{ + { + description: "size=1024000", + command: func(tID string) { + base.Cmd("volume", "ls", "--size", "--filter", "size=1024000").AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 3 { + return errors.New("expected at least 3 lines") + } + + var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") + var err = tab.ParseHeader(lines[0]) + if err != nil { + return err + } + volNames := map[string]struct{}{ + vol2: {}, + vol4: {}, + } + + for _, line := range lines { + name, _ := tab.ReadRow(line, "VOLUME NAME") + if name == "VOLUME NAME" { + continue + } + _, ok := volNames[name] + if !ok { + return fmt.Errorf("unexpected volume %s found", name) + } + } + return nil + }) + }, + }, + { + description: "size>=1024000 size<=2048000", + command: func(tID string) { + base.Cmd("volume", "ls", "--size", "--filter", "size>=1024000", "--filter", "size<=2048000").AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 3 { + return errors.New("expected at least 3 lines") + } + + var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") + var err = tab.ParseHeader(lines[0]) + if err != nil { + return err + } + volNames := map[string]struct{}{ + vol2: {}, + vol4: {}, + } + + for _, line := range lines { + name, _ := tab.ReadRow(line, "VOLUME NAME") + if name == "VOLUME NAME" { + continue + } + _, ok := volNames[name] + if !ok { + return fmt.Errorf("unexpected volume %s found", name) + } + } + return nil + }) + }, + }, + { + description: "size>204800 size<1024000", + command: func(tID string) { + base.Cmd("volume", "ls", "--size", "--filter", "size>204800", "--filter", "size<1024000").AssertOutWithFunc(func(stdout string) error { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 3 { + return errors.New("expected at least 3 lines") + } + + var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") + var err = tab.ParseHeader(lines[0]) + if err != nil { + return err + } + volNames := map[string]struct{}{ + vol1: {}, + vol3: {}, + } + + for _, line := range lines { + name, _ := tab.ReadRow(line, "VOLUME NAME") + if name == "VOLUME NAME" { + continue + } + _, ok := volNames[name] + if !ok { + return fmt.Errorf("unexpected volume %s found", name) + } + } + return nil + }) + }, + }, + } + + for _, test := range testCases { + currentTest := test + t.Run(currentTest.description, func(tt *testing.T) { + tt.Parallel() + currentTest.command(tID) + }) + } } diff --git a/cmd/nerdctl/volume_namespace_test.go b/cmd/nerdctl/volume_namespace_test.go new file mode 100644 index 00000000000..745025dba45 --- /dev/null +++ b/cmd/nerdctl/volume_namespace_test.go @@ -0,0 +1,150 @@ +/* + 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 ( + "testing" + + "github.com/containerd/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "gotest.tools/v3/icmd" +) + +func TestVolumeNamespace(t *testing.T) { + testutil.DockerIncompatible(t) + + t.Parallel() + + base := testutil.NewBase(t) + tID := testutil.Identifier(t) + otherBase := testutil.NewBaseWithNamespace(t, tID+"-1") + thirdBase := testutil.NewBaseWithNamespace(t, tID+"-2") + + tearUp := func(t *testing.T) { + base.Cmd("volume", "create", tID).AssertOK() + } + + tearDown := func(t *testing.T) { + base.Cmd("volume", "rm", "-f", tID).Run() + otherBase.Cmd("namespace", "rm", "-f", tID+"-1").Run() + thirdBase.Cmd("namespace", "rm", "-f", tID+"-2").Run() + } + + tearDown(t) + t.Cleanup(func() { + tearDown(t) + }) + tearUp(t) + + testCases := []struct { + description string + command func(tID string) *testutil.Cmd + tearUp func(tID string) + tearDown func(tID string) + expected func(tID string) icmd.Expected + inspect func(t *testing.T, stdout string, stderr string) + dockerIncompatible bool + }{ + { + description: "inspect another namespace volume should fail", + command: func(tID string) *testutil.Cmd { + return otherBase.Cmd("volume", "inspect", tID) + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: errdefs.ErrNotFound.Error(), + } + }, + }, + { + description: "remove another namespace volume should fail", + command: func(tID string) *testutil.Cmd { + return otherBase.Cmd("volume", "remove", tID) + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: errdefs.ErrNotFound.Error(), + } + }, + }, + { + description: "prune should leave other namespace untouched", + command: func(tID string) *testutil.Cmd { + return otherBase.Cmd("volume", "prune", "-a", "-f") + }, + tearDown: func(tID string) { + // Assert that the volume is here in the base namespace + // both before and after the prune command + base.Cmd("volume", "inspect", tID).AssertOK() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + } + }, + }, + { + description: "create with namespace should work", + command: func(tID string) *testutil.Cmd { + return thirdBase.Cmd("volume", "create", tID) + }, + tearDown: func(tID string) { + thirdBase.Cmd("volume", "remove", "-f", tID).Run() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + Out: tID, + } + }, + }, + } + + for _, test := range testCases { + currentTest := test + t.Run(currentTest.description, func(tt *testing.T) { + if currentTest.dockerIncompatible { + testutil.DockerIncompatible(tt) + } + + tt.Parallel() + + // Note that here we are using the main test tID + // since we are testing against the volume created in it + if currentTest.tearDown != nil { + currentTest.tearDown(tID) + tt.Cleanup(func() { + currentTest.tearDown(tID) + }) + } + if currentTest.tearUp != nil { + currentTest.tearUp(tID) + } + + // See https://github.com/containerd/nerdctl/issues/3130 + // We run first to capture the underlying icmd command and output + cmd := currentTest.command(tID) + res := cmd.Run() + cmd.Assert(currentTest.expected(tID)) + if currentTest.inspect != nil { + currentTest.inspect(tt, res.Stdout(), res.Stderr()) + } + }) + } +} diff --git a/cmd/nerdctl/volume_prune_linux_test.go b/cmd/nerdctl/volume_prune_linux_test.go index df610ca1a04..17f6ad539c7 100644 --- a/cmd/nerdctl/volume_prune_linux_test.go +++ b/cmd/nerdctl/volume_prune_linux_test.go @@ -17,30 +17,133 @@ package main import ( - "fmt" + "strings" "testing" + "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestVolumePrune(t *testing.T) { - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - base.Cmd("volume", "prune", "-a", "-f").Run() + // Volume pruning cannot be parallelized for Docker, since we need namespaces to do that in a way that does interact with other tests + if testutil.GetTarget() != testutil.Docker { + t.Parallel() + } + + // FIXME: for an unknown reason, when testing ipv6, calling NewBaseWithNamespace per sub-test, in the tearDown/tearUp methods + // will actually panic the test (also happens with target=docker) + // Calling base here *first* so that it can skip NOW - does seem to workaround the problem + // If you have any idea how to properly do this, feel free to remove the following line and fix the underlying issue + testutil.NewBase(t) + + subTearUp := func(tID string) { + base := testutil.NewBaseWithNamespace(t, tID) + res := base.Cmd("volume", "create").Run() + anonIDBusy := res.Stdout() + base.Cmd("volume", "create").Run() + base.Cmd("volume", "create", tID+"-busy").AssertOK() + base.Cmd("volume", "create", tID+"-free").AssertOK() + base.Cmd("run", "--name", tID, + "-v", tID+"-busy:/whatever", + "-v", anonIDBusy, testutil.CommonImage).AssertOK() + } + + subTearDown := func(tID string) { + base := testutil.NewBaseWithNamespace(t, tID) + base.Cmd("rm", "-f", tID).Run() + base.Cmd("namespace", "remove", "-f", tID).Run() + } + + testCases := []struct { + description string + command func(tID string) *testutil.Cmd + tearUp func(tID string) + tearDown func(tID string) + expected func(tID string) icmd.Expected + inspect func(t *testing.T, stdout string, stderr string) + dockerIncompatible bool + }{ + { + description: "prune anonymous only", + command: func(tID string) *testutil.Cmd { + base := testutil.NewBaseWithNamespace(t, tID) + return base.Cmd("volume", "prune", "-f") + }, + tearUp: subTearUp, + tearDown: subTearDown, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + } + }, + inspect: func(t *testing.T, stdout string, stderr string) { + tID := testutil.Identifier(t) + base := testutil.NewBaseWithNamespace(t, tID) + assert.Assert(base.T, !strings.Contains(stdout, tID+"-free")) + base.Cmd("volume", "inspect", tID+"-free").AssertOK() + assert.Assert(base.T, !strings.Contains(stdout, tID+"-busy")) + base.Cmd("volume", "inspect", tID+"-busy").AssertOK() + // TODO verify the anonymous volumes status + }, + }, + { + description: "prune all", + command: func(tID string) *testutil.Cmd { + base := testutil.NewBaseWithNamespace(t, tID) + return base.Cmd("volume", "prune", "-f", "--all") + }, + tearUp: subTearUp, + tearDown: subTearDown, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 0, + } + }, + inspect: func(t *testing.T, stdout string, stderr string) { + tID := testutil.Identifier(t) + base := testutil.NewBaseWithNamespace(t, tID) + assert.Assert(t, !strings.Contains(stdout, tID+"-busy")) + base.Cmd("volume", "inspect", tID+"-busy").AssertOK() + assert.Assert(t, strings.Contains(stdout, tID+"-free")) + base.Cmd("volume", "inspect", tID+"-free").AssertFail() + // TODO verify the anonymous volumes status + }, + }, + } + + for _, test := range testCases { + currentTest := test + t.Run(currentTest.description, func(tt *testing.T) { + if currentTest.dockerIncompatible { + testutil.DockerIncompatible(tt) + } - vID := base.Cmd("volume", "create").Out() - base.Cmd("volume", "create", tID+"-1").AssertOK() - base.Cmd("volume", "create", tID+"-2").AssertOK() + if testutil.GetTarget() != testutil.Docker { + tt.Parallel() + } - base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID+"-1"), "--name", tID, testutil.CommonImage).AssertOK() - defer base.Cmd("rm", "-f", tID).Run() + subTID := testutil.Identifier(tt) - base.Cmd("volume", "prune", "-f").AssertOutContains(vID) - base.Cmd("volume", "prune", "-a", "-f").AssertOutContains(tID + "-2") - base.Cmd("volume", "ls").AssertOutContains(tID + "-1") - base.Cmd("volume", "ls").AssertOutNotContains(tID + "-2") + if currentTest.tearDown != nil { + currentTest.tearDown(subTID) + tt.Cleanup(func() { + currentTest.tearDown(subTID) + }) + } + if currentTest.tearUp != nil { + currentTest.tearUp(subTID) + } - base.Cmd("rm", "-f", tID).AssertOK() - base.Cmd("volume", "prune", "-a", "-f").AssertOK() - base.Cmd("volume", "ls").AssertOutNotContains(tID + "-1") + // See https://github.com/containerd/nerdctl/issues/3130 + // We run first to capture the underlying icmd command and output + cmd := currentTest.command(subTID) + res := cmd.Run() + cmd.Assert(currentTest.expected(subTID)) + if currentTest.inspect != nil { + currentTest.inspect(tt, res.Stdout(), res.Stderr()) + } + }) + } } diff --git a/cmd/nerdctl/volume_remove_linux_test.go b/cmd/nerdctl/volume_remove_linux_test.go index 6023381c782..8394a37ed5c 100644 --- a/cmd/nerdctl/volume_remove_linux_test.go +++ b/cmd/nerdctl/volume_remove_linux_test.go @@ -18,34 +18,45 @@ package main import ( "fmt" + "strings" "testing" + "github.com/containerd/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/testutil" + "gotest.tools/v3/assert" "gotest.tools/v3/icmd" ) +// TestVolumeRemove does test a large variety of volume remove situations, albeit none of them being +// hard filesystem errors. +// Behavior in such cases is largely unspecified, as there is no easy way to compare with Docker. +// Anyhow, borked filesystem conditions is not something we should be expected to deal with in a smart way. func TestVolumeRemove(t *testing.T) { t.Parallel() base := testutil.NewBase(t) - malformed := "malformed volume name" - notFound := "no such volume" + inUse := errdefs.ErrFailedPrecondition.Error() + malformed := errdefs.ErrInvalidArgument.Error() + notFound := errdefs.ErrNotFound.Error() requireArg := "requires at least 1 arg" - inUse := "is in use" if base.Target == testutil.Docker { malformed = "no such volume" + notFound = "no such volume" + inUse = "volume is in use" } testCases := []struct { - description string - command func(tID string) *testutil.Cmd - tearUp func(tID string) - tearDown func(tID string) - expected func(tID string) icmd.Expected + description string + command func(tID string) *testutil.Cmd + tearUp func(tID string) + tearDown func(tID string) + expected func(tID string) icmd.Expected + inspect func(t *testing.T, stdout string, stderr string) + dockerIncompatible bool }{ { - description: "arg missing", + description: "arg missing should fail", command: func(tID string) *testutil.Cmd { return base.Cmd("volume", "rm") }, @@ -57,7 +68,7 @@ func TestVolumeRemove(t *testing.T) { }, }, { - description: "invalid identifier", + description: "invalid identifier should fail", command: func(tID string) *testutil.Cmd { return base.Cmd("volume", "rm", "∞") }, @@ -69,7 +80,7 @@ func TestVolumeRemove(t *testing.T) { }, }, { - description: "non existent volume", + description: "non existent volume should fail", command: func(tID string) *testutil.Cmd { return base.Cmd("volume", "rm", "doesnotexist") }, @@ -81,7 +92,7 @@ func TestVolumeRemove(t *testing.T) { }, }, { - description: "busy volume", + description: "busy volume should fail", command: func(tID string) *testutil.Cmd { return base.Cmd("volume", "rm", tID) }, @@ -102,7 +113,39 @@ func TestVolumeRemove(t *testing.T) { }, }, { - description: "freed volume", + description: "busy anonymous volume should fail", + command: func(tID string) *testutil.Cmd { + // Inspect the container and find the anonymous volume id + inspect := base.InspectContainer(tID) + var anonName string + for _, v := range inspect.Mounts { + if v.Destination == "/volume" { + anonName = v.Name + break + } + } + assert.Assert(t, anonName != "", "Failed to find anonymous volume id") + + // Try to remove that anon volume + return base.Cmd("volume", "rm", anonName) + }, + tearUp: func(tID string) { + // base.Cmd("volume", "create", tID).AssertOK() + base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID), "--name", tID, testutil.CommonImage).AssertOK() + }, + tearDown: func(tID string) { + base.Cmd("rm", "-f", tID).Run() + }, + expected: func(tID string) icmd.Expected { + return icmd.Expected{ + ExitCode: 1, + Err: inUse, + } + + }, + }, + { + description: "freed volume should succeed", command: func(tID string) *testutil.Cmd { return base.Cmd("volume", "rm", tID) }, @@ -122,7 +165,7 @@ func TestVolumeRemove(t *testing.T) { }, }, { - description: "dangling volume", + description: "dangling volume should succeed", command: func(tID string) *testutil.Cmd { return base.Cmd("volume", "rm", tID) }, @@ -139,23 +182,31 @@ func TestVolumeRemove(t *testing.T) { }, }, { - "part success multi remove", - func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm", "invalid∞", "nonexistent", tID) + description: "part success multi-remove", + command: func(tID string) *testutil.Cmd { + return base.Cmd("volume", "rm", "invalid∞", "nonexistent", tID+"-busy", tID) }, - func(tID string) { + tearUp: func(tID string) { base.Cmd("volume", "create", tID).AssertOK() + base.Cmd("volume", "create", tID+"-busy").AssertOK() + base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID+"-busy"), "--name", tID, testutil.CommonImage).AssertOK() }, - func(tID string) { + tearDown: func(tID string) { + base.Cmd("rm", "-f", tID).Run() base.Cmd("volume", "rm", "-f", tID).Run() + base.Cmd("volume", "rm", "-f", tID+"-busy").Run() }, - func(tID string) icmd.Expected { + expected: func(tID string) icmd.Expected { return icmd.Expected{ ExitCode: 1, Out: tID, - Err: notFound, } }, + inspect: func(t *testing.T, stdout string, stderr string) { + assert.Assert(t, strings.Contains(stderr, notFound)) + assert.Assert(t, strings.Contains(stderr, inUse)) + assert.Assert(t, strings.Contains(stderr, malformed)) + }, }, { description: "success multi-remove", @@ -177,21 +228,37 @@ func TestVolumeRemove(t *testing.T) { }, { description: "failing multi-remove", + tearUp: func(tID string) { + base.Cmd("volume", "create", tID+"-busy").AssertOK() + base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID+"-busy"), "--name", tID, testutil.CommonImage).AssertOK() + }, + tearDown: func(tID string) { + base.Cmd("rm", "-f", tID).Run() + base.Cmd("volume", "rm", "-f", tID+"-busy").Run() + }, command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm", "nonexist1", "nonexist2") + return base.Cmd("volume", "rm", "invalid∞", "nonexistent", tID+"-busy") }, expected: func(tID string) icmd.Expected { return icmd.Expected{ ExitCode: 1, - Err: notFound, } }, + inspect: func(t *testing.T, stdout string, stderr string) { + assert.Assert(t, strings.Contains(stderr, notFound)) + assert.Assert(t, strings.Contains(stderr, inUse)) + assert.Assert(t, strings.Contains(stderr, malformed)) + }, }, } for _, test := range testCases { currentTest := test t.Run(currentTest.description, func(tt *testing.T) { + if currentTest.dockerIncompatible { + testutil.DockerIncompatible(tt) + } + tt.Parallel() tID := testutil.Identifier(tt) @@ -206,8 +273,14 @@ func TestVolumeRemove(t *testing.T) { currentTest.tearUp(tID) } + // See https://github.com/containerd/nerdctl/issues/3130 + // We run first to capture the underlying icmd command and output cmd := currentTest.command(tID) + res := cmd.Run() cmd.Assert(currentTest.expected(tID)) + if currentTest.inspect != nil { + currentTest.inspect(tt, res.Stdout(), res.Stderr()) + } }) } } diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 2b347d890e1..dd0b596b6f8 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -39,6 +39,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/flagutil" "github.com/containerd/nerdctl/v2/pkg/idgen" @@ -61,6 +62,17 @@ import ( // Create will create a container. func Create(ctx context.Context, client *containerd.Client, args []string, netManager containerutil.NetworkOptionsManager, options types.ContainerCreateOptions) (containerd.Container, func(), error) { + // Acquire an exclusive lock on the volume store until we are done to avoid being raced by other volume operations + volStore, err := volume.Store(options.GOptions.Namespace, options.GOptions.DataRoot, options.GOptions.Address) + if err != nil { + return nil, nil, err + } + err = volStore.Lock() + if err != nil { + return nil, nil, err + } + defer volStore.Unlock() + // simulate the behavior of double dash newArg := []string{} if len(args) >= 2 && args[1] == "--" { @@ -151,7 +163,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa } var mountOpts []oci.SpecOpts - mountOpts, internalLabels.anonVolumes, internalLabels.mountPoints, err = generateMountOpts(ctx, client, ensuredImage, options) + mountOpts, internalLabels.anonVolumes, internalLabels.mountPoints, err = generateMountOpts(ctx, client, ensuredImage, volStore, options) if err != nil { return nil, nil, err } diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 56cdcc3ebea..4dca4d117a2 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -132,6 +132,14 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions if err != nil { return err } + // Note: technically, it is not strictly necessary to acquire an exclusive lock on the volume store here. + // Worst case scenario, we would fail removing anonymous volumes later on, which is a soft error, and which would + // only happen if we concurrently tried to remove the same container. + err = volStore.Lock() + if err != nil { + return err + } + defer volStore.Unlock() // Decode IPC ipc, err := ipcutil.DecodeIPCLabel(containerLabels[labels.IPC]) if err != nil { diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index 3a53c8c6f70..87c36f45142 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -37,7 +37,6 @@ import ( "github.com/containerd/continuity/fs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" - "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" @@ -122,13 +121,8 @@ func parseMountFlags(volStore volumestore.VolumeStore, options types.ContainerCr // generateMountOpts generates volume-related mount opts. // Other mounts such as procfs mount are not handled here. -func generateMountOpts(ctx context.Context, client *containerd.Client, ensuredImage *imgutil.EnsuredImage, options types.ContainerCreateOptions) ([]oci.SpecOpts, []string, []*mountutil.Processed, error) { - // volume store is corresponds to a directory like `/var/lib/nerdctl/1935db59/volumes/default` - volStore, err := volume.Store(options.GOptions.Namespace, options.GOptions.DataRoot, options.GOptions.Address) - if err != nil { - return nil, nil, nil, err - } - +func generateMountOpts(ctx context.Context, client *containerd.Client, ensuredImage *imgutil.EnsuredImage, + volStore volumestore.VolumeStore, options types.ContainerCreateOptions) ([]oci.SpecOpts, []string, []*mountutil.Processed, error) { //nolint:golint,prealloc var ( opts []oci.SpecOpts diff --git a/pkg/cmd/volume/create.go b/pkg/cmd/volume/create.go index c00fe00efa3..f8cdbbcd345 100644 --- a/pkg/cmd/volume/create.go +++ b/pkg/cmd/volume/create.go @@ -19,7 +19,6 @@ package volume import ( "fmt" - "github.com/containerd/containerd/identifiers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/labels" @@ -32,9 +31,6 @@ func Create(name string, options types.VolumeCreateOptions) (*native.Volume, err name = stringid.GenerateRandomID() options.Labels = append(options.Labels, labels.AnonymousVolumes+"=") } - if err := identifiers.Validate(name); err != nil { - return nil, fmt.Errorf("malformed name %s: %w", name, err) - } volStore, err := Store(options.GOptions.Namespace, options.GOptions.DataRoot, options.GOptions.Address) if err != nil { return nil, err diff --git a/pkg/cmd/volume/inspect.go b/pkg/cmd/volume/inspect.go index 4c9442ed286..4a7ee1cd2e5 100644 --- a/pkg/cmd/volume/inspect.go +++ b/pkg/cmd/volume/inspect.go @@ -17,23 +17,40 @@ package volume import ( + "context" + "errors" + + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" ) -func Inspect(volumes []string, options types.VolumeInspectOptions) error { +func Inspect(ctx context.Context, volumes []string, options types.VolumeInspectOptions) error { volStore, err := Store(options.GOptions.Namespace, options.GOptions.DataRoot, options.GOptions.Address) if err != nil { return err } - result := make([]interface{}, len(volumes)) + result := []interface{}{} - for i, name := range volumes { + warns := []error{} + for _, name := range volumes { var vol, err = volStore.Get(name, options.Size) if err != nil { - return err + warns = append(warns, err) + continue } - result[i] = vol + result = append(result, vol) + } + err = formatter.FormatSlice(options.Format, options.Stdout, result) + if err != nil { + return err + } + for _, warn := range warns { + log.G(ctx).Warn(warn) + } + + if len(warns) != 0 { + return errors.New("some volumes could not be inspected") } - return formatter.FormatSlice(options.Format, options.Stdout, result) + return nil } diff --git a/pkg/cmd/volume/prune.go b/pkg/cmd/volume/prune.go index f9dff99f428..ab9728be34f 100644 --- a/pkg/cmd/volume/prune.go +++ b/pkg/cmd/volume/prune.go @@ -26,29 +26,46 @@ import ( ) func Prune(ctx context.Context, client *containerd.Client, options types.VolumePruneOptions) error { + // Get the volume store and lock it until we are done. + // This will prevent racing new containers from being created or removed until we are done with the cleanup of volumes volStore, err := Store(options.GOptions.Namespace, options.GOptions.DataRoot, options.GOptions.Address) if err != nil { return err } - volumes, err := volStore.List(false) + err = volStore.Lock() if err != nil { return err } + defer volStore.Unlock() + // Get containers and see which volumes are used containers, err := client.Containers(ctx) if err != nil { return err } - usedVolumes, err := usedVolumes(ctx, containers) + + usedVolumesList, err := usedVolumes(ctx, containers) if err != nil { return err } var removeNames []string // nolint: prealloc + + // Get the list of known volumes from the store + volumes, err := volStore.List(false) + if err != nil { + return err + } + + // Iterate through the known volumes, making sure we do not remove in-use volumes + // but capture as well anon volumes (if --all was passed) for _, volume := range volumes { - if _, ok := usedVolumes[volume.Name]; ok { + if _, ok := usedVolumesList[volume.Name]; ok { continue } if !options.All { + if volume.Labels == nil { + continue + } val, ok := (*volume.Labels)[labels.AnonymousVolumes] //skip the named volume and only remove the anonymous volume if !ok || val != "" { @@ -57,6 +74,8 @@ func Prune(ctx context.Context, client *containerd.Client, options types.VolumeP } removeNames = append(removeNames, volume.Name) } + + // Remove the volumes from that list removedNames, _, err := volStore.Remove(removeNames) if err != nil { return err diff --git a/pkg/cmd/volume/rm.go b/pkg/cmd/volume/rm.go index 2c74df9f1b2..8d363de0968 100644 --- a/pkg/cmd/volume/rm.go +++ b/pkg/cmd/volume/rm.go @@ -32,47 +32,61 @@ import ( ) func Remove(ctx context.Context, client *containerd.Client, volumes []string, options types.VolumeRemoveOptions) error { - containers, err := client.Containers(ctx) + // Get the volume store and lock it until we are done. + // This will prevent racing new containers from being created or removed until we are done with the cleanup of volumes + volStore, err := Store(options.GOptions.Namespace, options.GOptions.DataRoot, options.GOptions.Address) if err != nil { return err } - volStore, err := Store(options.GOptions.Namespace, options.GOptions.DataRoot, options.GOptions.Address) + err = volStore.Lock() if err != nil { return err } - usedVolumes, err := usedVolumes(ctx, containers) + defer volStore.Unlock() + + // Get containers and see which volumes are used + containers, err := client.Containers(ctx) if err != nil { return err } - var volumenames []string // nolint: prealloc + usedVolumesList, err := usedVolumes(ctx, containers) + if err != nil { + return err + } + + volumeNames := []string{} + cannotRemove := []error{} + for _, name := range volumes { - if _, ok := usedVolumes[name]; ok { - return fmt.Errorf("volume %q is in use", name) + if _, ok := usedVolumesList[name]; ok { + cannotRemove = append(cannotRemove, fmt.Errorf("volume %q is in use (%w)", name, errdefs.ErrFailedPrecondition)) + continue } - volumenames = append(volumenames, name) + volumeNames = append(volumeNames, name) } // if err is set, this is a hard filesystem error - removedNames, warns, err := volStore.Remove(volumenames) + removedNames, warns, err := volStore.Remove(volumeNames) if err != nil { return err } + cannotRemove = append(cannotRemove, warns...) // Otherwise, output on stdout whatever was successful for _, name := range removedNames { fmt.Fprintln(options.Stdout, name) } // Log the rest - for _, volErr := range warns { + for _, volErr := range cannotRemove { log.G(ctx).Warn(volErr) } - if len(warns) > 0 { + if len(cannotRemove) > 0 { return errors.New("some volumes could not be removed") } return nil } func usedVolumes(ctx context.Context, containers []containerd.Container) (map[string]struct{}, error) { - usedVolumes := make(map[string]struct{}) + usedVolumesList := make(map[string]struct{}) for _, c := range containers { l, err := c.Labels(ctx) if err != nil { @@ -95,9 +109,9 @@ func usedVolumes(ctx context.Context, containers []containerd.Container) (map[st } for _, m := range mounts { if m.Type == mountutil.Volume { - usedVolumes[m.Name] = struct{}{} + usedVolumesList[m.Name] = struct{}{} } } } - return usedVolumes, nil + return usedVolumesList, nil } diff --git a/pkg/composer/up_volume.go b/pkg/composer/up_volume.go index 436c85c51c5..190001956cf 100644 --- a/pkg/composer/up_volume.go +++ b/pkg/composer/up_volume.go @@ -41,6 +41,9 @@ func (c *Composer) upVolume(ctx context.Context, shortName string) error { // shortName is like "db_data", fullName is like "compose-wordpress_db_data" fullName := vol.Name + // FIXME: this is racy. By the time we get below to creating the volume, there is no guarantee that things are still fine + // Furthermore, volStore.Get no longer errors if the volume already exists (docker behavior), so, the purpose of this + // call needs to be assessed (it might still error if the name is malformed, or if there is a filesystem error) volExists, err := c.VolumeExists(fullName) if err != nil { return err diff --git a/pkg/lockutil/lockutil_unix.go b/pkg/lockutil/lockutil_unix.go index 64e9867b044..9b3d9d98932 100644 --- a/pkg/lockutil/lockutil_unix.go +++ b/pkg/lockutil/lockutil_unix.go @@ -32,18 +32,18 @@ func WithDirLock(dir string, fn func() error) error { return err } defer dirFile.Close() - if err := Flock(dirFile, unix.LOCK_EX); err != nil { + if err := flock(dirFile, unix.LOCK_EX); err != nil { return fmt.Errorf("failed to lock %q: %w", dir, err) } defer func() { - if err := Flock(dirFile, unix.LOCK_UN); err != nil { + if err := flock(dirFile, unix.LOCK_UN); err != nil { log.L.WithError(err).Errorf("failed to unlock %q", dir) } }() return fn() } -func Flock(f *os.File, flags int) error { +func flock(f *os.File, flags int) error { fd := int(f.Fd()) for { err := unix.Flock(fd, flags) @@ -52,3 +52,27 @@ func Flock(f *os.File, flags int) error { } } } + +func Lock(dir string) (*os.File, error) { + dirFile, err := os.Open(dir) + if err != nil { + return nil, err + } + + if err = flock(dirFile, unix.LOCK_EX); err != nil { + return nil, err + } + + return dirFile, nil +} + +func Unlock(locked *os.File) error { + defer func() { + _ = locked.Close() + }() + + if err := flock(locked, unix.LOCK_UN); err != nil { + return err + } + return nil +} diff --git a/pkg/lockutil/lockutil_windows.go b/pkg/lockutil/lockutil_windows.go index 85658167443..a269fc65716 100644 --- a/pkg/lockutil/lockutil_windows.go +++ b/pkg/lockutil/lockutil_windows.go @@ -43,3 +43,24 @@ func WithDirLock(dir string, fn func() error) error { }() return fn() } + +func Lock(dir string) (*os.File, error) { + dirFile, err := os.OpenFile(dir+".lock", os.O_CREATE, 0644) + if err != nil { + return nil, err + } + // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx + // 1 lock immediately + if err = windows.LockFileEx(windows.Handle(dirFile.Fd()), 1, 0, 1, 0, &windows.Overlapped{}); err != nil { + return nil, fmt.Errorf("failed to lock %q: %w", dir, err) + } + return dirFile, nil +} + +func Unlock(locked *os.File) error { + defer func() { + _ = locked.Close() + }() + + return windows.UnlockFileEx(windows.Handle(locked.Fd()), 0, 1, 0, &windows.Overlapped{}) +} diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index f8e184033b0..6223a6d5501 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -17,14 +17,12 @@ package mountutil import ( - "errors" "fmt" "os" "path/filepath" "runtime" "strings" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/pkg/userns" @@ -203,16 +201,11 @@ func handleAnonymousVolumes(s string, volStore volumestore.VolumeStore) (volumeS func handleNamedVolumes(source string, volStore volumestore.VolumeStore) (volumeSpec, error) { var res volumeSpec res.Name = source - vol, err := volStore.Get(res.Name, false) + + // Create returns an existing volume or creates a new one if necessary. + vol, err := volStore.Create(res.Name, nil) if err != nil { - if errors.Is(err, errdefs.ErrNotFound) { - vol, err = volStore.Create(res.Name, nil) - if err != nil { - return res, fmt.Errorf("failed to create volume %q: %w", res.Name, err) - } - } else { - return res, fmt.Errorf("failed to get volume %q: %w", res.Name, err) - } + return res, fmt.Errorf("failed to get volume %q: %w", res.Name, err) } // src is now an absolute path res.Type = Volume diff --git a/pkg/mountutil/mountutilmock/volumestore.mock.go b/pkg/mountutil/mountutilmock/volumestore.mock.go index efed1cfc219..695742f85b7 100644 --- a/pkg/mountutil/mountutilmock/volumestore.mock.go +++ b/pkg/mountutil/mountutilmock/volumestore.mock.go @@ -106,16 +106,26 @@ func (m *MockVolumeStoreMockRecorder) Remove(names any) *gomock.Call { return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Remove", reflect.TypeOf((*MockVolumeStore)(nil).Remove), names) } -// Dir mocks the Dir method of VolumeStore -func (m *MockVolumeStore) Dir() string { +// Lock mocks the Lock method of VolumeStore +func (m *MockVolumeStore) Lock() error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Dir") - ret0, _ := ret[0].(string) - return ret0 + return nil } -// Dir indicates an expected call of Dir -func (m *MockVolumeStoreMockRecorder) Dir() *gomock.Call { +// Lock indicates an expected call of Lock +func (m *MockVolumeStoreMockRecorder) Lock() *gomock.Call { m.mock.ctrl.T.Helper() - return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Dir", reflect.TypeOf((*MockVolumeStore)(nil).Dir)) + return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Lock", reflect.TypeOf((*MockVolumeStore)(nil).Lock)) +} + +// Unlock mocks the Unlock method of VolumeStore +func (m *MockVolumeStore) Unlock() error { + m.ctrl.T.Helper() + return nil +} + +// Unlock indicates an expected call of Unlock +func (m *MockVolumeStoreMockRecorder) Unlock() *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Unlock", reflect.TypeOf((*MockVolumeStore)(nil).Unlock)) } diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index 8093212a7b7..a9a50a0f8e3 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -31,21 +31,33 @@ import ( "github.com/containerd/nerdctl/v2/pkg/strutil" ) -// Path returns a string like `/var/lib/nerdctl/1935db59/volumes/default`. -func Path(dataStore, ns string) (string, error) { - if dataStore == "" || ns == "" { - return "", errdefs.ErrInvalidArgument - } - volStore := filepath.Join(dataStore, "volumes", ns) - return volStore, nil +const ( + dataDirName = "_data" + volumeJSONFileName = "volume.json" +) + +// VolumeStore allows manipulating containers' volumes +// Every method is protected by a file lock, and is safe to use concurrently. +// If you need to use multiple methods successively (for example: List, then Remove), you should instead optin +// for an explicit durable lock, by first calling `Lock` then `defer Unlock`. +// This is also true (and important to do) for any operation that is going to inspect containers before going for +// creation or removal of volumes. +type VolumeStore interface { + Create(name string, labels []string) (*native.Volume, error) + Get(name string, size bool) (*native.Volume, error) + List(size bool) (map[string]native.Volume, error) + Remove(names []string) (removed []string, warns []error, err error) + Lock() error + Unlock() error } // New returns a VolumeStore func New(dataStore, ns string) (VolumeStore, error) { - volStoreDir, err := Path(dataStore, ns) - if err != nil { - return nil, err + if dataStore == "" || ns == "" { + return nil, errdefs.ErrInvalidArgument } + volStoreDir := filepath.Join(dataStore, "volumes", ns) + if err := os.MkdirAll(volStoreDir, 0700); err != nil { return nil, err } @@ -55,175 +67,246 @@ func New(dataStore, ns string) (VolumeStore, error) { return vs, nil } -// DataDirName is "_data" -const DataDirName = "_data" +type volumeStore struct { + dir string + locked *os.File +} -const volumeJSONFileName = "volume.json" +// Lock should be called when you need an exclusive lock on the volume store for an extended period of time +// spanning multiple atomic method calls. +// Be sure to defer Unlock to release it. +func (vs *volumeStore) Lock() error { + if vs.locked != nil { + return fmt.Errorf("cannot lock already locked volume store %q", vs.dir) + } -type VolumeStore interface { - Dir() string - Create(name string, labels []string) (*native.Volume, error) - // Get may return ErrNotFound - Get(name string, size bool) (*native.Volume, error) - List(size bool) (map[string]native.Volume, error) - Remove(names []string) (removed []string, warns []error, err error) -} + dirFile, err := lockutil.Lock(vs.dir) + if err != nil { + return err + } -type volumeStore struct { - // dir is a string like `/var/lib/nerdctl/1935db59/volumes/default`. - // dir is guaranteed to exist. - dir string + vs.locked = dirFile + return nil } -func (vs *volumeStore) Dir() string { - return vs.dir +// Unlock should be called once done (see Lock) to release the persistent lock on the store +func (vs *volumeStore) Unlock() error { + if vs.locked == nil { + return fmt.Errorf("cannot unlock already unlocked volume store %q", vs.dir) + } + + defer func() { + vs.locked = nil + }() + + if err := lockutil.Unlock(vs.locked); err != nil { + return fmt.Errorf("failed to unlock volume store %q: %w", vs.dir, err) + } + return nil } +// Create will create a new volume, or return an existing one if there is one already by that name +// Besides a possible locking error, it might return ErrInvalidArgument, hard filesystem errors, json errors func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, error) { if err := identifiers.Validate(name); err != nil { - return nil, fmt.Errorf("malformed volume name: %w", err) + return nil, fmt.Errorf("malformed volume name: %w (%w)", err, errdefs.ErrInvalidArgument) } volPath := filepath.Join(vs.dir, name) - volDataPath := filepath.Join(volPath, DataDirName) + volDataPath := filepath.Join(volPath, dataDirName) volFilePath := filepath.Join(volPath, volumeJSONFileName) - fn := func() (err error) { - if err := os.Mkdir(volPath, 0700); err != nil { + + vol := &native.Volume{} + + fn := func() error { + // Failures that are not os.ErrExist must exit here + if err := os.Mkdir(volPath, 0700); err != nil && !errors.Is(err, os.ErrExist) { return err } - defer func() { - if err != nil { - os.Remove(volPath) - } - }() - if err := os.Mkdir(volDataPath, 0755); err != nil { + if err := os.Mkdir(volDataPath, 0755); err != nil && !errors.Is(err, os.ErrExist) { return err } - defer func() { - if err != nil { - os.Remove(volDataPath) - } - }() - type volumeOpts struct { + volOpts := struct { Labels map[string]string `json:"labels"` - } - - labelsMap := strutil.ConvertKVStringsToMap(labels) + }{} - volOpts := volumeOpts{ - Labels: labelsMap, + if len(labels) > 0 { + volOpts.Labels = strutil.ConvertKVStringsToMap(labels) } + // Failure here must exit, no need to clean-up labelsJSON, err := json.MarshalIndent(volOpts, "", " ") if err != nil { return err } - defer func() { - if err != nil { - if _, statErr := os.Stat(volFilePath); statErr != nil && !os.IsNotExist(statErr) { - log.L.Warnf("failed to stat volume file: %v", statErr) - return - } else if statErr == nil { - os.Remove(volFilePath) - } + // If it does not exist + if _, err = os.Stat(volFilePath); err != nil { + // Any other stat error than "not exists", hard exit + if !errors.Is(err, os.ErrNotExist) { + return err + } + // Error was does not exist, so, write it + if err = os.WriteFile(volFilePath, labelsJSON, 0644); err != nil { + return err } - }() - return os.WriteFile(volFilePath, labelsJSON, 0644) + } else { + log.L.Warnf("volume %q already exists and will be returned as-is", name) + } + + // At this point, we either have a volume, or created a new one successfully + vol.Name = name + vol.Mountpoint = volDataPath + + return nil } - if err := lockutil.WithDirLock(vs.dir, fn); err != nil && !errors.Is(err, os.ErrExist) { + var err error + if vs.locked == nil { + err = lockutil.WithDirLock(vs.dir, fn) + } else { + err = fn() + } + if err != nil { return nil, err } - // If other new actions that might fail are added below, we should move the cleanup function out of fn. - vol := &native.Volume{ - Name: name, - Mountpoint: volDataPath, - } return vol, nil } +// Get retrieves a native volume from the store +// Besides a possible locking error, it might return ErrInvalidArgument, ErrNotFound, or a filesystem error func (vs *volumeStore) Get(name string, size bool) (*native.Volume, error) { if err := identifiers.Validate(name); err != nil { - return nil, fmt.Errorf("malformed name %s: %w", name, err) + return nil, fmt.Errorf("malformed volume name %q: %w", name, err) } - dataPath := filepath.Join(vs.dir, name, DataDirName) - if _, err := os.Stat(dataPath); err != nil { - if os.IsNotExist(err) { - return nil, fmt.Errorf("volume %q not found: %w", name, errdefs.ErrNotFound) + volPath := filepath.Join(vs.dir, name) + volDataPath := filepath.Join(volPath, dataDirName) + volFilePath := filepath.Join(volPath, volumeJSONFileName) + + vol := &native.Volume{} + + fn := func() error { + if _, err := os.Stat(volDataPath); err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("%q does not exist in the volume store: %w", name, errdefs.ErrNotFound) + } + return fmt.Errorf("filesystem error reading %q from the volume store: %w", name, err) } - return nil, err - } - volFilePath := filepath.Join(vs.dir, name, volumeJSONFileName) - volumeDataBytes, err := os.ReadFile(volFilePath) - if err != nil { - if !os.IsNotExist(err) { - return nil, err - } // on else, volume.json does not exists should not be blocking for inspect operation + volumeDataBytes, err := os.ReadFile(volFilePath) + if err != nil { + if os.IsNotExist(err) { + return fmt.Errorf("%q labels file does not exist in the volume store: %w", name, errdefs.ErrNotFound) + } + return fmt.Errorf("filesystem error reading %q from the volume store: %w", name, err) + } + + vol.Name = name + vol.Mountpoint = volDataPath + vol.Labels = labels(volumeDataBytes) + + if size { + vol.Size, err = volumeSize(vol) + if err != nil { + return fmt.Errorf("failed reading volume size for %q from the volume store: %w", name, err) + } + } + return nil } - entry := native.Volume{ - Name: name, - Mountpoint: dataPath, - Labels: Labels(volumeDataBytes), + var err error + if vs.locked == nil { + err = lockutil.WithDirLock(vs.dir, fn) + } else { + err = fn() } - if size { - entry.Size, err = Size(&entry) - if err != nil { - return nil, err - } + if err != nil { + return nil, err } - return &entry, nil + + return vol, nil } +// List retrieves all known volumes from the store. +// Besides a possible locking error, it might return ErrNotFound (indicative that the store is in a broken state), or a filesystem error func (vs *volumeStore) List(size bool) (map[string]native.Volume, error) { - dEnts, err := os.ReadDir(vs.dir) - if err != nil { - return nil, err + res := map[string]native.Volume{} + + fn := func() error { + dirEntries, err := os.ReadDir(vs.dir) + if err != nil { + return fmt.Errorf("filesystem error while trying to list volumes from the volume store: %w", err) + } + + for _, dirEntry := range dirEntries { + name := dirEntry.Name() + vol, err := vs.Get(name, size) + if err != nil { + return err + } + res[name] = *vol + } + return nil } - res := make(map[string]native.Volume, len(dEnts)) - for _, dEnt := range dEnts { - name := dEnt.Name() - vol, err := vs.Get(name, size) + var err error + // Since we are calling Get, we need to acquire a global lock + if vs.locked == nil { + err = vs.Lock() if err != nil { - return res, err + return nil, err } - res[name] = *vol + defer vs.Unlock() + } + err = fn() + if err != nil { + return nil, err } return res, nil } +// Remove will remove one or more containers +// Besides a possible locking error, it might return hard filesystem errors +// Any other failure (ErrInvalidArgument, ErrNotFound) is a soft error that will be added the `warns` func (vs *volumeStore) Remove(names []string) (removed []string, warns []error, err error) { fn := func() error { for _, name := range names { + // Invalid name, soft error if err := identifiers.Validate(name); err != nil { - warns = append(warns, fmt.Errorf("malformed volume name: %w", err)) + warns = append(warns, fmt.Errorf("malformed volume name: %w (%w)", err, errdefs.ErrInvalidArgument)) continue } dir := filepath.Join(vs.dir, name) - if _, err := os.Stat(dir); os.IsNotExist(err) { - warns = append(warns, fmt.Errorf("no such volume: %s", name)) - continue + // Does not exist, soft error + if _, err := os.Stat(dir); err != nil { + if os.IsNotExist(err) { + warns = append(warns, fmt.Errorf("no such volume: %s (%w)", name, errdefs.ErrNotFound)) + continue + } + return fmt.Errorf("filesystem error while trying to remove volumes from the volume store: %w", err) } - // This is a hard filesystem error. Exit on this. + // Hard filesystem error, hard error, and stop here if err := os.RemoveAll(dir); err != nil { - return err + return fmt.Errorf("filesystem error while trying to remove volumes from the volume store: %w", err) } + // Otherwise, add it the list of successfully removed removed = append(removed, name) } return nil } - if err := lockutil.WithDirLock(vs.dir, fn); err != nil { - return nil, nil, err + if vs.locked == nil { + err = lockutil.WithDirLock(vs.dir, fn) + } else { + err = fn() } - return removed, warns, nil + + return removed, warns, err } -func Labels(b []byte) *map[string]string { +// Private helpers +func labels(b []byte) *map[string]string { type volumeOpts struct { Labels *map[string]string `json:"labels,omitempty"` } @@ -234,7 +317,7 @@ func Labels(b []byte) *map[string]string { return vo.Labels } -func Size(volume *native.Volume) (int64, error) { +func volumeSize(volume *native.Volume) (int64, error) { var size int64 var walkFn = func(_ string, info os.FileInfo, err error) error { if err != nil { From 09739c120eabccba7136fc6589956f19e16a9efe Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 5 Jul 2024 11:05:26 -0700 Subject: [PATCH 0559/1066] Improve tests debugging output Signed-off-by: apostasie --- cmd/nerdctl/container_create_linux_test.go | 6 +++--- cmd/nerdctl/container_run_linux_test.go | 2 +- cmd/nerdctl/container_run_network_linux_test.go | 4 ++-- cmd/nerdctl/container_run_security_linux_test.go | 2 +- cmd/nerdctl/container_run_test.go | 4 ++-- cmd/nerdctl/image_push_linux_test.go | 2 +- pkg/testutil/testutil.go | 8 ++++---- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cmd/nerdctl/container_create_linux_test.go b/cmd/nerdctl/container_create_linux_test.go index 871685e70a9..e080cc72980 100644 --- a/cmd/nerdctl/container_create_linux_test.go +++ b/cmd/nerdctl/container_create_linux_test.go @@ -118,7 +118,7 @@ func TestCreateWithMACAddress(t *testing.T) { "sh", "-c", "--", "ip addr show").Run() if !wantErr { - assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res.Combined()) + assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res) // This is currently blocked by: https://github.com/containerd/nerdctl/pull/3104 // res = base.Cmd("start", "-i", containerName). // CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))).Run() @@ -131,7 +131,7 @@ func TestCreateWithMACAddress(t *testing.T) { // unlike nerdctl // when using network ipvlan or container in Docker // it delays fail on executing start command - assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res.Combined()) + assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res) res = base.Cmd("start", "-i", "-a", containerName). CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))).Run() } @@ -146,7 +146,7 @@ func TestCreateWithMACAddress(t *testing.T) { } else { assert.Assert(t, res.Combined() == "", fmt.Sprintf("expected output to be empty: %q", res.Combined())) } - assert.Assert(t, res.ExitCode != 0, "Command should have failed", res.Combined()) + assert.Assert(t, res.ExitCode != 0, "Command should have failed", res) } }) } diff --git a/cmd/nerdctl/container_run_linux_test.go b/cmd/nerdctl/container_run_linux_test.go index f85c5618c79..f73fd8ebfda 100644 --- a/cmd/nerdctl/container_run_linux_test.go +++ b/cmd/nerdctl/container_run_linux_test.go @@ -321,7 +321,7 @@ func TestRunTTY(t *testing.T) { // tests pipe works res := icmd.RunCmd(icmd.Command("unbuffer", "/bin/sh", "-c", fmt.Sprintf("%q run --rm -it %q echo hi | grep hi", base.Binary, testutil.CommonImage))) - assert.Equal(t, 0, res.ExitCode, res.Combined()) + assert.Equal(t, 0, res.ExitCode, res) } func runSigProxy(t *testing.T, args ...string) (string, bool, bool) { diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index 0f6f8990371..8228bf6ac44 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -512,10 +512,10 @@ func TestRunContainerWithMACAddress(t *testing.T) { CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))).Run() if wantErr { - assert.Assert(t, res.ExitCode != 0, "Command should have failed", res.Combined()) + assert.Assert(t, res.ExitCode != 0, "Command should have failed", res) assert.Assert(t, strings.Contains(res.Combined(), expect), fmt.Sprintf("expected output to contain %q: %q", expect, res.Combined())) } else { - assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res.Combined()) + assert.Assert(t, res.ExitCode == 0, "Command should have succeeded", res) assert.Assert(t, strings.Contains(res.Stdout(), expect), fmt.Sprintf("expected output to contain %q: %q", expect, res.Stdout())) } }) diff --git a/cmd/nerdctl/container_run_security_linux_test.go b/cmd/nerdctl/container_run_security_linux_test.go index 55ffdcf306b..e5a029d6a08 100644 --- a/cmd/nerdctl/container_run_security_linux_test.go +++ b/cmd/nerdctl/container_run_security_linux_test.go @@ -224,7 +224,7 @@ func TestRunPrivileged(t *testing.T) { res := base.Cmd("run", "--rm", "--privileged", "--security-opt", "privileged-without-host-devices", testutil.AlpineImage, "ls", devPath).Run() // normally for not a exists file, the `ls` will return `1``. - assert.Check(t, res.ExitCode != 0, res.Combined()) + assert.Check(t, res.ExitCode != 0, res) // something like `ls: /dev/dummy-zero: No such file or directory` assert.Check(t, strings.Contains(res.Combined(), "No such file or directory")) diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index fcf4305bcad..127e763bced 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -330,7 +330,7 @@ func TestRunWithJournaldLogDriver(t *testing.T) { found := 0 check := func(log poll.LogT) poll.Result { res := icmd.RunCmd(icmd.Command(journalctl, "--no-pager", "--since", "2 minutes ago", fmt.Sprintf("SYSLOG_IDENTIFIER=%s", inspectedContainer.ID[:12]))) - assert.Equal(t, 0, res.ExitCode, res.Combined()) + assert.Equal(t, 0, res.ExitCode, res) if strings.Contains(res.Stdout(), "bar") && strings.Contains(res.Stdout(), "foo") { found = 1 return poll.Success() @@ -359,7 +359,7 @@ func TestRunWithJournaldLogDriverAndLogOpt(t *testing.T) { found := 0 check := func(log poll.LogT) poll.Result { res := icmd.RunCmd(icmd.Command(journalctl, "--no-pager", "--since", "2 minutes ago", fmt.Sprintf("SYSLOG_IDENTIFIER=%s", inspectedContainer.ID))) - assert.Equal(t, 0, res.ExitCode, res.Combined()) + assert.Equal(t, 0, res.ExitCode, res) if strings.Contains(res.Stdout(), "bar") && strings.Contains(res.Stdout(), "foo") { found = 1 return poll.Success() diff --git a/cmd/nerdctl/image_push_linux_test.go b/cmd/nerdctl/image_push_linux_test.go index 79fa63f52cb..0bea04d169f 100644 --- a/cmd/nerdctl/image_push_linux_test.go +++ b/cmd/nerdctl/image_push_linux_test.go @@ -41,7 +41,7 @@ func TestPushPlainHTTPFails(t *testing.T) { res := base.Cmd("push", testImageRef).Run() resCombined := res.Combined() - t.Logf("result: exitCode=%d, out=%q", res.ExitCode, res.Combined()) + t.Logf("result: exitCode=%d, out=%q", res.ExitCode, res) assert.Assert(t, res.ExitCode != 0) assert.Assert(t, strings.Contains(resCombined, "server gave HTTP response to HTTPS client")) } diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 62d81a0799e..de80334f09e 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -397,7 +397,7 @@ func (c *Cmd) AssertFail() { func (c *Cmd) AssertExitCode(exitCode int) { c.Base.T.Helper() res := c.runIfNecessary() - assert.Assert(c.Base.T, res.ExitCode == exitCode, res.Combined()) + assert.Assert(c.Base.T, res.ExitCode == exitCode, res) } func (c *Cmd) AssertOutContains(s string) { @@ -502,21 +502,21 @@ func (c *Cmd) AssertOutStreamsExactly(stdout, stderr string) { func (c *Cmd) AssertOutWithFunc(fn func(stdout string) error) { c.Base.T.Helper() res := c.runIfNecessary() - assert.Equal(c.Base.T, 0, res.ExitCode, res.Combined()) + assert.Equal(c.Base.T, 0, res.ExitCode, res) assert.NilError(c.Base.T, fn(res.Stdout()), res.Combined()) } func (c *Cmd) AssertOutStreamsWithFunc(fn func(stdout, stderr string) error) { c.Base.T.Helper() res := c.runIfNecessary() - assert.Equal(c.Base.T, 0, res.ExitCode, res.Combined()) + assert.Equal(c.Base.T, 0, res.ExitCode, res) assert.NilError(c.Base.T, fn(res.Stdout(), res.Stderr()), res.Combined()) } func (c *Cmd) Out() string { c.Base.T.Helper() res := c.runIfNecessary() - assert.Equal(c.Base.T, 0, res.ExitCode, res.Combined()) + assert.Equal(c.Base.T, 0, res.ExitCode, res) return res.Stdout() } From fbf9a53803aa10c69280b45b8cbbbcf6c7e80368 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jul 2024 22:44:52 +0000 Subject: [PATCH 0560/1066] build(deps): bump golang.org/x/crypto from 0.24.0 to 0.25.0 Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.24.0 to 0.25.0. - [Commits](https://github.com/golang/crypto/compare/v0.24.0...v0.25.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3ab2255a049..7f98f9462d0 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.24.0 + golang.org/x/crypto v0.25.0 golang.org/x/net v0.26.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.22.0 diff --git a/go.sum b/go.sum index 3a0a4efa641..d9fc9ef7657 100644 --- a/go.sum +++ b/go.sum @@ -338,8 +338,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= From f83f23806be04332946dd29ac65063b3c315faa5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jul 2024 23:30:40 +0000 Subject: [PATCH 0561/1066] build(deps): bump golang.org/x/net from 0.26.0 to 0.27.0 Bumps [golang.org/x/net](https://github.com/golang/net) from 0.26.0 to 0.27.0. - [Commits](https://github.com/golang/net/compare/v0.26.0...v0.27.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7f98f9462d0..1f05721c975 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,7 @@ require ( github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 golang.org/x/crypto v0.25.0 - golang.org/x/net v0.26.0 + golang.org/x/net v0.27.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.22.0 golang.org/x/term v0.22.0 diff --git a/go.sum b/go.sum index d9fc9ef7657..20dbd0f22d9 100644 --- a/go.sum +++ b/go.sum @@ -363,8 +363,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 156b5fd021c8d40c8204cfa56b4fc9b3f0f2dc4a Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 5 Jul 2024 15:50:57 -0700 Subject: [PATCH 0562/1066] Do not hard error if containers are gone Signed-off-by: apostasie --- pkg/cmd/container/run_mount.go | 7 +++++++ pkg/cmd/volume/rm.go | 1 + 2 files changed, 8 insertions(+) diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index 3a53c8c6f70..0d94860ff83 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -19,6 +19,7 @@ package container import ( "context" "encoding/json" + "errors" "fmt" "os" "path/filepath" @@ -307,6 +308,12 @@ func generateMountOpts(ctx context.Context, client *containerd.Client, ensuredIm for _, c := range containers { ls, err := c.Labels(ctx) if err != nil { + // Containerd note: there is no guarantee that the containers we got from the list still exist at this point + // If that is the case, just ignore and move on + if errors.Is(err, errdefs.ErrNotFound) { + log.G(ctx).Debugf("container %q is gone - ignoring", c.ID()) + continue + } return nil, nil, nil, err } _, idMatch := vfSet[c.ID()] diff --git a/pkg/cmd/volume/rm.go b/pkg/cmd/volume/rm.go index 2c74df9f1b2..23413a2b500 100644 --- a/pkg/cmd/volume/rm.go +++ b/pkg/cmd/volume/rm.go @@ -79,6 +79,7 @@ func usedVolumes(ctx context.Context, containers []containerd.Container) (map[st // Containerd note: there is no guarantee that the containers we got from the list still exist at this point // If that is the case, just ignore and move on if errors.Is(err, errdefs.ErrNotFound) { + log.G(ctx).Debugf("container %q is gone - ignoring", c.ID()) continue } return nil, err From fceea23b9d722dc924717554c994f16cc3ff132a Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 5 Jul 2024 18:27:50 -0700 Subject: [PATCH 0563/1066] Ensure we dont fail if containers disappear (#3167) Signed-off-by: apostasie --- pkg/netutil/netutil.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 10a4b99148b..3bf69ded3dc 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -88,12 +88,17 @@ func namespaceUsedNetworks(ctx context.Context, containers []containerd.Containe task, err := c.Task(ctx, nil) if err != nil { if errdefs.IsNotFound(err) { + log.G(ctx).Debugf("task not found - likely container %q was removed", c.ID()) continue } return nil, err } status, err := task.Status(ctx) if err != nil { + if errdefs.IsNotFound(err) { + log.G(ctx).Debugf("task not found - likely container %q was removed", c.ID()) + continue + } return nil, err } switch status.Status { @@ -103,6 +108,10 @@ func namespaceUsedNetworks(ctx context.Context, containers []containerd.Containe } l, err := c.Labels(ctx) if err != nil { + if errdefs.IsNotFound(err) { + log.G(ctx).Debugf("container %q is gone", c.ID()) + continue + } return nil, err } networkJSON, ok := l[labels.Networks] From c4ea3d0e1b6d87290b701d491fccc18ba82e68ff Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 5 Jul 2024 00:07:06 -0700 Subject: [PATCH 0564/1066] Fix IPFS test flakyness Signed-off-by: apostasie --- cmd/nerdctl/ipfs_compose_linux_test.go | 10 ++- cmd/nerdctl/ipfs_linux_test.go | 35 ++------ .../testregistry/testregistry_linux.go | 81 ++++++++++++++++++- 3 files changed, 92 insertions(+), 34 deletions(-) diff --git a/cmd/nerdctl/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs_compose_linux_test.go index 06f211f3897..1872d24596e 100644 --- a/cmd/nerdctl/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs_compose_linux_test.go @@ -24,14 +24,20 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" "gotest.tools/v3/assert" ) func TestIPFSComposeUp(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - ipfsaddr, done := runIPFSDaemonContainer(t, base) - defer done() + + iReg := testregistry.NewIPFSRegistry(base, nil, 0, nil, nil) + t.Cleanup(func() { + iReg.Cleanup(nil) + }) + ipfsaddr := fmt.Sprintf("/ip4/%s/tcp/%d", iReg.IP, iReg.Port) + tests := []struct { name string snapshotter string diff --git a/cmd/nerdctl/ipfs_linux_test.go b/cmd/nerdctl/ipfs_linux_test.go index f86d7d92a97..cb4e6e32efe 100644 --- a/cmd/nerdctl/ipfs_linux_test.go +++ b/cmd/nerdctl/ipfs_linux_test.go @@ -18,12 +18,12 @@ package main import ( "fmt" - "regexp" "testing" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" "gotest.tools/v3/assert" ) @@ -57,42 +57,21 @@ func TestIPFS(t *testing.T) { base.Cmd("run", "--rm", decryptImageRef, "/bin/sh", "-c", "echo hello").AssertOK() } -var iplineRegexp = regexp.MustCompile(`"([0-9\.]*)"`) - func TestIPFSAddress(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - ipfsaddr, done := runIPFSDaemonContainer(t, base) - defer done() + iReg := testregistry.NewIPFSRegistry(base, nil, 0, nil, nil) + t.Cleanup(func() { + iReg.Cleanup(nil) + }) + ipfsaddr := fmt.Sprintf("/ip4/%s/tcp/%d", iReg.IP, iReg.Port) + ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, fmt.Sprintf("--ipfs-address=%s", ipfsaddr)) base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=overlayfs") base.Cmd("pull", "--ipfs-address", ipfsaddr, ipfsCID).AssertOK() base.Cmd("run", "--ipfs-address", ipfsaddr, "--rm", ipfsCID, "echo", "hello").AssertOK() } -func runIPFSDaemonContainer(t *testing.T, base *testutil.Base) (ipfsAddress string, done func()) { - name := "test-ipfs-address" - var ipfsaddr string - if detachedNetNS, _ := rootlessutil.DetachedNetNS(); detachedNetNS != "" { - // detached-netns mode can't use .NetworkSettings.IPAddress, because the daemon and CNI has different network namespaces - base.Cmd("run", "-d", "-p", "127.0.0.1:5999:5999", "--name", name, "--entrypoint=/bin/sh", testutil.KuboImage, "-c", "ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/5999 && ipfs daemon --offline").AssertOK() - ipfsaddr = "/ip4/127.0.0.1/tcp/5999" - } else { - base.Cmd("run", "-d", "--name", name, "--entrypoint=/bin/sh", testutil.KuboImage, "-c", "ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/5001 && ipfs daemon --offline").AssertOK() - iplines := base.Cmd("inspect", name, "-f", "'{{json .NetworkSettings.IPAddress}}'").OutLines() - t.Logf("IPAddress=%v", iplines) - assert.Equal(t, len(iplines), 2) - matches := iplineRegexp.FindStringSubmatch(iplines[0]) - t.Logf("ip address matches=%v", matches) - assert.Equal(t, len(matches), 2) - ipfsaddr = fmt.Sprintf("/ip4/%s/tcp/5001", matches[1]) - } - return ipfsaddr, func() { - base.Cmd("kill", "test-ipfs-address").AssertOK() - base.Cmd("rm", "test-ipfs-address").AssertOK() - } -} - func TestIPFSCommit(t *testing.T) { // cgroup is required for nerdctl commit if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { diff --git a/pkg/testutil/testregistry/testregistry_linux.go b/pkg/testutil/testregistry/testregistry_linux.go index b5c05525846..a5b60aaf834 100644 --- a/pkg/testutil/testregistry/testregistry_linux.go +++ b/pkg/testutil/testregistry/testregistry_linux.go @@ -55,6 +55,7 @@ type TokenAuthServer struct { func EnsureImages(base *testutil.Base) { base.Cmd("pull", testutil.RegistryImage).AssertOK() base.Cmd("pull", testutil.DockerAuthImage).AssertOK() + base.Cmd("pull", testutil.KuboImage).AssertOK() } func NewAuthServer(base *testutil.Base, ca *testca.CA, port int, user, pass string, tls bool) *TokenAuthServer { @@ -112,6 +113,8 @@ acl: port, err = portlock.Acquire(port) assert.NilError(base.T, err, fmt.Errorf("failed acquiring port: %w", err)) containerName := fmt.Sprintf("auth-%s-%d", name, port) + // Cleanup possible leftovers first + base.Cmd("rm", "-f", containerName).Run() cleanup := func(err error) { result := base.Cmd("rm", "-f", containerName).Run() @@ -232,7 +235,78 @@ func (ba *BasicAuth) Params(base *testutil.Base) []string { return ret } +func NewIPFSRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundCleanup func(error)) *RegistryServer { + EnsureImages(base) + + name := testutil.Identifier(base.T) + // listen on 0.0.0.0 to enable 127.0.0.1 + listenIP := net.ParseIP("0.0.0.0") + hostIP, err := nettestutil.NonLoopbackIPv4() + assert.NilError(base.T, err, fmt.Errorf("failed finding ipv4 non loopback interface: %w", err)) + port, err = portlock.Acquire(port) + assert.NilError(base.T, err, fmt.Errorf("failed acquiring port: %w", err)) + + containerName := fmt.Sprintf("ipfs-registry-%s-%d", name, port) + // Cleanup possible leftovers first + base.Cmd("rm", "-f", containerName).Run() + + args := []string{ + "run", + "--pull=never", + "-d", + "-p", fmt.Sprintf("%s:%d:%d", listenIP, port, port), + "--name", containerName, + "--entrypoint=/bin/sh", + testutil.KuboImage, + "-c", "--", + fmt.Sprintf("ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/%d && ipfs daemon --offline", port), + } + + cleanup := func(err error) { + result := base.Cmd("rm", "-f", containerName).Run() + errPortRelease := portlock.Release(port) + if boundCleanup != nil { + boundCleanup(err) + } + if err == nil { + assert.NilError(base.T, result.Error, fmt.Errorf("failed removing container: %w", err)) + assert.NilError(base.T, errPortRelease, fmt.Errorf("failed releasing port: %w", err)) + } + } + + scheme := "http" + + err = func() error { + cmd := base.Cmd(args...).Run() + if cmd.Error != nil { + base.T.Logf("%s:\n%s\n%s\n-------\n%s", containerName, cmd.Cmd, cmd.Stdout(), cmd.Stderr()) + return cmd.Error + } + + if _, err = nettestutil.HTTPGet(fmt.Sprintf("%s://%s:%s/api/v0", scheme, hostIP.String(), strconv.Itoa(port)), 30, true); err != nil { + return err + } + + return nil + }() + + assert.NilError(base.T, err, fmt.Errorf("failed starting IPFS registry container in a timely manner: %w", err)) + + return &RegistryServer{ + IP: hostIP, + Port: port, + Scheme: scheme, + ListenIP: listenIP, + Cleanup: cleanup, + Logs: func() { + base.T.Logf("%s: %q", containerName, base.Cmd("logs", containerName).Run().String()) + }, + } +} + func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundCleanup func(error)) *RegistryServer { + EnsureImages(base) + name := testutil.Identifier(base.T) // listen on 0.0.0.0 to enable 127.0.0.1 listenIP := net.ParseIP("0.0.0.0") @@ -242,6 +316,9 @@ func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundC assert.NilError(base.T, err, fmt.Errorf("failed acquiring port: %w", err)) containerName := fmt.Sprintf("registry-%s-%d", name, port) + // Cleanup possible leftovers first + base.Cmd("rm", "-f", containerName).Run() + args := []string{ "run", "--pull=never", @@ -325,8 +402,6 @@ func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundC }() if err != nil { - // cs := base.Cmd("inspect", containerName).Run() - // base.T.Logf("%s:\n%s\n%s\n=========================\n%s", containerName, cs.Cmd, cs.Stdout(), cs.Stderr()) cl := base.Cmd("logs", containerName).Run() base.T.Logf("%s:\n%s\n%s\n=========================\n%s", containerName, cl.Cmd, cl.Stdout(), cl.Stderr()) cleanup(err) @@ -357,8 +432,6 @@ func NewWithTokenAuth(base *testutil.Base, user, pass string, port int, tls bool } func NewWithNoAuth(base *testutil.Base, port int, tls bool) *RegistryServer { - EnsureImages(base) - var ca *testca.CA if tls { ca = testca.New(base.T) From 81aac851b4e4576fda1767ad31ce556f6bfd73fc Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 8 Jul 2024 17:46:05 +0900 Subject: [PATCH 0565/1066] rootless: add `Requires=dbus.socket` Equates to moby/moby PR 48134 Signed-off-by: Akihiro Suda --- extras/rootless/containerd-rootless-setuptool.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/extras/rootless/containerd-rootless-setuptool.sh b/extras/rootless/containerd-rootless-setuptool.sh index 9b005c7cce0..747d5c41c87 100755 --- a/extras/rootless/containerd-rootless-setuptool.sh +++ b/extras/rootless/containerd-rootless-setuptool.sh @@ -230,6 +230,7 @@ cmd_entrypoint_install() { cat <<-EOT | install_systemd_unit "${SYSTEMD_CONTAINERD_UNIT}" [Unit] Description=containerd (Rootless) + Requires=dbus.socket [Service] Environment=PATH=$BIN:/sbin:/usr/sbin:$PATH From fee1ab365e99ff3790d2c27406eca13917b2fb5b Mon Sep 17 00:00:00 2001 From: Iceber Gu Date: Mon, 8 Jul 2024 17:56:52 +0800 Subject: [PATCH 0566/1066] fix the created tasks cannot be deleted Signed-off-by: Iceber Gu --- pkg/cmd/container/remove.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 4dca4d117a2..3bf655b6118 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -274,8 +274,17 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions if err == nil { <-es } - case containerd.Created, containerd.Stopped: - // Created and stopped containers always get removed + case containerd.Created: + // TODO(Iceber): Since `containerd.WithProcessKill` blocks the killing of tasks with PID 0, + // remove the judgment and break when it is compatible with the tasks. + if task.Pid() == 0 { + // Created tasks with PID 0 always get removed + // Delete the task, without forcing kill + _, err = task.Delete(ctx) + return err + } + case containerd.Stopped: + // Stopped containers always get removed // Delete the task, without forcing kill _, err = task.Delete(ctx) return err From c3ea8ff4de6870ced0b7c73f8df0602f117f6a6d Mon Sep 17 00:00:00 2001 From: TinaMor Date: Mon, 1 Jul 2024 22:20:33 +0300 Subject: [PATCH 0567/1066] Fix nerdctl info missing on Windows Signed-off-by: Tina Murimi --- pkg/cmd/system/info.go | 62 +++--- pkg/infoutil/infoutil_unix.go | 1 - pkg/infoutil/infoutil_windows.go | 193 ++++++++++++++++++- pkg/infoutil/infoutil_windows_test.go | 200 ++++++++++++++++++++ pkg/infoutil/infoutilmock/info.util.mock.go | 108 +++++++++++ 5 files changed, 533 insertions(+), 31 deletions(-) create mode 100644 pkg/infoutil/infoutil_windows_test.go create mode 100644 pkg/infoutil/infoutilmock/info.util.mock.go diff --git a/pkg/cmd/system/info.go b/pkg/cmd/system/info.go index 5e87cf24fc4..6fce7d68334 100644 --- a/pkg/cmd/system/info.go +++ b/pkg/cmd/system/info.go @@ -25,19 +25,19 @@ import ( "text/template" "github.com/containerd/containerd" + "github.com/containerd/containerd/api/services/introspection/v1" "github.com/containerd/log" - "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/docker/go-units" "golang.org/x/text/cases" "golang.org/x/text/language" - "github.com/containerd/containerd/api/services/introspection/v1" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/docker/go-units" ) func Info(ctx context.Context, client *containerd.Client, options types.SystemInfoOptions) error { @@ -153,13 +153,45 @@ func prettyPrintInfoDockerCompat(stdout io.Writer, stderr io.Writer, info *docke // Storage Driver is not really Server concept for nerdctl, but mimics `docker info` output fmt.Fprintf(w, " Storage Driver: %s\n", info.Driver) fmt.Fprintf(w, " Logging Driver: %s\n", info.LoggingDriver) - fmt.Fprintf(w, " Cgroup Driver: %s\n", info.CgroupDriver) - fmt.Fprintf(w, " Cgroup Version: %s\n", info.CgroupVersion) + printF(w, " Cgroup Driver: ", info.CgroupDriver) + printF(w, " Cgroup Version: ", info.CgroupVersion) fmt.Fprintf(w, " Plugins:\n") - fmt.Fprintf(w, " Log: %s\n", strings.Join(info.Plugins.Log, " ")) + fmt.Fprintf(w, " Log: %s\n", strings.Join(info.Plugins.Log, " ")) fmt.Fprintf(w, " Storage: %s\n", strings.Join(info.Plugins.Storage, " ")) + + // print Security options + printSecurityOptions(w, info.SecurityOptions) + + fmt.Fprintf(w, " Kernel Version: %s\n", info.KernelVersion) + fmt.Fprintf(w, " Operating System: %s\n", info.OperatingSystem) + fmt.Fprintf(w, " OSType: %s\n", info.OSType) + fmt.Fprintf(w, " Architecture: %s\n", info.Architecture) + fmt.Fprintf(w, " CPUs: %d\n", info.NCPU) + fmt.Fprintf(w, " Total Memory: %s\n", units.BytesSize(float64(info.MemTotal))) + fmt.Fprintf(w, " Name: %s\n", info.Name) + fmt.Fprintf(w, " ID: %s\n", info.ID) + + fmt.Fprintln(w) + if len(info.Warnings) > 0 { + fmt.Fprintln(stderr, strings.Join(info.Warnings, "\n")) + } + return nil +} + +func printF(w io.Writer, label string, dockerCompatInfo string) { + if dockerCompatInfo == "" { + return + } + fmt.Fprintf(w, " %s: %s\n", label, dockerCompatInfo) +} + +func printSecurityOptions(w io.Writer, securityOptions []string) { + if len(securityOptions) == 0 { + return + } + fmt.Fprintf(w, " Security Options:\n") - for _, s := range info.SecurityOptions { + for _, s := range securityOptions { m, err := strutil.ParseCSVMap(s) if err != nil { log.L.WithError(err).Warnf("unparsable security option %q", s) @@ -175,21 +207,7 @@ func prettyPrintInfoDockerCompat(stdout io.Writer, stderr io.Writer, info *docke if k == "name" { continue } - fmt.Fprintf(w, " %s: %s\n", cases.Title(language.English).String(k), v) + fmt.Fprintf(w, " %s:\t%s\n", cases.Title(language.English).String(k), v) } } - fmt.Fprintf(w, " Kernel Version: %s\n", info.KernelVersion) - fmt.Fprintf(w, " Operating System: %s\n", info.OperatingSystem) - fmt.Fprintf(w, " OSType: %s\n", info.OSType) - fmt.Fprintf(w, " Architecture: %s\n", info.Architecture) - fmt.Fprintf(w, " CPUs: %d\n", info.NCPU) - fmt.Fprintf(w, " Total Memory: %s\n", units.BytesSize(float64(info.MemTotal))) - fmt.Fprintf(w, " Name: %s\n", info.Name) - fmt.Fprintf(w, " ID: %s\n", info.ID) - - fmt.Fprintln(w) - if len(info.Warnings) > 0 { - fmt.Fprintln(stderr, strings.Join(info.Warnings, "\n")) - } - return nil } diff --git a/pkg/infoutil/infoutil_unix.go b/pkg/infoutil/infoutil_unix.go index 782a17537f0..1a4068a067a 100644 --- a/pkg/infoutil/infoutil_unix.go +++ b/pkg/infoutil/infoutil_unix.go @@ -23,7 +23,6 @@ import ( "io" "os" "regexp" - "strings" "golang.org/x/sys/unix" diff --git a/pkg/infoutil/infoutil_windows.go b/pkg/infoutil/infoutil_windows.go index 7612bd2015a..6f01255a7b6 100644 --- a/pkg/infoutil/infoutil_windows.go +++ b/pkg/infoutil/infoutil_windows.go @@ -17,33 +17,210 @@ package infoutil import ( - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "fmt" + "runtime" + "strings" + + "github.com/containerd/log" + "github.com/docker/docker/pkg/meminfo" "github.com/docker/docker/pkg/sysinfo" + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" ) -// UnameR returns `uname -r` +const UnameO = "Microsoft Windows" + +// MsiNTProductType is the product type of the operating system. +// https://learn.microsoft.com/en-us/windows/win32/msi/msintproducttype +// Ref: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoexa +const ( + verNTServer = 0x0000003 +) + +type windowsInfoUtil interface { + RtlGetVersion() *windows.OsVersionInfoEx + GetRegistryStringValue(key registry.Key, path string, name string) (string, error) + GetRegistryIntValue(key registry.Key, path string, name string) (int, error) +} + +type winInfoUtil struct{} + +// RtlGetVersion implements the RtlGetVersion method using the actual windows package +func (sw *winInfoUtil) RtlGetVersion() *windows.OsVersionInfoEx { + return windows.RtlGetVersion() +} + +// UnameR returns the Kernel version func UnameR() string { - return "" + util := &winInfoUtil{} + version, err := getKernelVersion(util) + if err != nil { + log.L.Error(err.Error()) + } + + return version } -// UnameM returns `uname -m` +// UnameM returns the architecture of the system func UnameM() string { - return "" + arch := runtime.GOARCH + + if strings.ToLower(arch) == "amd64" { + return "x86_64" + } + + // "386": 32-bit Intel/AMD processors (x86 architecture) + if strings.ToLower(arch) == "386" { + return "x86" + } + + // arm, s390x, and so on + return arch } +// DistroName returns version information about the currently running operating system func DistroName() string { - return "" + util := &winInfoUtil{} + version, err := distroName(util) + if err != nil { + log.L.Error(err.Error()) + } + + return version } +func distroName(sw windowsInfoUtil) (string, error) { + // Get the OS version information from the Windows registry + regPath := `SOFTWARE\Microsoft\Windows NT\CurrentVersion` + + // Eg. 22631 (REG_SZ) + currBuildNo, err := sw.GetRegistryStringValue(registry.LOCAL_MACHINE, regPath, "CurrentBuildNumber") + if err != nil { + return "", fmt.Errorf("failed to get os version (build number) %v", err) + } + + // Eg. 23H2 (REG_SZ) + displayVersion, err := sw.GetRegistryStringValue(registry.LOCAL_MACHINE, regPath, "DisplayVersion") + if err != nil { + return "", fmt.Errorf("failed to get os version (display version) %v", err) + } + + // UBR: Update Build Revision. Eg. 3737 (REG_DWORD 32-bit Value) + ubr, err := sw.GetRegistryIntValue(registry.LOCAL_MACHINE, regPath, "UBR") + if err != nil { + return "", fmt.Errorf("failed to get os version (ubr) %v", err) + } + + productType := "" + if isWindowsServer(sw) { + productType = "Server" + } + + // Concatenate the reg.key values to get the OS version information + // Example: "Microsoft Windows Version 23H2 (OS Build 22631.3737)" + versionString := fmt.Sprintf("%s %s Version %s (OS Build %s.%d)", + UnameO, + productType, + displayVersion, + currBuildNo, + ubr, + ) + + // Replace double spaces with single spaces + versionString = strings.ReplaceAll(versionString, " ", " ") + + return versionString, nil +} + +func getKernelVersion(sw windowsInfoUtil) (string, error) { + // Get BuildLabEx value from the Windows registry + // [buiild number].[revision number].[architecture].[branch].[date]-[time] + // Eg. "BuildLabEx: 10240.16412.amd64fre.th1.150729-1800" + buildLab, err := sw.GetRegistryStringValue(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, "BuildLabEx") + if err != nil { + return "", err + } + + // Get Version: Contains the major and minor version numbers of the operating system. + // Eg. "10.0" + osvi := sw.RtlGetVersion() + + // Concatenate the OS version and BuildLabEx values to get the Kernel version information + // Example: "10.0 22631 (10240.16412.amd64fre.th1.150729-1800)" + version := fmt.Sprintf("%d.%d %d (%s)", osvi.MajorVersion, osvi.MinorVersion, osvi.BuildNumber, buildLab) + return version, nil +} + +// GetRegistryStringValue retrieves a string value from the Windows registry +func (sw *winInfoUtil) GetRegistryStringValue(key registry.Key, path string, name string) (string, error) { + k, err := registry.OpenKey(key, path, registry.QUERY_VALUE) + if err != nil { + return "", err + } + defer k.Close() + + v, _, err := k.GetStringValue(name) + if err != nil { + return "", err + } + return v, nil +} + +// GetRegistryIntValue retrieves an integer value from the Windows registry +func (sw *winInfoUtil) GetRegistryIntValue(key registry.Key, path string, name string) (int, error) { + k, err := registry.OpenKey(key, path, registry.QUERY_VALUE) + if err != nil { + return 0, err + } + defer k.Close() + + v, _, err := k.GetIntegerValue(name) + if err != nil { + return 0, err + } + return int(v), nil +} + +func isWindowsServer(sw windowsInfoUtil) bool { + osvi := sw.RtlGetVersion() + return osvi.ProductType == verNTServer +} + +// Cgroups not supported on Windows func CgroupsVersion() string { return "" } func fulfillPlatformInfo(info *dockercompat.Info) { - // unimplemented + mobySysInfo := mobySysInfo(info) + + // NOTE: cgroup fields are not available on Windows + // https://techcommunity.microsoft.com/t5/containers/introducing-the-host-compute-service-hcs/ba-p/382332 + + info.IPv4Forwarding = !mobySysInfo.IPv4ForwardingDisabled + if !info.IPv4Forwarding { + info.Warnings = append(info.Warnings, "WARNING: IPv4 forwarding is disabled") + } + info.BridgeNfIptables = !mobySysInfo.BridgeNFCallIPTablesDisabled + if !info.BridgeNfIptables { + info.Warnings = append(info.Warnings, "WARNING: bridge-nf-call-iptables is disabled") + } + info.BridgeNfIP6tables = !mobySysInfo.BridgeNFCallIP6TablesDisabled + if !info.BridgeNfIP6tables { + info.Warnings = append(info.Warnings, "WARNING: bridge-nf-call-ip6tables is disabled") + } + info.NCPU = sysinfo.NumCPU() + memLimit, err := meminfo.Read() + if err != nil { + info.Warnings = append(info.Warnings, fmt.Sprintf("failed to read mem info: %v", err)) + } else { + info.MemTotal = memLimit.MemTotal + } } -func mobySysInfo(info *dockercompat.Info) *sysinfo.SysInfo { +func mobySysInfo(_ *dockercompat.Info) *sysinfo.SysInfo { var sysinfo sysinfo.SysInfo return &sysinfo } diff --git a/pkg/infoutil/infoutil_windows_test.go b/pkg/infoutil/infoutil_windows_test.go new file mode 100644 index 00000000000..d59c157513c --- /dev/null +++ b/pkg/infoutil/infoutil_windows_test.go @@ -0,0 +1,200 @@ +/* + 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 infoutil + +import ( + "testing" + + mocks "github.com/containerd/nerdctl/v2/pkg/infoutil/infoutilmock" + "go.uber.org/mock/gomock" + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" + "gotest.tools/v3/assert" +) + +func setUpMocks(t *testing.T) *mocks.MockWindowsInfoUtil { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockInfoUtil := mocks.NewMockWindowsInfoUtil(ctrl) + + // Mock registry value: CurrentBuildNumber + mockInfoUtil. + EXPECT(). + GetRegistryStringValue(gomock.Any(), gomock.Any(), "CurrentBuildNumber"). + Return("19041", nil). + AnyTimes() + + // Mock registry value: DisplayVersion + mockInfoUtil. + EXPECT(). + GetRegistryStringValue(gomock.Any(), gomock.Any(), "DisplayVersion"). + Return("22H4", nil). + AnyTimes() + + // Mock registry value: UBR + mockInfoUtil. + EXPECT(). + GetRegistryIntValue(gomock.Any(), gomock.Any(), "UBR"). + Return(558, nil). + AnyTimes() + + return mockInfoUtil +} + +const ( + verNTWorkStation = 0x0000001 + verNTDomainController = 0x0000002 +) + +func TestDistroName(t *testing.T) { + mockInfoUtil := setUpMocks(t) + + baseVersion := windows.OsVersionInfoEx{ + MajorVersion: 10, + MinorVersion: 0, + BuildNumber: 19041, + } + + tests := []struct { + productType byte + expected string + }{ + { + productType: verNTWorkStation, + expected: "Microsoft Windows Version 22H4 (OS Build 19041.558)", + }, + { + productType: verNTServer, + expected: "Microsoft Windows Server Version 22H4 (OS Build 19041.558)", + }, + } + + for _, tt := range tests { + // Mock sys/windows RtlGetVersion + osvi := baseVersion + osvi.ProductType = tt.productType + mockInfoUtil.EXPECT().RtlGetVersion().Return(&osvi).Times(1) + + t.Run(tt.expected, func(t *testing.T) { + actual, err := distroName(mockInfoUtil) + assert.Equal(t, tt.expected, actual, "distroName should return the name of the operating system") + assert.NilError(t, err) + }) + } +} + +func TestDistroNameError(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockInfoUtil := mocks.NewMockWindowsInfoUtil(ctrl) + + mockInfoUtil.EXPECT().RtlGetVersion().Return(nil).Times(0) + mockInfoUtil. + EXPECT(). + GetRegistryStringValue(gomock.Any(), gomock.Any(), gomock.Any()). + Return("19041", registry.ErrNotExist).AnyTimes() + + actual, err := distroName(mockInfoUtil) + assert.ErrorContains(t, err, registry.ErrNotExist.Error(), "distroName should return an error on error") + assert.Equal(t, "", actual, "distroname should return an empty string on error") +} + +func TestGetKernelVersion(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockInfoUtil := mocks.NewMockWindowsInfoUtil(ctrl) + + // Mock registry value: BuildLabEx + mockInfoUtil. + EXPECT(). + GetRegistryStringValue(gomock.Any(), gomock.Any(), "BuildLabEx"). + Return("10240.16412.amd64fre.th1.150729-1800", nil). + Times(1) + + baseVersion := windows.OsVersionInfoEx{ + MajorVersion: 10, + MinorVersion: 0, + BuildNumber: 19041, + } + + expected := "10.0 19041 (10240.16412.amd64fre.th1.150729-1800)" + + // Mock sys/windows RtlGetVersion + osvi := baseVersion + mockInfoUtil.EXPECT().RtlGetVersion().Return(&osvi).Times(1) + + actual, err := getKernelVersion(mockInfoUtil) + assert.NilError(t, err) + assert.Equal(t, expected, actual, "getKernelVersion should return the kernel version") +} + +func TestGetKernelVersionError(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockInfoUtil := mocks.NewMockWindowsInfoUtil(ctrl) + + mockInfoUtil.EXPECT().RtlGetVersion().Return(nil).Times(0) + mockInfoUtil. + EXPECT(). + GetRegistryStringValue(gomock.Any(), gomock.Any(), gomock.Any()). + Return("", registry.ErrNotExist).Times(1) + + actual, err := getKernelVersion(mockInfoUtil) + assert.ErrorContains(t, err, registry.ErrNotExist.Error(), "getKernelVersion should return an error on error") + assert.Equal(t, "", actual, "getKernelVersion should return an empty string on error") +} + +func TestIsWindowsServer(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + tests := []struct { + productType string + osvi windows.OsVersionInfoEx + expected bool + }{ + { + productType: "VER_NT_WORKSTATION", + osvi: windows.OsVersionInfoEx{ProductType: verNTWorkStation}, + expected: false, + }, + { + productType: "VER_NT_DOMAIN_CONTROLLER", + osvi: windows.OsVersionInfoEx{ProductType: verNTDomainController}, + expected: false, + }, + { + productType: "VER_NT_SERVER", + osvi: windows.OsVersionInfoEx{ProductType: verNTServer}, + expected: true, + }, + } + + mockSysCall := mocks.NewMockWindowsInfoUtil(ctrl) + for _, tt := range tests { + mockSysCall.EXPECT().RtlGetVersion().Return(&tt.osvi) + + t.Run(tt.productType, func(t *testing.T) { + actual := isWindowsServer(mockSysCall) + assert.Equal(t, tt.expected, actual, "isWindowsServer should return true on Windows Server") + }) + } +} diff --git a/pkg/infoutil/infoutilmock/info.util.mock.go b/pkg/infoutil/infoutilmock/info.util.mock.go new file mode 100644 index 00000000000..298597ece67 --- /dev/null +++ b/pkg/infoutil/infoutilmock/info.util.mock.go @@ -0,0 +1,108 @@ +//go:build windows + +/* + 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 infoutilmock + +import ( + "reflect" + + "go.uber.org/mock/gomock" + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" +) + +// MockWindowsInfoUtil is a mock of windowsInfoUtil interface +type MockWindowsInfoUtil struct { + ctrl *gomock.Controller + recorder *MockWindowsInfoUtilMockRecorder +} + +// MockWindowsInfoUtilMockRecorder is the mock recorder for MockWindowsInfoUtil +type MockWindowsInfoUtilMockRecorder struct { + mock *MockWindowsInfoUtil +} + +// NewMockWindowsInfoUtil creates a new mock instance +func NewMockWindowsInfoUtil(ctrl *gomock.Controller) *MockWindowsInfoUtil { + mock := &MockWindowsInfoUtil{ctrl: ctrl} + mock.recorder = &MockWindowsInfoUtilMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockWindowsInfoUtil) EXPECT() *MockWindowsInfoUtilMockRecorder { + return m.recorder +} + +// Create mocks the RtlGetVersion method of windowsInfoUtil +func (m *MockWindowsInfoUtil) RtlGetVersion() *windows.OsVersionInfoEx { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RtlGetVersion") + ret0, _ := ret[0].(*windows.OsVersionInfoEx) + return ret0 +} + +// Expected call of RtlGetVersion +func (m *MockWindowsInfoUtilMockRecorder) RtlGetVersion() *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType( + m.mock, + "RtlGetVersion", + reflect.TypeOf((*MockWindowsInfoUtil)(nil).RtlGetVersion), + ) +} + +// Create mocks the GetRegistryStringValue method of windowsInfoUtil +func (m *MockWindowsInfoUtil) GetRegistryStringValue(key registry.Key, path string, name string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRegistryStringValue", key, path, name) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Expected call of GetRegistryStringValue +func (m *MockWindowsInfoUtilMockRecorder) GetRegistryStringValue(key any, path any, name any) *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType( + m.mock, + "GetRegistryStringValue", + reflect.TypeOf((*MockWindowsInfoUtil)(nil).GetRegistryStringValue), + key, path, name, + ) +} + +// Create mocks the GetRegistryIntValue method of windowsInfoUtil +func (m *MockWindowsInfoUtil) GetRegistryIntValue(key registry.Key, path string, name string) (int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRegistryIntValue", key, path, name) + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Expected call of GetRegistryIntValue +func (m *MockWindowsInfoUtilMockRecorder) GetRegistryIntValue(key any, path any, name any) *gomock.Call { + m.mock.ctrl.T.Helper() + return m.mock.ctrl.RecordCallWithMethodType( + m.mock, + "GetRegistryIntValue", + reflect.TypeOf((*MockWindowsInfoUtil)(nil).GetRegistryIntValue), + key, path, name, + ) +} From 11a0d9ac9eab5fa55e42e7ec4f6ed276489d4595 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 8 Jul 2024 10:39:24 -0700 Subject: [PATCH 0568/1066] Move to 24.04 for docker integration testing Signed-off-by: apostasie --- .github/workflows/test.yml | 2 +- cmd/nerdctl/container_logs_test.go | 17 ++++++++++++----- cmd/nerdctl/container_run_cgroup_linux_test.go | 14 +++++++++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b6693a2f6a7..2043aa83cbe 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -253,7 +253,7 @@ jobs: run: GO_VERSION="$(echo ${{ matrix.go-version }} | sed -e s/.x//)" make binaries test-integration-docker-compatibility: - runs-on: ubuntu-22.04 # TODO: ubuntu-24.04 + runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - uses: actions/checkout@v4.1.7 diff --git a/cmd/nerdctl/container_logs_test.go b/cmd/nerdctl/container_logs_test.go index 397aa0c1ad6..944b48486d2 100644 --- a/cmd/nerdctl/container_logs_test.go +++ b/cmd/nerdctl/container_logs_test.go @@ -209,7 +209,12 @@ func TestLogsWithForegroundContainers(t *testing.T) { } func TestTailFollowRotateLogs(t *testing.T) { - t.Parallel() + // FIXME this is flaky by nature... 5 lines is arbitrary, 2000 ms is arbitrary, and both are some sort of educated + // guess that things will mostly always kinda work maybe... + // Furthermore, parallelizing will put pressure on the daemon which might be even slower in answering, increasing + // the risk of transient failure. + // This test needs to be rethought entirely + // t.Parallel() if runtime.GOOS == "windows" { t.Skip("tail log is not supported on Windows") } @@ -217,7 +222,7 @@ func TestTailFollowRotateLogs(t *testing.T) { containerName := testutil.Identifier(t) const sampleJSONLog = `{"log":"A\n","stream":"stdout","time":"2024-04-11T12:01:09.800288974Z"}` - const linesPerFile = 100 + const linesPerFile = 5 defer base.Cmd("rm", "-f", containerName).Run() base.Cmd("run", "-d", "--log-driver", "json-file", @@ -227,10 +232,12 @@ func TestTailFollowRotateLogs(t *testing.T) { "sh", "-euc", "while true; do echo A; done").AssertOK() tailLogCmd := base.Cmd("logs", "-f", containerName) - tailLogCmd.Timeout = 100 * time.Millisecond - tailLogs := strings.Split(strings.TrimSpace(tailLogCmd.Run().Combined()), "\n") + tailLogCmd.Timeout = 2000 * time.Millisecond + tailLogs := strings.Split(strings.TrimSpace(tailLogCmd.Run().Stdout()), "\n") for _, line := range tailLogs { - assert.Equal(t, "A", line) + if line != "" { + assert.Equal(t, "A", line) + } } assert.Equal(t, true, len(tailLogs) > linesPerFile) } diff --git a/cmd/nerdctl/container_run_cgroup_linux_test.go b/cmd/nerdctl/container_run_cgroup_linux_test.go index 8174336b8a3..106060bf365 100644 --- a/cmd/nerdctl/container_run_cgroup_linux_test.go +++ b/cmd/nerdctl/container_run_cgroup_linux_test.go @@ -296,14 +296,12 @@ func TestRunCgroupParent(t *testing.T) { t.Parallel() base := testutil.NewBase(t) info := base.Info() - containerName := testutil.Identifier(t) - defer base.Cmd("rm", "-f", containerName).Run() - switch info.CgroupDriver { case "none", "": t.Skip("test requires cgroup driver") } + containerName := testutil.Identifier(t) t.Logf("Using %q cgroup driver", info.CgroupDriver) parent := "/foobarbaz" @@ -314,6 +312,13 @@ func TestRunCgroupParent(t *testing.T) { parent = "foobarbaz.slice" } + tearDown := func() { + base.Cmd("rm", "-f", containerName).Run() + } + + tearDown() + t.Cleanup(tearDown) + // cgroup2 without host cgroup ns will just output 0::/ which doesn't help much to verify // we got our expected path. This approach should work for both cgroup1 and 2, there will // just be many more entries for cgroup1 as there'll be an entry per controller. @@ -333,6 +338,9 @@ func TestRunCgroupParent(t *testing.T) { expected := filepath.Join(parent, id) if info.CgroupDriver == "systemd" { expected = filepath.Join(parent, fmt.Sprintf("nerdctl-%s", id)) + if base.Target == testutil.Docker { + expected = filepath.Join(parent, fmt.Sprintf("docker-%s", id)) + } } base.Cmd("exec", containerName, "cat", "/proc/self/cgroup").AssertOutContains(expected) } From af2f1402ff58fe794879f5e3c5288da4c3dcb00f Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 6 Jul 2024 14:35:55 -0700 Subject: [PATCH 0569/1066] Fix test: wait for systemd to come up Signed-off-by: apostasie --- cmd/nerdctl/container_run_systemd_linux_test.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/container_run_systemd_linux_test.go b/cmd/nerdctl/container_run_systemd_linux_test.go index 770c62a438f..e1757c3950b 100644 --- a/cmd/nerdctl/container_run_systemd_linux_test.go +++ b/cmd/nerdctl/container_run_systemd_linux_test.go @@ -46,7 +46,17 @@ func TestRunWithSystemdTrueEnabled(t *testing.T) { base.Cmd("inspect", "--format", "{{json .Config.Labels}}", containerName).AssertOutContains("SIGRTMIN+3") - base.Cmd("exec", containerName, "systemctl", "list-jobs").AssertOutContains("jobs listed.") + base.Cmd("exec", containerName, "sh", "-c", "--", `tries=0 +until systemctl is-system-running >/dev/null 2>&1; do + >&2 printf "Waiting for systemd to come up...\n" + sleep 1s + tries=$(( tries + 1)) + [ $tries -lt 10 ] || { + >&2 printf "systemd failed to come up in a reasonable amount of time\n" + exit 1 + } +done +systemctl list-jobs`).AssertOutContains("jobs") } func TestRunWithSystemdTrueDisabled(t *testing.T) { From c628ef1e299a6edd7728ad377060e667596a1f02 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 8 Jul 2024 10:41:03 -0700 Subject: [PATCH 0570/1066] Workaround delayed log file creation Signed-off-by: apostasie --- pkg/logging/json_logger.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index 6383eb3b768..68ac48740b7 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -28,6 +28,7 @@ import ( "strings" "time" + "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime/v2/logging" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/logging/jsonfile" @@ -129,7 +130,16 @@ func (jsonLogger *JSONLogger) PostProcess() error { func viewLogsJSONFile(lvopts LogViewOptions, stdout, stderr io.Writer, stopChannel chan os.Signal) error { logFilePath := jsonfile.Path(lvopts.DatastoreRootPath, lvopts.Namespace, lvopts.ContainerID) if _, err := os.Stat(logFilePath); err != nil { - return fmt.Errorf("failed to stat JSON log file ") + // FIXME: this is a workaround for the actual issue, not a real solution + // https://github.com/containerd/nerdctl/issues/3187 + if errors.Is(err, errdefs.ErrNotFound) { + log.L.Warnf("Racing log file creation. Pausing briefly.") + time.Sleep(200 * time.Millisecond) + _, err = os.Stat(logFilePath) + } + if err != nil { + return fmt.Errorf("failed to stat JSON log file %w", err) + } } if checkExecutableAvailableInPath("tail") { From 3a0df1651be568b847b95a44e0a1ddeb4029eb08 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 9 Jul 2024 16:04:41 +0900 Subject: [PATCH 0571/1066] CI: shrink test matrix Mitigates issue 3205 Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 32 +------------------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2043aa83cbe..d5930e8d695 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -58,14 +58,8 @@ jobs: include: - ubuntu: 20.04 containerd: v1.6.33 - - ubuntu: 20.04 - containerd: v1.7.19 - ubuntu: 22.04 containerd: v1.7.19 - - ubuntu: 22.04 - containerd: main # v2.0.0-rc.X - - ubuntu: 24.04 - containerd: v1.7.19 - ubuntu: 24.04 containerd: main # v2.0.0-rc.X env: @@ -152,42 +146,18 @@ jobs: include: - ubuntu: 20.04 containerd: v1.6.33 - rootlesskit: v1.1.1 - target: test-integration-rootless - - ubuntu: 20.04 - containerd: v1.7.19 - rootlesskit: v2.1.0 + rootlesskit: v1.1.1 # Deprecated target: test-integration-rootless - ubuntu: 22.04 containerd: v1.7.19 - rootlesskit: v1.1.1 - target: test-integration-rootless - - ubuntu: 22.04 - containerd: main # v2.0.0-rc.X rootlesskit: v2.1.0 target: test-integration-rootless - - ubuntu: 24.04 - containerd: v1.7.19 - rootlesskit: v1.1.1 - target: test-integration-rootless - ubuntu: 24.04 containerd: main # v2.0.0-rc.X rootlesskit: v2.1.0 target: test-integration-rootless - - ubuntu: 20.04 - containerd: v1.6.33 - rootlesskit: v1.1.1 - target: test-integration-rootless-port-slirp4netns - - ubuntu: 20.04 - containerd: v1.7.19 - rootlesskit: v2.1.0 - target: test-integration-rootless-port-slirp4netns - ubuntu: 24.04 containerd: v1.7.19 - rootlesskit: v1.1.1 - target: test-integration-rootless-port-slirp4netns - - ubuntu: 24.04 - containerd: main # v2.0.0-rc.X rootlesskit: v2.1.0 target: test-integration-rootless-port-slirp4netns env: From 496c78e8922d2f424da9f3f0d15c5f2edb27d317 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 9 Jul 2024 11:20:13 -0700 Subject: [PATCH 0572/1066] Test fixes Signed-off-by: apostasie --- cmd/nerdctl/builder_build_test.go | 5 ----- cmd/nerdctl/container_logs_test.go | 6 +++--- pkg/testutil/testutil_linux.go | 3 ++- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index 59b25d7fc42..472d93b2495 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -152,7 +152,6 @@ CMD ["cat", "/hello2"] } func TestBuildFromStdin(t *testing.T) { - t.Parallel() testutil.RequiresBuild(t) base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() @@ -199,7 +198,6 @@ CMD ["echo", "nerdctl-build-test-dockerfile"] } func TestBuildLocal(t *testing.T) { - t.Parallel() testutil.RequiresBuild(t) base := testutil.NewBase(t) if testutil.GetTarget() == testutil.Docker { @@ -293,7 +291,6 @@ CMD echo $TEST_STRING } func TestBuildWithIIDFile(t *testing.T) { - t.Parallel() testutil.RequiresBuild(t) base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() @@ -318,7 +315,6 @@ CMD ["echo", "nerdctl-build-test-string"] } func TestBuildWithLabels(t *testing.T) { - t.Parallel() testutil.RequiresBuild(t) base := testutil.NewBase(t) defer base.Cmd("builder", "prune").Run() @@ -547,7 +543,6 @@ func buildWithNamedBuilder(base *testutil.Base, builderName string, args ...stri } func TestBuildAttestation(t *testing.T) { - t.Parallel() testutil.RequiresBuild(t) base := testutil.NewBase(t) builderName := testutil.Identifier(t) diff --git a/cmd/nerdctl/container_logs_test.go b/cmd/nerdctl/container_logs_test.go index 944b48486d2..ac036e74c52 100644 --- a/cmd/nerdctl/container_logs_test.go +++ b/cmd/nerdctl/container_logs_test.go @@ -209,7 +209,7 @@ func TestLogsWithForegroundContainers(t *testing.T) { } func TestTailFollowRotateLogs(t *testing.T) { - // FIXME this is flaky by nature... 5 lines is arbitrary, 2000 ms is arbitrary, and both are some sort of educated + // FIXME this is flaky by nature... 2 lines is arbitrary, 10000 ms is arbitrary, and both are some sort of educated // guess that things will mostly always kinda work maybe... // Furthermore, parallelizing will put pressure on the daemon which might be even slower in answering, increasing // the risk of transient failure. @@ -222,7 +222,7 @@ func TestTailFollowRotateLogs(t *testing.T) { containerName := testutil.Identifier(t) const sampleJSONLog = `{"log":"A\n","stream":"stdout","time":"2024-04-11T12:01:09.800288974Z"}` - const linesPerFile = 5 + const linesPerFile = 2 defer base.Cmd("rm", "-f", containerName).Run() base.Cmd("run", "-d", "--log-driver", "json-file", @@ -232,7 +232,7 @@ func TestTailFollowRotateLogs(t *testing.T) { "sh", "-euc", "while true; do echo A; done").AssertOK() tailLogCmd := base.Cmd("logs", "-f", containerName) - tailLogCmd.Timeout = 2000 * time.Millisecond + tailLogCmd.Timeout = 10000 * time.Millisecond tailLogs := strings.Split(strings.TrimSpace(tailLogCmd.Run().Stdout()), "\n") for _, line := range tailLogs { if line != "" { diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index b6573b122a5..b3628f128e0 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -124,7 +124,8 @@ func NewDelayOnceReader(wrapped io.Reader) io.Reader { } func (r *delayOnceReader) Read(p []byte) (int, error) { - r.once.Do(func() { time.Sleep(time.Second) }) + // FIXME: this is obviously not exact science. At 1 second, it will fail regularly on the CI under load. + r.once.Do(func() { time.Sleep(2 * time.Second) }) n, err := r.wrapped.Read(p) if errors.Is(err, io.EOF) { time.Sleep(time.Second) From 41870985aa3393e037c572b0299c08d994fdbdee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 22:59:45 +0000 Subject: [PATCH 0573/1066] build(deps): bump github.com/containerd/typeurl/v2 from 2.1.1 to 2.2.0 Bumps [github.com/containerd/typeurl/v2](https://github.com/containerd/typeurl) from 2.1.1 to 2.2.0. - [Release notes](https://github.com/containerd/typeurl/releases) - [Commits](https://github.com/containerd/typeurl/compare/v2.1.1...v2.2.0) --- updated-dependencies: - dependency-name: github.com/containerd/typeurl/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1f05721c975..044a22df287 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 github.com/containerd/stargz-snapshotter/ipfs v0.15.1 - github.com/containerd/typeurl/v2 v2.1.1 + github.com/containerd/typeurl/v2 v2.2.0 github.com/containernetworking/cni v1.2.2 github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.7.0 diff --git a/go.sum b/go.sum index 20dbd0f22d9..ff1edc01753 100644 --- a/go.sum +++ b/go.sum @@ -64,8 +64,8 @@ github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oL 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= -github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= +github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= +github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/containernetworking/cni v1.2.2 h1:9IbP6KJQQxVKo4hhnm8r50YcVKrJbJu3Dqw+Rbt1vYk= github.com/containernetworking/cni v1.2.2/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= From fdd88383fed9071789ccccfc5b20b19dc2af05d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jul 2024 22:29:07 +0000 Subject: [PATCH 0574/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.2.5 to 0.3.0. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.2.5...v0.3.0) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 044a22df287..eafda312a60 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.2.5 + github.com/cyphar/filepath-securejoin v0.3.0 github.com/docker/cli v27.0.3+incompatible github.com/docker/docker v27.0.3+incompatible github.com/docker/go-connections v0.5.0 diff --git a/go.sum b/go.sum index ff1edc01753..3957163b05d 100644 --- a/go.sum +++ b/go.sum @@ -79,8 +79,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo= -github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.3.0 h1:tXpmbiaeBrS/K2US8nhgwdKYnfAOnVfkcLPKFgFHeA0= +github.com/cyphar/filepath-securejoin v0.3.0/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= 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= From b028812177df59111f60b3db1e1e5e38e500c548 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 11 Jul 2024 22:51:17 -0700 Subject: [PATCH 0575/1066] Update FUSE and buildkit in dockerfile Signed-off-by: apostasie --- Dockerfile | 4 ++-- Dockerfile.d/SHA256SUMS.d/buildkit-v0.14.1 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.0 | 2 ++ Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.13 | 6 ------ Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.14 | 2 ++ 5 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.14.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.0 delete mode 100644 Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.13 create mode 100644 Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.14 diff --git a/Dockerfile b/Dockerfile index fa41e63de70..6fada9be74c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.13 ARG CNI_PLUGINS_VERSION=v1.5.1 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.14.1 +ARG BUILDKIT_VERSION=v0.15.0 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption @@ -34,7 +34,7 @@ ARG SLIRP4NETNS_VERSION=v1.3.1 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.4.1 # Extra deps: FUSE-OverlayFS -ARG FUSE_OVERLAYFS_VERSION=v1.13 +ARG FUSE_OVERLAYFS_VERSION=v1.14 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 # Extra deps: IPFS ARG KUBO_VERSION=v0.29.0 diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.14.1 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.14.1 deleted file mode 100644 index e059cbf6e7a..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.14.1 +++ /dev/null @@ -1,2 +0,0 @@ -836208f50ab8856a91aa5bba455b8451bbe261318cbc92e9c0ca3e786135756c buildkit-v0.14.1.linux-amd64.tar.gz -e1caad39f0bc5848a5687d7a0e8e344d20724133365596e5d881d8fbe5594b32 buildkit-v0.14.1.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.0 new file mode 100644 index 00000000000..bda954324e8 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.0 @@ -0,0 +1,2 @@ +803de21f1656b2f0398e09204abcff2943c17b6b5951fe5ccfc8300012fcb838 buildkit-v0.15.0.linux-amd64.tar.gz +dfa15ef3f194afc0f588de1e78053cdcd553e7de2f9692efe964c9aa7e9d621e buildkit-v0.15.0.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.13 b/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.13 deleted file mode 100644 index 1a6d275766c..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.13 +++ /dev/null @@ -1,6 +0,0 @@ -ab8685073e6daef4d8935e878cd55a8350dd0299eea1d3249684a548ad6394bf fuse-overlayfs-aarch64 -ffaaa64b858e6fe10a1f00d02c0e598556ad0fc85165f740cd5bb08eeb991142 fuse-overlayfs-armv7l -fa078140cb1caf85849559af56f654d351973f63a47b1613422d02d28b8c4f8b fuse-overlayfs-ppc64le -06c9dc13d2c0afdb0ee3007d0ebb5cec64feaaa4a79497d08b1f2cfcb6316a43 fuse-overlayfs-riscv64 -322d48a0e98b34715e4857b826b91ae510d7e56fa1fbd7b4d0a6bbae5a01435c fuse-overlayfs-s390x -0011ad825dc0274b6e330fb9a8d3d578ea7bbf738bab08934b90be070b8d0a4a fuse-overlayfs-x86_64 diff --git a/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.14 b/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.14 new file mode 100644 index 00000000000..4ef7dca0da1 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/fuse-overlayfs-v1.14 @@ -0,0 +1,2 @@ +bf2c19b80e68afe1f53bae7a08cc9e7fb2f1b49bfdb9e5b49ab87cbe80b97cd1 fuse-overlayfs-aarch64 +4817a8896a9e6f0433080f88f5b71dec931e8829a89d64c71af94b0630ccb4a9 fuse-overlayfs-x86_64 From f759e03576bb026ec630fce4d3bda3945152dc39 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 11 Jul 2024 22:59:16 -0700 Subject: [PATCH 0576/1066] Silence apt-get and uniformize calls format Signed-off-by: apostasie --- Dockerfile | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6fada9be74c..ed6e55273d9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,13 +57,19 @@ FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.4.0 AS xx FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bullseye AS build-base-debian COPY --from=xx / / ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && \ - apt-get install -y git pkg-config dpkg-dev +RUN apt-get update -qq && apt-get install -qq --no-install-recommends \ + git \ + pkg-config \ + dpkg-dev ARG TARGETARCH # libbtrfs: for containerd # libseccomp: for runc and bypass4netns -RUN xx-apt-get update && \ - xx-apt-get install -y binutils gcc libc6-dev libbtrfs-dev libseccomp-dev +RUN xx-apt-get update -qq && xx-apt-get install -qq --no-install-recommends \ + binutils \ + gcc \ + libc6-dev \ + libbtrfs-dev \ + libseccomp-dev FROM build-base-debian AS build-containerd ARG TARGETARCH @@ -241,14 +247,13 @@ COPY --from=build-full /out / FROM ubuntu:${UBUNTU_VERSION} AS base # fuse3 is required by stargz snapshotter -RUN apt-get update && \ - apt-get install -qq -y --no-install-recommends \ - apparmor \ - bash-completion \ - ca-certificates curl \ - iproute2 iptables \ - dbus dbus-user-session systemd systemd-sysv \ - fuse3 +RUN apt-get update -qq && apt-get install -qq -y --no-install-recommends \ + apparmor \ + bash-completion \ + ca-certificates curl \ + iproute2 iptables \ + dbus dbus-user-session systemd systemd-sysv \ + fuse3 ARG CONTAINERIZED_SYSTEMD_VERSION RUN curl -L -o /docker-entrypoint.sh https://raw.githubusercontent.com/AkihiroSuda/containerized-systemd/${CONTAINERIZED_SYSTEMD_VERSION}/docker-entrypoint.sh && \ chmod +x /docker-entrypoint.sh @@ -274,9 +279,9 @@ RUN go env GOVERSION > /GOVERSION FROM base AS test-integration ARG DEBIAN_FRONTEND=noninteractive # `expect` package contains `unbuffer(1)`, which is used for emulating TTY for testing -RUN apt-get update && \ - apt-get install -qq -y \ - expect git +RUN apt-get update -qq && apt-get install -qq --no-install-recommends \ + expect \ + git COPY --from=goversion /GOVERSION /GOVERSION ARG TARGETARCH RUN curl -L https://golang.org/dl/$(cat /GOVERSION).linux-${TARGETARCH:-amd64}.tar.gz | tar xzvC /usr/local @@ -320,10 +325,10 @@ FROM test-integration AS test-integration-rootless # Install SSH for creating systemd user session. # (`sudo` does not work for this purpose, # OTOH `machinectl shell` can create the session but does not propagate exit code) -RUN apt-get update && \ - apt-get install -qq -y \ - uidmap \ - openssh-server openssh-client +RUN apt-get update -qq && apt-get install -qq --no-install-recommends \ + uidmap \ + openssh-server \ + openssh-client # 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 && \ From db47b3196acf12f80767bb73fd67c0a12b66a4fa Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 11 Jul 2024 22:10:02 -0700 Subject: [PATCH 0577/1066] Adding a canary CI target to test against upcoming / unreleased versions Signed-off-by: apostasie --- .github/workflows/test-canary.yml | 103 ++++ .github/workflows/test.yml | 4 +- hack/build-integration-canary.sh | 438 ++++++++++++++++++ .../testregistry/testregistry_linux.go | 21 +- pkg/testutil/testutil_linux.go | 3 +- 5 files changed, 564 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/test-canary.yml create mode 100755 hack/build-integration-canary.sh diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml new file mode 100644 index 00000000000..2e954c3caf0 --- /dev/null +++ b/.github/workflows/test-canary.yml @@ -0,0 +1,103 @@ +# This pipeline purpose is solely meant to run a subset of our test suites against upcoming or unreleased dependencies versions +name: canary + +on: + push: + branches: + - main + - 'release/**' + pull_request: + paths-ignore: + - '**.md' + +env: + UBUNTU_VERSION: "24.04" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + linux: + runs-on: "ubuntu-24.04" + timeout-minutes: 40 + steps: + - uses: actions/checkout@v4.1.7 + with: + fetch-depth: 1 + - name: "Prepare integration test environment" + run: | + ./hack/build-integration-canary.sh + - name: "Remove snap loopback devices (conflicts with our loopback devices in TestRunDevice)" + run: | + sudo systemctl disable --now snapd.service snapd.socket + sudo apt-get purge -y snapd + sudo losetup -Dv + sudo losetup -lv + - name: "Register QEMU (tonistiigi/binfmt)" + run: docker run --privileged --rm tonistiigi/binfmt --install all + - name: "Run unit tests" + run: go test -v ./pkg/... + - name: "Run integration tests" + continue-on-error: true + run: docker run -t --rm --privileged test-integration + + windows: + runs-on: windows-latest + timeout-minutes: 30 + defaults: + run: + shell: bash + steps: + - name: Set GO env + run: | + # Get latest containerd + args=(curl --proto '=https' --tlsv1.2 -fsSL -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28") + [ "${GITHUB_TOKEN:-}" == "" ] && { + >&2 printf "GITHUB_TOKEN is not set - you might face rate limitations with the Github API\n" + } || args+=(-H "Authorization: Bearer $GITHUB_TOKEN") + ctd_v="$("${args[@]}" https://api.github.com/repos/containerd/containerd/tags | jq -rc .[0].name)" + echo "CONTAINERD_VERSION=${ctd_v:1}" >> $GITHUB_ENV + + # Get latest golang version and split it in components + norm=() + while read -r line; do + norm+=("$line") + done < \ + <(sed -E 's/^go([0-9]+)[.]([0-9]+)([.]([0-9]+))?(([a-z]+)([0-9]+))?/\1.\2\n\4\n\6\n\7/i' \ + <(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version) \ + ) + + # Serialize version, making sure we have a patch version, and separate possible rcX into .rc-X + [ "${norm[1]}" != "" ] || norm[1]="0" + norm[1]=".${norm[1]}" + [ "${norm[2]}" == "" ] || norm[2]="-${norm[2]}" + [ "${norm[3]}" == "" ] || norm[3]=".${norm[3]}" + # Save it + IFS= + echo "GO_VERSION=${norm[*]}" >> $GITHUB_ENV + - uses: actions/checkout@v4.1.7 + with: + fetch-depth: 1 + - uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + cache: true + check-latest: true + - run: go install ./cmd/nerdctl + # This here is solely to get the cni install script, which has not been modified in 3+ years. + # There is little to no reason to update this to latest containerd + - uses: actions/checkout@v4.1.7 + with: + repository: containerd/containerd + ref: "v1.7.19" + path: containerd + fetch-depth: 1 + - name: "Set up CNI" + working-directory: containerd + run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows + # Windows setup script can only use released versions + - name: "Set up containerd" + env: + ctrdVersion: ${{ env.CONTAINERD_VERSION }} + run: powershell hack/configure-windows-ci.ps1 + - name: "Run integration tests" + continue-on-error: true + run: go test -v ./cmd/... diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d5930e8d695..ecbb075425c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -61,7 +61,7 @@ jobs: - ubuntu: 22.04 containerd: v1.7.19 - ubuntu: 24.04 - containerd: main # v2.0.0-rc.X + containerd: v2.0.0-rc.3 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -153,7 +153,7 @@ jobs: rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 24.04 - containerd: main # v2.0.0-rc.X + containerd: v2.0.0-rc.3 rootlesskit: v2.1.0 target: test-integration-rootless - ubuntu: 24.04 diff --git a/hack/build-integration-canary.sh b/hack/build-integration-canary.sh new file mode 100755 index 00000000000..daddfe60ce1 --- /dev/null +++ b/hack/build-integration-canary.sh @@ -0,0 +1,438 @@ +#!/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 + +###################### +# Definitions +###################### + +# "Blacklisting" here means that any dependency which name is blacklisted will be left untouched, at the version +# currently pinned in the Dockerfile. +# This is convenient so that currently broken alpha/beta/RC can be held back temporarily to keep the build green + +# Currently pinned, see: +# - https://github.com/containerd/nerdctl/pull/3153 +blacklist=(runc) + +# List all the repositories we depend on to build and run integration tests +dependencies=( + ktock/buildg + moby/buildkit + containerd/containerd + distribution/distribution + containers/fuse-overlayfs + containerd/fuse-overlayfs-snapshotter + gotestyourself/gotestsum + ipfs/kubo + containerd/nydus-snapshotter + containernetworking/plugins + rootless-containers/rootlesskit + opencontainers/runc + rootless-containers/slirp4netns + awslabs/soci-snapshotter + containerd/stargz-snapshotter + krallin/tini +) + +# Certain dependencies do issue multiple unrelated releaes on their repo - use these below to ignore certain releases +BUILDKIT_EXCLUDE="dockerfile/" +CONTAINERD_EXCLUDE="containerd API" + +# Some dependencies will be checksum-matched. Setting the variables below will trigger us to download and generate shasums +# The value you set the variable to also decides which artifacts you are interested in. +BUILDKIT_CHECKSUM=linux +CNI_PLUGINS_CHECKSUM=linux +CONTAINERD_FUSE_OVERLAYFS_CHECKSUM=linux +FUSE_OVERLAYFS_CHECKSUM=linux +# Avoids the full build +BUILDG_CHECKSUM=buildg-v +ROOTLESSKIT_CHECKSUM=linux +SLIRP4NETNS_CHECKSUM=linux +STARGZ_SNAPSHOTTER_CHECKSUM=linux +# We specifically want the static ones +TINI_CHECKSUM=static + + +###################### +# Lib +###################### + +# Simple logger +readonly LOG_LEVEL_DEBUG=0 +readonly LOG_LEVEL_INFO=1 +readonly LOG_LEVEL_WARNING=2 +readonly LOG_LEVEL_ERROR=3 + +readonly LOG_COLOR_BLACK=0 +readonly LOG_COLOR_RED=1 +readonly LOG_COLOR_GREEN=2 +readonly LOG_COLOR_YELLOW=3 +readonly LOG_COLOR_BLUE=4 +readonly LOG_COLOR_MAGENTA=5 +readonly LOG_COLOR_CYAN=6 +readonly LOG_COLOR_WHITE=7 +readonly LOG_COLOR_DEFAULT=9 + +readonly LOG_STYLE_DEBUG=( setaf "$LOG_COLOR_WHITE" ) +readonly LOG_STYLE_INFO=( setaf "$LOG_COLOR_GREEN" ) +readonly LOG_STYLE_WARNING=( setaf "$LOG_COLOR_YELLOW" ) +readonly LOG_STYLE_ERROR=( setaf "$LOG_COLOR_RED" ) + +_log::log(){ + local level + local style + local numeric_level + local message="$2" + + level="$(printf "%s" "$1" | tr '[:lower:]' '[:upper:]')" + numeric_level="$(printf "LOG_LEVEL_%s" "$level")" + style="LOG_STYLE_${level}[@]" + + [ "${!numeric_level}" -ge "$LOG_LEVEL" ] || return 0 + + [ ! "$TERM" ] || [ ! -t 2 ] || >&2 tput "${!style}" 2>/dev/null || true + >&2 printf "[%s] %s: %s\n" "$(date 2>/dev/null || true)" "$(printf "%s" "$level" | tr '[:lower:]' '[:upper:]')" "$message" + [ ! "$TERM" ] || [ ! -t 2 ] || >&2 tput op 2>/dev/null || true +} + +log::init(){ + # Default log to warning if unspecified + _ll="$(printf "LOG_LEVEL_%s" "${NERDCTL_CI_LOG_LEVEL:-warning}" | tr '[:lower:]' '[:upper:]')" + # Default to 3 (warning) if unrecognized + LOG_LEVEL="${!_ll:-3}" +} + +log::debug(){ + _log::log debug "$@" +} + +log::info(){ + _log::log info "$@" +} + +log::warning(){ + _log::log warning "$@" +} + +log::error(){ + _log::log error "$@" +} + +# Helpers +host::require(){ + local binary="$1" + command -v "$binary" >/dev/null || { + log::error "You need $binary for this script to work, and it cannot be found in your path" + exit 1 + } +} + +fs::mktemp(){ + mktemp -dq "${TMPDIR:-/tmp}/$prefix.XXXXXX" 2>/dev/null || mktemp -dq || { + log::error "Failed to create temporary directory" + exit 1 + } +} + +http::get(){ + local args=(curl --proto '=https' --tlsv1.2 -fsSL) + args+=("$@") + + log::debug "${args[*]}" + "${args[@]}" +} + +http::checksum(){ + local urls=("$@") + local url + + local prefix="nerdctl-checksum" + + local temp + temp="$(fs::mktemp)" + + for url in "${urls[@]}"; do + http::get -o "$temp/${url##*/}" "$url" + done + + cd "$temp" + shasum -a 256 ./* + cd - >/dev/null || true +} + +# Github API helpers +# Set GITHUB_TOKEN to use authenticated requests to workaround limitations +github::request(){ + local endpoint="$1" + local args=( + -H "Accept: application/vnd.github+json" + -H "X-GitHub-Api-Version: 2022-11-28" + ) + + [ "${GITHUB_TOKEN:-}" == "" ] || args+=(-H "Authorization: Bearer $GITHUB_TOKEN") + + http::get "${args[@]}" https://api.github.com/"$endpoint" +} + +github::tags::getlatest(){ + local repo="$1" + github::request "repos/$repo/tags" | + jq -rc .[0].name +} + +github::releases::latest(){ + local repo="$1" + github::request "repos/$repo/releases" | + jq -rc .[] +} + +version::compare(){ + local raw_version_fd="$1" + local parsed + local line + while read -r line; do + parsed+=("$line") + done < <(sed -E 's/^(.* )?v?([0-9]+)[.]([0-9]+)([.]([0-9]+))?(-?([a-z]+)[.]?([0-9]+))?.*/\2\n\3\n\5\n\7\n\8\n/i' < "$raw_version_fd") + + local maj="${higher[0]}" + local min="${higher[1]}" + local patch="${higher[2]}" + local sub="${higher[3]}" + local subv="${higher[4]}" + + log::debug "parsed version: ${parsed[*]}" + log::debug " > current higher version: ${higher[*]}" + + if [ "${parsed[0]}" -gt "$maj" ]; then + log::debug " > new higher" + higher=("${parsed[@]}") + return + elif [ "${parsed[0]}" -lt "$maj" ]; then + return 1 + fi + if [ "${parsed[1]}" -gt "$min" ]; then + log::debug " > new higher" + higher=("${parsed[@]}") + return + elif [ "${parsed[1]}" -lt "$min" ]; then + return 1 + fi + if [ "${parsed[2]}" -gt "$patch" ]; then + log::debug " > new higher" + higher=("${parsed[@]}") + return + elif [ "${parsed[2]}" -lt "$patch" ]; then + return 1 + fi + # If the current latest does not have a sub, then it is more recent + if [ "$sub" == "" ]; then + return 1 + fi + # If it has a sub, and the parsed one does not, then the parsed one is more recent + if [ "${parsed[3]}" == "" ]; then + log::debug " > new higher" + higher=("${parsed[@]}") + return + fi + # Otherwise, we have two subs. Normalize, then compare + # alpha < beta < rc + [ "$sub" == "rc" ] && sub=2 || { [ "$sub" == "beta" ] && sub=1; } || { [ "$sub" == "alpha" ] && sub=0; } || { + log::error "Unrecognized sub pattern: $sub" + exit 42 + } + [ "${parsed[3]}" == "rc" ] && parsed[3]=2 || { [ "${parsed[3]}" == "beta" ] && parsed[3]=1; } || { [ "${parsed[3]}" == "alpha" ] && parsed[3]=0; } || { + log::error "Unrecognized sub pattern: ${parsed[3]}" + exit 42 + } + if [ "${parsed[3]}" -gt "$sub" ]; then + log::debug " > new higher" + higher=("${parsed[@]}") + return + elif [ "${parsed[3]}" -lt "$sub" ]; then + return 1 + fi + # Ok... we are left with just the sub version + if [ "${parsed[4]}" -gt "$subv" ]; then + log::debug " > new higher" + higher=("${parsed[@]}") + return + elif [ "${parsed[4]}" -lt "$subv" ]; then + return 1 + fi +} + +# Retrieves the "highest version" release for a given repo +# Optional argument 2 allows to filter out unwanted release which name matches the argument +# This is useful for repo that do independent releases for assets (like buildkit dockerfiles) +latest::release(){ + local repo="$1" + local ignore="${2:-}" + local line + local name + + higher=(0 0 0 "alpha" 0) + higher_data= + higher_readable= + + log::info "Analyzing releases for $repo" + + while read -r line; do + [ ! "$ignore" ] || ! grep -q "$ignore" <<<"$line" || continue + name="$(echo "$line" | jq -rc .name)" + if [ "$name" == "" ] || [ "$name" == null ] ; then + log::debug " > bogus release name ($name) ignored" + continue + fi + log::debug " > found release: $name" + if version::compare <(echo "$line" | jq -rc .name); then + higher_data="$line" + higher_readable="$(echo "$line" | jq -rc .name | sed -E 's/(.*[ ])?(v?[0-9][0-9.a-z-]+).*/\2/')" + fi + done < <(github::releases::latest "$repo") + + log::info " >>> latest release detected: $higher_readable" +} + +# Retrieve the latest git tag for a given repo +latest::tag(){ + local repo="$1" + + log::info "Analyzing tags for $repo" + github::tags::getlatest "$repo" +} + +# Once a latest release has been retrieved for a given project, you can get the url to the asset matching OS and ARCH +assets::get(){ + local os="$1" + local arch="$2" + local name= + local found= + + while read -r line; do + name="$(echo "$line" | jq -rc .name)" + log::debug " >>> candidate $name" + ! grep -qi "$os" <<<"$name" || ! grep -qi "$arch" <<<"$name" || ( + ! grep -Eqi "[.]t?g?x?z$" <<<"$name" && grep -Eqi "[.][a-z]+$" <<<"$name" + ) || { + found="$line" + break + } + done < <(echo "$higher_data" | jq -rc .assets.[]) + [ "$found" == "" ] && { + log::warning " >>> no asset found for $os/$arch" + } || { + log::info " >>> found asset for $os/$arch: $(echo "$found" | jq -rc .browser_download_url)" + printf "%s\n" "$(echo "$found" | jq -rc .browser_download_url)" + } +} + +log::init +host::require jq +host::require curl +host::require shasum +host::require docker +host::require tput + +###################### +# Script +###################### + +docker_args=(docker build -t test-integration --target test-integration) + +for dep in "${dependencies[@]}"; do + shortname="${dep##*/}" + [ "$shortname" != "plugins" ] || shortname="cni-plugins" + [ "$shortname" != "fuse-overlayfs-snapshotter" ] || shortname="containerd-fuse-overlayfs" + for bl in "${blacklist[@]}"; do + if [ "$bl" == "$shortname" ]; then + log::warning "Dependency $shortname is blacklisted and will be left to its currently pinned version" + break + fi + done + [ "$bl" != "$shortname" ] || continue + + shortsafename="$(printf "%s" "$shortname" | tr '[:lower:]' '[:upper:]' | tr '-' '_')" + + exclusion="${shortsafename}_EXCLUDE" + latest::release "$dep" "${!exclusion:-}" + + # XXX containerd does not display "v" in its released versions + [ "${higher_readable:0:1}" == v ] || higher_readable="v$higher_readable" + + checksum="${shortsafename}_CHECKSUM" + if [ "${!checksum:-}" != "" ]; then + # Checksum file + checksum_file=./Dockerfile.d/SHA256SUMS.d/"${shortname}-${higher_readable}" + if [ ! -e "$checksum_file" ]; then + # Get assets - try first os/arch - fallback on gnu style arch otherwise + assets=() + + # Most well behaved go projects will tag with a go os and arch + candidate="$(assets::get "${!checksum:-}" "amd64")" + # Then non go projects tend to use gnu style + [ "$candidate" != "" ] || candidate="$(assets::get "" "x86_64")" + # And then some projects which are linux only do not specify the OS + [ "$candidate" != "" ] || candidate="$(assets::get "" "amd64")" + [ "$candidate" == "" ] || assets+=("$candidate") + + candidate="$(assets::get "${!checksum:-}" "arm64")" + [ "$candidate" != "" ] || candidate="$(assets::get "" "aarch64")" + [ "$candidate" != "" ] || candidate="$(assets::get "" "arm64")" + [ "$candidate" == "" ] || assets+=("$candidate") + # Fallback to source if there is nothing else + + [ "${#assets[@]}" != 0 ] || candidate="$(assets::get "" "source")" + [ "$candidate" == "" ] || assets+=("$candidate") + + # XXX very special... + if [ "$shortsafename" == "STARGZ_SNAPSHOTTER" ]; then + assets+=("https://raw.githubusercontent.com/containerd/stargz-snapshotter/${higher_readable}/script/config/etc/systemd/system/stargz-snapshotter.service") + fi + + # Write the checksum for what we found + if [ "${#assets[@]}" == 0 ]; then + log::error "No asset found for this checksum-able dependency. Dropping off." + exit 1 + fi + http::checksum "${assets[@]}" > "$checksum_file" + fi + fi + + while read -r line; do + # Extract value after "=" from a possible dockerfile `ARG XXX_VERSION` + old_version=$(echo "$line" | grep "ARG ${shortsafename}_VERSION=") || true + old_version="${old_version##*=}" + [ "$old_version" != "" ] || continue + # If the Dockerfile version does NOT start with a v, adapt to that + [ "${old_version:0:1}" == "v" ] || higher_readable="${higher_readable:1}" + + if [ "$old_version" != "$higher_readable" ]; then + log::warning "Dependency ${shortsafename} is going to use an updated version $higher_readable (currently: $old_version)" + fi + done < ./Dockerfile + + docker_args+=(--build-arg "${shortsafename}_VERSION=$higher_readable") +done + + +GO_VERSION="$(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version)" +GO_VERSION="${GO_VERSION##*go}" +docker_args+=(--build-arg "GO_VERSION=$GO_VERSION") + +log::debug "${docker_args[*]} ." +"${docker_args[@]}" "." diff --git a/pkg/testutil/testregistry/testregistry_linux.go b/pkg/testutil/testregistry/testregistry_linux.go index a5b60aaf834..24c29058908 100644 --- a/pkg/testutil/testregistry/testregistry_linux.go +++ b/pkg/testutil/testregistry/testregistry_linux.go @@ -53,7 +53,15 @@ type TokenAuthServer struct { } func EnsureImages(base *testutil.Base) { - base.Cmd("pull", testutil.RegistryImage).AssertOK() + registryImage := testutil.RegistryImageStable + up := os.Getenv("DISTRIBUTION_VERSION") + if up != "" { + if up[0:1] != "v" { + up = "v" + up + } + registryImage = testutil.RegistryImageNext + up + } + base.Cmd("pull", registryImage).AssertOK() base.Cmd("pull", testutil.DockerAuthImage).AssertOK() base.Cmd("pull", testutil.KuboImage).AssertOK() } @@ -340,7 +348,16 @@ func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundC } args = append(args, auth.Params(base)...) - args = append(args, testutil.RegistryImage) + registryImage := testutil.RegistryImageStable + + up := os.Getenv("DISTRIBUTION_VERSION") + if up != "" { + if up[0:1] != "v" { + up = "v" + up + } + registryImage = testutil.RegistryImageNext + up + } + args = append(args, registryImage) cleanup := func(err error) { result := base.Cmd("rm", "-f", containerName).Run() diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index b3628f128e0..7aa47117294 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -34,7 +34,8 @@ var ( AlpineImage = mirrorOf("alpine:3.13") NginxAlpineImage = mirrorOf("nginx:1.19-alpine") NginxAlpineIndexHTMLSnippet = "Welcome to nginx!" - RegistryImage = mirrorOf("registry:2") + RegistryImageStable = mirrorOf("registry:2") + RegistryImageNext = "ghcr.io/distribution/distribution:" WordpressImage = mirrorOf("wordpress:5.7") WordpressIndexHTMLSnippet = "WordPress › Installation" MariaDBImage = mirrorOf("mariadb:10.5") From 164b9f65118d1c184a9c742e6e59138148bc25bb Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 12 Jul 2024 13:37:58 -0700 Subject: [PATCH 0578/1066] Normalize curl invocations Signed-off-by: apostasie --- Dockerfile | 28 +++++++++---------- .../ipfs-cluster/README.md | 2 +- .../ipfs-cluster/nerdctl-ipfs-registry.yaml | 2 +- .../ipfs-stargz-snapshotter/README.md | 2 +- .../nerdctl-ipfs-registry.yaml | 2 +- .../ipfs/README.md | 2 +- .../ipfs/nerdctl-ipfs-registry.yaml | 2 +- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index ed6e55273d9..9746b272409 100644 --- a/Dockerfile +++ b/Dockerfile @@ -146,7 +146,7 @@ COPY --from=build-runc /out/runc.${TARGETARCH:-amd64} /out/bin/runc RUN echo "- runc: ${RUNC_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG CNI_PLUGINS_VERSION RUN fname="cni-plugins-${TARGETOS:-linux}-${TARGETARCH:-amd64}-${CNI_PLUGINS_VERSION}.tgz" && \ - curl -o "${fname}" -fSL "https://github.com/containernetworking/plugins/releases/download/${CNI_PLUGINS_VERSION}/${fname}" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/containernetworking/plugins/releases/download/${CNI_PLUGINS_VERSION}/${fname}" && \ grep "${fname}" "/SHA256SUMS.d/cni-plugins-${CNI_PLUGINS_VERSION}" | sha256sum -c && \ mkdir -p /out/libexec/cni && \ tar xzf "${fname}" -C /out/libexec/cni && \ @@ -154,7 +154,7 @@ RUN fname="cni-plugins-${TARGETOS:-linux}-${TARGETARCH:-amd64}-${CNI_PLUGINS_VER echo "- CNI plugins: ${CNI_PLUGINS_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG BUILDKIT_VERSION RUN fname="buildkit-${BUILDKIT_VERSION}.${TARGETOS:-linux}-${TARGETARCH:-amd64}.tar.gz" && \ - curl -o "${fname}" -fSL "https://github.com/moby/buildkit/releases/download/${BUILDKIT_VERSION}/${fname}" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/moby/buildkit/releases/download/${BUILDKIT_VERSION}/${fname}" && \ grep "${fname}" "/SHA256SUMS.d/buildkit-${BUILDKIT_VERSION}" | sha256sum -c && \ tar xzf "${fname}" -C /out && \ rm -f "${fname}" /out/bin/buildkit-qemu-* /out/bin/buildkit-cni-* /out/bin/buildkit-runc && \ @@ -168,8 +168,8 @@ RUN cd /out/lib/systemd/system && \ echo "# This file was converted from containerd.service, with \`sed -E '${sedcomm}'\`" >> buildkit.service ARG STARGZ_SNAPSHOTTER_VERSION RUN fname="stargz-snapshotter-${STARGZ_SNAPSHOTTER_VERSION}-${TARGETOS:-linux}-${TARGETARCH:-amd64}.tar.gz" && \ - curl -o "${fname}" -fSL "https://github.com/containerd/stargz-snapshotter/releases/download/${STARGZ_SNAPSHOTTER_VERSION}/${fname}" && \ - curl -o "stargz-snapshotter.service" -fSL "https://raw.githubusercontent.com/containerd/stargz-snapshotter/${STARGZ_SNAPSHOTTER_VERSION}/script/config/etc/systemd/system/stargz-snapshotter.service" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/containerd/stargz-snapshotter/releases/download/${STARGZ_SNAPSHOTTER_VERSION}/${fname}" && \ + curl -o "stargz-snapshotter.service" -fsSL --proto '=https' --tlsv1.2 "https://raw.githubusercontent.com/containerd/stargz-snapshotter/${STARGZ_SNAPSHOTTER_VERSION}/script/config/etc/systemd/system/stargz-snapshotter.service" && \ grep "${fname}" "/SHA256SUMS.d/stargz-snapshotter-${STARGZ_SNAPSHOTTER_VERSION}" | sha256sum -c - && \ grep "stargz-snapshotter.service" "/SHA256SUMS.d/stargz-snapshotter-${STARGZ_SNAPSHOTTER_VERSION}" | sha256sum -c - && \ tar xzf "${fname}" -C /out/bin && \ @@ -184,14 +184,14 @@ RUN git clone https://github.com/containerd/imgcrypt.git /go/src/github.com/cont echo "- imgcrypt: ${IMGCRYPT_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG ROOTLESSKIT_VERSION RUN fname="rootlesskit-$(cat /target_uname_m).tar.gz" && \ - curl -o "${fname}" -fSL "https://github.com/rootless-containers/rootlesskit/releases/download/${ROOTLESSKIT_VERSION}/${fname}" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/rootless-containers/rootlesskit/releases/download/${ROOTLESSKIT_VERSION}/${fname}" && \ grep "${fname}" "/SHA256SUMS.d/rootlesskit-${ROOTLESSKIT_VERSION}" | sha256sum -c && \ tar xzf "${fname}" -C /out/bin && \ rm -f "${fname}" /out/bin/rootlesskit-docker-proxy && \ echo "- RootlessKit: ${ROOTLESSKIT_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG SLIRP4NETNS_VERSION RUN fname="slirp4netns-$(cat /target_uname_m)" && \ - curl -o "${fname}" -fSL "https://github.com/rootless-containers/slirp4netns/releases/download/${SLIRP4NETNS_VERSION}/${fname}" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/rootless-containers/slirp4netns/releases/download/${SLIRP4NETNS_VERSION}/${fname}" && \ grep "${fname}" "/SHA256SUMS.d/slirp4netns-${SLIRP4NETNS_VERSION}" | sha256sum -c && \ mv "${fname}" /out/bin/slirp4netns && \ chmod +x /out/bin/slirp4netns && \ @@ -201,14 +201,14 @@ COPY --from=build-bypass4netns /out/${TARGETARCH:-amd64}/* /out/bin/ RUN echo "- bypass4netns: ${BYPASS4NETNS_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG FUSE_OVERLAYFS_VERSION RUN fname="fuse-overlayfs-$(cat /target_uname_m)" && \ - curl -o "${fname}" -fSL "https://github.com/containers/fuse-overlayfs/releases/download/${FUSE_OVERLAYFS_VERSION}/${fname}" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/containers/fuse-overlayfs/releases/download/${FUSE_OVERLAYFS_VERSION}/${fname}" && \ grep "${fname}" "/SHA256SUMS.d/fuse-overlayfs-${FUSE_OVERLAYFS_VERSION}" | sha256sum -c && \ mv "${fname}" /out/bin/fuse-overlayfs && \ chmod +x /out/bin/fuse-overlayfs && \ echo "- fuse-overlayfs: ${FUSE_OVERLAYFS_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG CONTAINERD_FUSE_OVERLAYFS_VERSION RUN fname="containerd-fuse-overlayfs-${CONTAINERD_FUSE_OVERLAYFS_VERSION/v}-${TARGETOS:-linux}-${TARGETARCH:-amd64}.tar.gz" && \ - curl -o "${fname}" -fSL "https://github.com/containerd/fuse-overlayfs-snapshotter/releases/download/${CONTAINERD_FUSE_OVERLAYFS_VERSION}/${fname}" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/containerd/fuse-overlayfs-snapshotter/releases/download/${CONTAINERD_FUSE_OVERLAYFS_VERSION}/${fname}" && \ grep "${fname}" "/SHA256SUMS.d/containerd-fuse-overlayfs-${CONTAINERD_FUSE_OVERLAYFS_VERSION}" | sha256sum -c && \ tar xzf "${fname}" -C /out/bin && \ rm -f "${fname}" && \ @@ -218,13 +218,13 @@ COPY --from=build-kubo /out/${TARGETARCH:-amd64}/* /out/bin/ RUN echo "- Kubo (IPFS): ${KUBO_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG TINI_VERSION RUN fname="tini-static-${TARGETARCH:-amd64}" && \ - curl -o "${fname}" -fSL "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/${fname}" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/${fname}" && \ grep "${fname}" "/SHA256SUMS.d/tini-${TINI_VERSION}" | sha256sum -c && \ cp -a "${fname}" /out/bin/tini && chmod +x /out/bin/tini && \ echo "- Tini: ${TINI_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG BUILDG_VERSION RUN fname="buildg-${BUILDG_VERSION}-${TARGETOS:-linux}-${TARGETARCH:-amd64}.tar.gz" && \ - curl -o "${fname}" -fSL "https://github.com/ktock/buildg/releases/download/${BUILDG_VERSION}/${fname}" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/ktock/buildg/releases/download/${BUILDG_VERSION}/${fname}" && \ grep "${fname}" "/SHA256SUMS.d/buildg-${BUILDG_VERSION}" | sha256sum -c && \ tar xzf "${fname}" -C /out/bin && \ rm -f "${fname}" && \ @@ -255,7 +255,7 @@ RUN apt-get update -qq && apt-get install -qq -y --no-install-recommends \ dbus dbus-user-session systemd systemd-sysv \ fuse3 ARG CONTAINERIZED_SYSTEMD_VERSION -RUN curl -L -o /docker-entrypoint.sh https://raw.githubusercontent.com/AkihiroSuda/containerized-systemd/${CONTAINERIZED_SYSTEMD_VERSION}/docker-entrypoint.sh && \ +RUN curl -o /docker-entrypoint.sh -fsSL --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/AkihiroSuda/containerized-systemd/${CONTAINERIZED_SYSTEMD_VERSION}/docker-entrypoint.sh && \ chmod +x /docker-entrypoint.sh COPY --from=out-full / /usr/local/ RUN perl -pi -e 's/multi-user.target/docker-entrypoint.target/g' /usr/local/lib/systemd/system/*.service && \ @@ -284,7 +284,7 @@ RUN apt-get update -qq && apt-get install -qq --no-install-recommends \ git COPY --from=goversion /GOVERSION /GOVERSION ARG TARGETARCH -RUN curl -L https://golang.org/dl/$(cat /GOVERSION).linux-${TARGETARCH:-amd64}.tar.gz | tar xzvC /usr/local +RUN curl -fsSL --proto '=https' --tlsv1.2 https://golang.org/dl/$(cat /GOVERSION).linux-${TARGETARCH:-amd64}.tar.gz | tar xzvC /usr/local ENV PATH=/usr/local/go/bin:$PATH ARG GOTESTSUM_VERSION RUN GOBIN=/usr/local/bin go install gotest.tools/gotestsum@${GOTESTSUM_VERSION} @@ -297,7 +297,7 @@ COPY --from=gcr.io/projectsigstore/cosign:v2.2.3@sha256:8fc9cad121611e8479f65f79 # installing soci for integration test ARG SOCI_SNAPSHOTTER_VERSION RUN fname="soci-snapshotter-${SOCI_SNAPSHOTTER_VERSION}-${TARGETOS:-linux}-${TARGETARCH:-amd64}.tar.gz" && \ - curl -o "${fname}" -fSL "https://github.com/awslabs/soci-snapshotter/releases/download/v${SOCI_SNAPSHOTTER_VERSION}/${fname}" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/awslabs/soci-snapshotter/releases/download/v${SOCI_SNAPSHOTTER_VERSION}/${fname}" && \ tar -C /usr/local/bin -xvf "${fname}" soci soci-snapshotter-grpc # enable offline ipfs for integration test COPY ./Dockerfile.d/test-integration-etc_containerd-stargz-grpc_config.toml /etc/containerd-stargz-grpc/config.toml @@ -314,7 +314,7 @@ RUN systemctl enable test-integration-ipfs-offline test-integration-buildkit-ner ipfs config Addresses.Gateway "/ip4/127.0.0.1/tcp/5889" # install nydus components ARG NYDUS_VERSION -RUN curl -L -o nydus-static.tgz "https://github.com/dragonflyoss/image-service/releases/download/${NYDUS_VERSION}/nydus-static-${NYDUS_VERSION}-linux-${TARGETARCH}.tgz" && \ +RUN curl -o nydus-static.tgz -fsSL --proto '=https' --tlsv1.2 "https://github.com/dragonflyoss/image-service/releases/download/${NYDUS_VERSION}/nydus-static-${NYDUS_VERSION}-linux-${TARGETARCH}.tgz" && \ tar xzf nydus-static.tgz && \ mv nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/bin/ && \ rm nydus-static.tgz diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/README.md b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/README.md index b8549e06238..05bd41fdc67 100644 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/README.md +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/README.md @@ -36,7 +36,7 @@ Prepare `kind-worker` (1st node) for importing an image to IPFS ```console $ docker exec -it kind-worker /bin/bash (kind-worker)# NERDCTL_VERSION=0.23.0 -(kind-worker)# curl -sSL --output /tmp/nerdctl.tgz https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz +(kind-worker)# curl -o /tmp/nerdctl.tgz -fsSL --proto '=https' --tlsv1.2 https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz (kind-worker)# tar zxvf /tmp/nerdctl.tgz -C /usr/local/bin/ ``` diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/nerdctl-ipfs-registry.yaml b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/nerdctl-ipfs-registry.yaml index 8a7d350f780..3e9a9743f09 100644 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/nerdctl-ipfs-registry.yaml +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/nerdctl-ipfs-registry.yaml @@ -310,7 +310,7 @@ data: # wait for ipfs daemon ok=false for i in $(seq 100) ; do - if curl localhost:9095/api/v0/id >/dev/null 2>&1 ; then + if curl -fsSL localhost:9095/api/v0/id >/dev/null 2>&1 ; then ok=true break fi diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/README.md b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/README.md index 8c6334677d0..80db2fcd4f5 100644 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/README.md +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/README.md @@ -49,7 +49,7 @@ Prepare `kind-worker` (1st node) for importing an image to IPFS ```console $ docker exec -it kind-worker /bin/bash (kind-worker)# NERDCTL_VERSION=0.23.0 -(kind-worker)# curl -sSL --output /tmp/nerdctl.tgz https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz +(kind-worker)# curl -o /tmp/nerdctl.tgz -fsSL --proto '=https' --tlsv1.2 https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz (kind-worker)# tar zxvf /tmp/nerdctl.tgz -C /usr/local/bin/ ``` diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/nerdctl-ipfs-registry.yaml b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/nerdctl-ipfs-registry.yaml index f2f8551104a..6da5096546f 100644 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/nerdctl-ipfs-registry.yaml +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/nerdctl-ipfs-registry.yaml @@ -193,7 +193,7 @@ data: # wait for ipfs daemon ok=false for i in $(seq 100) ; do - if curl localhost:5001/api/v0/id >/dev/null 2>&1 ; then + if curl -fsSL localhost:5001/api/v0/id >/dev/null 2>&1 ; then ok=true break fi diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md b/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md index 64c91f02a88..53ef383802f 100644 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs/README.md @@ -34,7 +34,7 @@ Prepare `kind-worker` (1st node) for importing an image to IPFS ```console $ docker exec -it kind-worker /bin/bash (kind-worker)# NERDCTL_VERSION=0.23.0 -(kind-worker)# curl -sSL --output /tmp/nerdctl.tgz https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz +(kind-worker)# curl -fsSL --proto '=https' --tlsv1.2 --output /tmp/nerdctl.tgz https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz (kind-worker)# tar zxvf /tmp/nerdctl.tgz -C /usr/local/bin/ ``` diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs/nerdctl-ipfs-registry.yaml b/examples/nerdctl-ipfs-registry-kubernetes/ipfs/nerdctl-ipfs-registry.yaml index f2f8551104a..6da5096546f 100644 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs/nerdctl-ipfs-registry.yaml +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs/nerdctl-ipfs-registry.yaml @@ -193,7 +193,7 @@ data: # wait for ipfs daemon ok=false for i in $(seq 100) ; do - if curl localhost:5001/api/v0/id >/dev/null 2>&1 ; then + if curl -fsSL localhost:5001/api/v0/id >/dev/null 2>&1 ; then ok=true break fi From 79b80d685b142d68d296139100cefd220b66ad5c Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 12 Jul 2024 13:47:39 -0700 Subject: [PATCH 0579/1066] Update go.mod Signed-off-by: apostasie --- go.mod | 71 ++++++++++++----------- go.sum | 176 ++++++++++++++++++++++----------------------------------- 2 files changed, 103 insertions(+), 144 deletions(-) diff --git a/go.mod b/go.mod index eafda312a60..af557f2670b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/containerd/nerdctl/v2 -go 1.21 +go 1.21.12 require ( github.com/Masterminds/semver/v3 v3.2.1 @@ -8,7 +8,7 @@ require ( github.com/Microsoft/hcsshim v0.12.4 github.com/awslabs/soci-snapshotter v0.6.1 github.com/compose-spec/compose-go/v2 v2.1.3 - github.com/containerd/accelerated-container-image v1.1.3 + github.com/containerd/accelerated-container-image v1.1.4 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd v1.7.19 @@ -29,6 +29,7 @@ require ( github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.0 + github.com/distribution/reference v0.6.0 github.com/docker/cli v27.0.3+incompatible github.com/docker/docker v27.0.3+incompatible github.com/docker/go-connections v0.5.0 @@ -37,6 +38,7 @@ require ( github.com/fatih/color v1.17.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/ipfs/go-cid v0.4.1 + github.com/klauspost/compress v1.17.9 github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/mapstructure v1.5.0 github.com/moby/sys/mount v0.3.3 @@ -66,27 +68,25 @@ require ( gotest.tools/v3 v3.5.1 ) -require github.com/go-viper/mapstructure/v2 v2.0.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 - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect - github.com/cilium/ebpf v0.11.0 // indirect + github.com/cilium/ebpf v0.15.0 // indirect github.com/containerd/errdefs v0.1.0 // indirect - github.com/containerd/go-runc v1.0.0 // indirect + github.com/containerd/go-runc v1.1.0 // indirect 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.10 // indirect - github.com/distribution/reference v0.6.0 + github.com/containerd/typeurl v1.0.2 // indirect + github.com/containers/ocicrypt v1.2.0 // indirect github.com/djherbis/times v1.6.0 // indirect - github.com/docker/docker-credential-helpers v0.7.0 // indirect + github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect - github.com/felixge/httpsnoop v1.0.3 // indirect - github.com/go-jose/go-jose/v3 v3.0.3 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-jose/go-jose/v4 v4.0.3 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.0.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -96,8 +96,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.9 - github.com/klauspost/cpuid/v2 v2.2.3 // indirect + github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect @@ -111,35 +110,35 @@ require ( github.com/moby/sys/user v0.1.0 // indirect 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 - github.com/multiformats/go-multiaddr v0.12.0 // indirect - github.com/multiformats/go-multibase v0.1.1 // indirect - github.com/multiformats/go-multihash v0.2.1 // indirect - github.com/multiformats/go-varint v0.0.6 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr v0.13.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect github.com/opencontainers/selinux v1.11.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/philhofer/fwd v1.1.1 // indirect + github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect 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-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 + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tinylib/msgp v1.2.0 // indirect github.com/vbatts/tar-split v0.11.5 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect - go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect + go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // 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 - golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect - google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/grpc v1.62.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect - lukechampine.com/blake3 v1.1.7 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect + google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + lukechampine.com/blake3 v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 3957163b05d..50cc1d9f08f 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -19,17 +19,16 @@ github.com/awslabs/soci-snapshotter v0.6.1/go.mod h1:o9NuuMmvmcpc+jRSoJlQqSqrWCj github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y= -github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs= +github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk= +github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/compose-spec/compose-go/v2 v2.1.3 h1:bD67uqLuL/XgkAK6ir3xZvNLFPxPScEi1KW7R5esrLE= github.com/compose-spec/compose-go/v2 v2.1.3/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= -github.com/containerd/accelerated-container-image v1.1.3 h1:4fw0FsGB3YPHzth8H8WalJxnVuUU566+UCTXnoIZRCQ= -github.com/containerd/accelerated-container-image v1.1.3/go.mod h1:9mpTpL4W4yAsq2giHgo4B7wTFJgE59qCPh7dZTSpGCA= +github.com/containerd/accelerated-container-image v1.1.4 h1:9iFHrNRSFnta1A4z6HP1MVD7vH3hEd7jvJv9wnHHJHc= +github.com/containerd/accelerated-container-image v1.1.4/go.mod h1:9mpTpL4W4yAsq2giHgo4B7wTFJgE59qCPh7dZTSpGCA= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= -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.19 h1:/xQ4XRJ0tamDkdzrrBAUy/LE5nCcxFKdBm4EcPrSMEE= @@ -44,8 +43,8 @@ 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.10 h1:c2U73nld7spSWfiJwSh/8W9DK+/qQwYM2rngIhCyhyg= github.com/containerd/go-cni v1.1.10/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= -github.com/containerd/go-runc v1.0.0 h1:oU+lLv1ULm5taqgV/CJivypVODI4SUz1znWjv3nNYS0= -github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA= +github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U= github.com/containerd/imgcrypt v1.1.11 h1:3RULIeLouE7B5l9NzMq0HdPWG0DP5deEVxB5UKxyUoU= github.com/containerd/imgcrypt v1.1.11/go.mod h1:nXL4jp1GrtO758b16DVsxaHHzu9PravAsKARYmyHR58= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -62,16 +61,16 @@ github.com/containerd/stargz-snapshotter/ipfs v0.15.1 h1:MMWRYrTu2iVOn9eRJqEer7v github.com/containerd/stargz-snapshotter/ipfs v0.15.1/go.mod h1:DvrczCWAJnbTOau8txguZXDZdA7r39O3/Aj2olx+Q90= 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 v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/containernetworking/cni v1.2.2 h1:9IbP6KJQQxVKo4hhnm8r50YcVKrJbJu3Dqw+Rbt1vYk= github.com/containernetworking/cni v1.2.2/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= -github.com/containers/ocicrypt v1.1.10 h1:r7UR6o8+lyhkEywetubUUgcKFjOWOaWz8cEBrCPX0ic= -github.com/containers/ocicrypt v1.1.10/go.mod h1:YfzSSr06PTHQwSTUKqDSjish9BeW1E4HUmreluQcMd8= +github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sirVuPM= +github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U= 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= @@ -92,8 +91,8 @@ github.com/docker/cli v27.0.3+incompatible h1:usGs0/BoBW8MWxGeEtqPMkzOY56jZ6kYlS github.com/docker/cli v27.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= -github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= +github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= +github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= @@ -108,19 +107,19 @@ github.com/fahedouch/go-logrotate v0.2.1 h1:Q0Hk9Kp/Y4iwy9uR9e/60fEoxGhvfk8MG7Ww github.com/fahedouch/go-logrotate v0.2.1/go.mod h1:Mmyex1f9fGXBNnhS9uHsbnO9BGvADF4VGqVnqAJalgc= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= -github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= -github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= -github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= +github.com/go-jose/go-jose/v4 v4.0.3 h1:o8aphO8Hv6RPmH+GfzVuyf7YXSBibp+8YyHdOoDESGo= +github.com/go-jose/go-jose/v4 v4.0.3/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc= @@ -144,7 +143,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -153,8 +151,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= @@ -175,9 +171,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= -github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= +github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -222,16 +217,16 @@ github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELU github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= -github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= -github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= -github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE= -github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8= -github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= -github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= -github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= -github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= -github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= -github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.13.0 h1:BCBzs61E3AGHcYYTv8dqRH43ZfyrqM8RXVPT8t13tLQ= +github.com/multiformats/go-multiaddr v0.13.0/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= @@ -240,7 +235,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= 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.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= @@ -249,8 +243,8 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -258,14 +252,13 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rootless-containers/bypass4netns v0.4.1 h1:zyYM1uSG7/prAphD2vlJvx/MEKK91EjD2XaefGx5PKA= github.com/rootless-containers/bypass4netns v0.4.1/go.mod h1:slu3ygwy1x6ey78oBTNs7lpymyEimLBYoXOG76b+Q+Y= github.com/rootless-containers/rootlesskit/v2 v2.1.0 h1:dKqduSlzo5TlTv7tTIoTct2cRUNQf+soqcs+6b1ynvE= github.com/rootless-containers/rootlesskit/v2 v2.1.0/go.mod h1:W+5NaXv3l2sD4LiPxRWLOlY+p9H0+Ev71zel/zFRnLo= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -281,7 +274,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -294,10 +286,11 @@ github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= -github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= +github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= @@ -316,19 +309,18 @@ github.com/yuchanns/srslog v1.1.0 h1:CEm97Xxxd8XpJThE0gc/XsqUGgPufh5u5MUjC27/KOk github.com/yuchanns/srslog v1.1.0/go.mod h1:HsLjdv3XV02C3kgBW2bTyW6i88OQE+VYJZIxrPKPPak= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M= -go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak= +go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= 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/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= 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= @@ -336,20 +328,16 @@ go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= -golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= +golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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/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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -359,10 +347,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -371,48 +355,29 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -422,12 +387,9 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -437,17 +399,17 @@ 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-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= -google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= 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= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= -google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -457,10 +419,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -472,5 +432,5 @@ gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= -lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= +lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= +lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= From 99b05e631182a36e5916ddef9765ba697e950eb0 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 14 Jul 2024 10:18:05 +0800 Subject: [PATCH 0580/1066] pkg/portutil: use net.SplitHostPort to parse ip address with port Signed-off-by: Akihiro Suda --- pkg/portutil/portutil.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pkg/portutil/portutil.go b/pkg/portutil/portutil.go index f0ffe9b96de..ad2848c4e47 100644 --- a/pkg/portutil/portutil.go +++ b/pkg/portutil/portutil.go @@ -31,20 +31,19 @@ import ( // return respectively ip, hostPort, containerPort func splitParts(rawport string) (string, string, string) { - parts := strings.Split(rawport, ":") - n := len(parts) - containerport := parts[n-1] + lastIndex := strings.LastIndex(rawport, ":") + containerPort := rawport[lastIndex+1:] + if lastIndex == -1 { + return "", "", containerPort + } - switch n { - case 1: - return "", "", containerport - case 2: - return "", parts[0], containerport - case 3: - return parts[0], parts[1], containerport - default: - return strings.Join(parts[:n-2], ":"), parts[n-2], containerport + hostAddrPort := rawport[:lastIndex] + addr, port, err := net.SplitHostPort(hostAddrPort) + if err != nil { + return "", hostAddrPort, containerPort } + + return addr, port, containerPort } // ParseFlagP parse port mapping pair, like "127.0.0.1:3000:8080/tcp", From e7b567cab9d41e7a24368cf686937cddef238a6d Mon Sep 17 00:00:00 2001 From: THLIVSQAZ Date: Sun, 14 Jul 2024 10:23:09 +0800 Subject: [PATCH 0581/1066] pkg/portutil: add ipv6 host ip test Signed-off-by: THLIVSQAZ --- pkg/portutil/portutil_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pkg/portutil/portutil_test.go b/pkg/portutil/portutil_test.go index 87f0f5dc892..e3ec270c2b5 100644 --- a/pkg/portutil/portutil_test.go +++ b/pkg/portutil/portutil_test.go @@ -357,6 +357,21 @@ func TestParseFlagP(t *testing.T) { }, wantErr: false, }, + { + name: "with ipv6 host ip", + args: args{ + s: "[::0]:8080:80/tcp", + }, + want: []gocni.PortMapping{ + { + HostPort: 8080, + ContainerPort: 80, + Protocol: "tcp", + HostIP: "::0", + }, + }, + wantErr: false, + }, { name: "with invalid protocol", args: args{ From f63081507b4952d898cf4558ee55645f733e7a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cz=C3=A9kus=20M=C3=A1t=C3=A9?= Date: Wed, 3 Jul 2024 18:27:36 +0200 Subject: [PATCH 0582/1066] fix: add login component username validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Czékus Máté --- cmd/nerdctl/login.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/nerdctl/login.go b/cmd/nerdctl/login.go index 07e03253f50..9aea0501f88 100644 --- a/cmd/nerdctl/login.go +++ b/cmd/nerdctl/login.go @@ -62,6 +62,10 @@ func processLoginOptions(cmd *cobra.Command) (types.LoginCommandOptions, error) return types.LoginCommandOptions{}, err } + if strings.Contains(username, ":") { + return types.LoginCommandOptions{}, errors.New("username cannot contain colons") + } + if password != "" { log.L.Warn("WARNING! Using --password via the CLI is insecure. Use --password-stdin.") if passwordStdin { From e2ede62ee93d7cae3ea1d9d2fba904aba6396c9b Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 12 Jul 2024 10:18:22 -0700 Subject: [PATCH 0583/1066] Remove no longer useful DOCKER_BUILDKIT=1 Signed-off-by: apostasie --- .github/workflows/test.yml | 6 +++--- cmd/nerdctl/builder_build_test.go | 18 ++++++------------ 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d5930e8d695..d45f27f5360 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -70,7 +70,7 @@ jobs: with: fetch-depth: 1 - name: "Prepare integration test environment" - run: DOCKER_BUILDKIT=1 docker build -t test-integration --target test-integration --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . + run: docker build -t test-integration --target test-integration --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . - name: "Remove snap loopback devices (conflicts with our loopback devices in TestRunDevice)" run: | sudo systemctl disable --now snapd.service snapd.socket @@ -114,7 +114,7 @@ jobs: echo '{"ipv6": true, "fixed-cidr-v6": "2001:db8:1::/64", "experimental": true, "ip6tables": true}' | sudo tee /etc/docker/daemon.json sudo systemctl restart docker - name: "Prepare integration test environment" - run: DOCKER_BUILDKIT=1 docker build -t test-integration-ipv6 --target test-integration-ipv6 --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . + run: docker build -t test-integration-ipv6 --target test-integration-ipv6 --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . - name: "Remove snap loopback devices (conflicts with our loopback devices in TestRunDevice)" run: | sudo systemctl disable --now snapd.service snapd.socket @@ -187,7 +187,7 @@ jobs: - name: "Register QEMU (tonistiigi/binfmt)" run: docker run --privileged --rm tonistiigi/binfmt --install all - name: "Prepare (network driver=slirp4netns, port driver=builtin)" - run: DOCKER_BUILDKIT=1 docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} --build-arg ROOTLESSKIT_VERSION=${ROOTLESSKIT_VERSION} . + run: docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} --build-arg ROOTLESSKIT_VERSION=${ROOTLESSKIT_VERSION} . - name: "Disable BuildKit for RootlessKit v1 (workaround for issue #622)" run: | # https://github.com/containerd/nerdctl/issues/622 diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index 472d93b2495..d4134dde94f 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -45,15 +45,12 @@ CMD ["echo", "nerdctl-build-test-string"] base.Cmd("build", buildCtx, "-t", imageName).AssertOK() base.Cmd("run", "--rm", imageName).AssertOutExactly("nerdctl-build-test-string\n") - // DOCKER_BUILDKIT (v20.10): `Error response from daemon: exporter "docker" could not be found` - if base.Target == testutil.Nerdctl { - ignoredImageNamed := imageName + "-" + "ignored" - outputOpt := fmt.Sprintf("--output=type=docker,name=%s", ignoredImageNamed) - base.Cmd("build", buildCtx, "-t", imageName, outputOpt).AssertOK() - - base.Cmd("run", "--rm", imageName).AssertOutExactly("nerdctl-build-test-string\n") - base.Cmd("run", "--rm", ignoredImageNamed).AssertFail() - } + ignoredImageNamed := imageName + "-" + "ignored" + outputOpt := fmt.Sprintf("--output=type=docker,name=%s", ignoredImageNamed) + base.Cmd("build", buildCtx, "-t", imageName, outputOpt).AssertOK() + + base.Cmd("run", "--rm", imageName).AssertOutExactly("nerdctl-build-test-string\n") + base.Cmd("run", "--rm", ignoredImageNamed).AssertFail() } func TestBuildIsShareableForCompatiblePlatform(t *testing.T) { @@ -200,9 +197,6 @@ CMD ["echo", "nerdctl-build-test-dockerfile"] func TestBuildLocal(t *testing.T) { testutil.RequiresBuild(t) base := testutil.NewBase(t) - if testutil.GetTarget() == testutil.Docker { - base.Env = append(base.Env, "DOCKER_BUILDKIT=1") - } defer base.Cmd("builder", "prune").Run() const testFileName = "nerdctl-build-test" const testContent = "nerdctl" From cfd8982296cc9428c3fc16fc1641378eeb6042c6 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 12 Jul 2024 10:19:26 -0700 Subject: [PATCH 0584/1066] Enhance Makefile Signed-off-by: apostasie --- .github/workflows/release.yml | 2 - Makefile | 88 ++++++++++++++++++++++------------- 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5cd401df273..a26668f6338 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,8 +5,6 @@ on: tags: - 'v*' - 'test-action-release-*' -env: - GO111MODULE: on jobs: release: runs-on: ubuntu-24.04 diff --git a/Makefile b/Makefile index 844ae7213bd..2a8c14cb63e 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ # Licensed under the Apache License, Version 2.0 # ----------------------------------------------------------------------------- +DOCKER ?= docker GO ?= go GOOS ?= $(shell $(GO) env GOOS) ifeq ($(GOOS),windows) @@ -32,18 +33,22 @@ BINDIR ?= $(PREFIX)/bin DATADIR ?= $(PREFIX)/share DOCDIR ?= $(DATADIR)/doc -VERSION ?= $(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags) +MAKEFILE_DIR := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) +VERSION ?= $(shell git -C $(MAKEFILE_DIR) describe --match 'v[0-9]*' --dirty='.m' --always --tags) VERSION_TRIMMED := $(VERSION:v%=%) -REVISION ?= $(shell git rev-parse HEAD)$(shell if ! git diff --no-ext-diff --quiet --exit-code; then echo .m; fi) - -GO_BUILD_LDFLAGS ?= -s -w -GO_BUILD_FLAGS ?= -export GO_BUILD=GO111MODULE=on CGO_ENABLED=0 GOOS=$(GOOS) $(GO) build -ldflags "$(GO_BUILD_LDFLAGS) -X $(PACKAGE)/pkg/version.Version=$(VERSION) -X $(PACKAGE)/pkg/version.Revision=$(REVISION)" +REVISION ?= $(shell git -C $(MAKEFILE_DIR) rev-parse HEAD)$(shell if ! git -C $(MAKEFILE_DIR) diff --no-ext-diff --quiet --exit-code; then echo .m; fi) ifdef VERBOSE VERBOSE_FLAG := -v + VERBOSE_FLAG_LONG := --verbose endif +GO_BUILD_LDFLAGS ?= -s -w +GO_BUILD_FLAGS ?= +export GO_BUILD=CGO_ENABLED=0 GOOS=$(GOOS) $(GO) -C $(MAKEFILE_DIR) build -ldflags "$(GO_BUILD_LDFLAGS) $(VERBOSE_FLAG) -X $(PACKAGE)/pkg/version.Version=$(VERSION) -X $(PACKAGE)/pkg/version.Revision=$(REVISION)" + +recursive_wildcard=$(wildcard $1$2) $(foreach e,$(wildcard $1*),$(call recursive_wildcard,$e/,$2)) + all: binaries help: @@ -52,63 +57,76 @@ help: @echo " * 'install' - Install binaries to system locations." @echo " * 'binaries' - Build nerdctl." @echo " * 'clean' - Clean artifacts." + @echo " * 'lint' - Run various linters." nerdctl: - $(GO_BUILD) $(GO_BUILD_FLAGS) $(VERBOSE_FLAG) -o $(CURDIR)/_output/nerdctl$(BIN_EXT) $(PACKAGE)/cmd/nerdctl + $(GO_BUILD) $(GO_BUILD_FLAGS) $(VERBOSE_FLAG) -o $(CURDIR)/_output/nerdctl$(BIN_EXT) ./cmd/nerdctl clean: find . -name \*~ -delete find . -name \#\* -delete - rm -rf _output/* vendor + rm -rf $(CURDIR)/_output/* $(MAKEFILE_DIR)/vendor + +lint: lint-go lint-yaml lint-shell + +lint-go: + cd $(MAKEFILE_DIR) && golangci-lint run $(VERBOSE_FLAG_LONG) + +lint-yaml: + cd $(MAKEFILE_DIR) && yamllint . + +lint-shell: $(call recursive_wildcard,$(MAKEFILE_DIR)/,*.sh) + shellcheck -a -x $^ binaries: nerdctl install: install -D -m 755 $(CURDIR)/_output/nerdctl $(DESTDIR)$(BINDIR)/nerdctl - install -D -m 755 $(CURDIR)/extras/rootless/containerd-rootless.sh $(DESTDIR)$(BINDIR)/containerd-rootless.sh - install -D -m 755 $(CURDIR)/extras/rootless/containerd-rootless-setuptool.sh $(DESTDIR)$(BINDIR)/containerd-rootless-setuptool.sh - install -D -m 644 -t $(DESTDIR)$(DOCDIR)/nerdctl docs/*.md + install -D -m 755 $(MAKEFILE_DIR)/extras/rootless/containerd-rootless.sh $(DESTDIR)$(BINDIR)/containerd-rootless.sh + install -D -m 755 $(MAKEFILE_DIR)/extras/rootless/containerd-rootless-setuptool.sh $(DESTDIR)$(BINDIR)/containerd-rootless-setuptool.sh + install -D -m 644 -t $(DESTDIR)$(DOCDIR)/nerdctl $(MAKEFILE_DIR)/docs/*.md + +# Note that these options will not work on macOS - unless you use gnu-tar instead of tar +TAR_OWNER0_FLAGS=--owner=0 --group=0 +TAR_FLATTEN_FLAGS=--transform 's/.*\///g' define make_artifact_full_linux - DOCKER_BUILDKIT=1 docker build --output type=tar,dest=$(CURDIR)/_output/nerdctl-full-$(VERSION_TRIMMED)-linux-$(1).tar --target out-full --platform $(1) --build-arg GO_VERSION $(CURDIR) + $(DOCKER) build --output type=tar,dest=$(CURDIR)/_output/nerdctl-full-$(VERSION_TRIMMED)-linux-$(1).tar --target out-full --platform $(1) --build-arg GO_VERSION -f $(MAKEFILE_DIR)/Dockerfile $(MAKEFILE_DIR) gzip -9 $(CURDIR)/_output/nerdctl-full-$(VERSION_TRIMMED)-linux-$(1).tar endef -TAR_OWNER0_FLAGS=--owner=0 --group=0 -TAR_FLATTEN_FLAGS=--transform 's/.*\///g' - artifacts: clean - GOOS=linux GOARCH=amd64 make -C $(CURDIR) binaries - tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-amd64.tar.gz _output/nerdctl extras/rootless/* + GOOS=linux GOARCH=amd64 make -C $(CURDIR) -f $(MAKEFILE_DIR)/Makefile binaries + tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-amd64.tar.gz $(CURDIR)/_output/nerdctl $(MAKEFILE_DIR)/extras/rootless/* - GOOS=linux GOARCH=arm64 make -C $(CURDIR) binaries - tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-arm64.tar.gz _output/nerdctl extras/rootless/* + GOOS=linux GOARCH=arm64 make -C $(CURDIR) -f $(MAKEFILE_DIR)/Makefile binaries + tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-arm64.tar.gz $(CURDIR)/_output/nerdctl $(MAKEFILE_DIR)/extras/rootless/* - GOOS=linux GOARCH=arm GOARM=7 make -C $(CURDIR) binaries - tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-arm-v7.tar.gz _output/nerdctl extras/rootless/* + GOOS=linux GOARCH=arm GOARM=7 make -C $(CURDIR) -f $(MAKEFILE_DIR)/Makefile binaries + tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-arm-v7.tar.gz $(CURDIR)/_output/nerdctl $(MAKEFILE_DIR)/extras/rootless/* - GOOS=linux GOARCH=ppc64le make -C $(CURDIR) binaries - tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-ppc64le.tar.gz _output/nerdctl extras/rootless/* + GOOS=linux GOARCH=ppc64le make -C $(CURDIR) -f $(MAKEFILE_DIR)/Makefile binaries + tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-ppc64le.tar.gz $(CURDIR)/_output/nerdctl $(MAKEFILE_DIR)/extras/rootless/* - GOOS=linux GOARCH=riscv64 make -C $(CURDIR) binaries - tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-riscv64.tar.gz _output/nerdctl extras/rootless/* + GOOS=linux GOARCH=riscv64 make -C $(CURDIR) -f $(MAKEFILE_DIR)/Makefile binaries + tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-riscv64.tar.gz $(CURDIR)/_output/nerdctl $(MAKEFILE_DIR)/extras/rootless/* - GOOS=linux GOARCH=s390x make -C $(CURDIR) binaries - tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-s390x.tar.gz _output/nerdctl extras/rootless/* + GOOS=linux GOARCH=s390x make -C $(CURDIR) -f $(MAKEFILE_DIR)/Makefile binaries + tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-linux-s390x.tar.gz $(CURDIR)/_output/nerdctl $(MAKEFILE_DIR)/extras/rootless/* - GOOS=windows GOARCH=amd64 make -C $(CURDIR) binaries - tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-windows-amd64.tar.gz _output/nerdctl.exe + GOOS=windows GOARCH=amd64 make -C $(CURDIR) -f $(MAKEFILE_DIR)/Makefile binaries + tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-windows-amd64.tar.gz $(CURDIR)/_output/nerdctl.exe - GOOS=freebsd GOARCH=amd64 make -C $(CURDIR) binaries - tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-freebsd-amd64.tar.gz _output/nerdctl + GOOS=freebsd GOARCH=amd64 make -C $(CURDIR) -f $(MAKEFILE_DIR)/Makefile binaries + tar $(TAR_OWNER0_FLAGS) $(TAR_FLATTEN_FLAGS) -czvf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-freebsd-amd64.tar.gz $(CURDIR)/_output/nerdctl rm -f $(CURDIR)/_output/nerdctl $(CURDIR)/_output/nerdctl.exe $(call make_artifact_full_linux,amd64) $(call make_artifact_full_linux,arm64) - go mod vendor - tar $(TAR_OWNER0_FLAGS) -czf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-go-mod-vendor.tar.gz go.mod go.sum vendor + $(GO) -C $(MAKEFILE_DIR) mod vendor + tar $(TAR_OWNER0_FLAGS) -czf $(CURDIR)/_output/nerdctl-$(VERSION_TRIMMED)-go-mod-vendor.tar.gz $(MAKEFILE_DIR)/go.mod $(MAKEFILE_DIR)/go.sum $(MAKEFILE_DIR)/vendor .PHONY: \ help \ @@ -117,3 +135,7 @@ artifacts: clean binaries \ install \ artifacts + lint \ + lint-yaml \ + lint-go \ + lint-shell From 67ade6dbe32e9c30e3e79c148d4c945b0a7d1e3f Mon Sep 17 00:00:00 2001 From: David Son Date: Fri, 29 Mar 2024 22:39:03 +0000 Subject: [PATCH 0585/1066] Move image pull args into ImagePullTypes Signed-off-by: David Son --- cmd/nerdctl/image_pull.go | 25 +++++++++++++----- pkg/api/types/image_types.go | 15 ++++++----- pkg/cmd/compose/compose.go | 17 +++++++++--- pkg/cmd/container/create.go | 7 ++++- pkg/cmd/image/pull.go | 23 +++------------- pkg/imgutil/imgutil.go | 51 +++++++++++++++++------------------- pkg/ipfs/image.go | 14 +++++----- 7 files changed, 81 insertions(+), 71 deletions(-) diff --git a/cmd/nerdctl/image_pull.go b/cmd/nerdctl/image_pull.go index ffb5f45e874..36c4fa617a5 100644 --- a/cmd/nerdctl/image_pull.go +++ b/cmd/nerdctl/image_pull.go @@ -20,6 +20,8 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/spf13/cobra" ) @@ -81,10 +83,19 @@ func processPullCommandFlags(cmd *cobra.Command) (types.ImagePullOptions, error) return types.ImagePullOptions{}, err } + ociSpecPlatform, err := platformutil.NewOCISpecPlatformSlice(allPlatforms, platform) + if err != nil { + return types.ImagePullOptions{}, err + } + unpackStr, err := cmd.Flags().GetString("unpack") if err != nil { return types.ImagePullOptions{}, err } + unpack, err := strutil.ParseBoolOrAuto(unpackStr) + if err != nil { + return types.ImagePullOptions{}, err + } quiet, err := cmd.Flags().GetBool("quiet") if err != nil { @@ -105,13 +116,13 @@ func processPullCommandFlags(cmd *cobra.Command) (types.ImagePullOptions, error) return types.ImagePullOptions{}, err } return types.ImagePullOptions{ - GOptions: globalOptions, - VerifyOptions: verifyOptions, - AllPlatforms: allPlatforms, - Platform: platform, - Unpack: unpackStr, - Quiet: quiet, - IPFSAddress: ipfsAddressStr, + GOptions: globalOptions, + VerifyOptions: verifyOptions, + OCISpecPlatform: ociSpecPlatform, + Unpack: unpack, + Mode: "always", + Quiet: quiet, + IPFSAddress: ipfsAddressStr, RFlags: types.RemoteSnapshotterFlags{ SociIndexDigest: sociIndexDigest, }, diff --git a/pkg/api/types/image_types.go b/pkg/api/types/image_types.go index 084e5bedd78..40015e8a24c 100644 --- a/pkg/api/types/image_types.go +++ b/pkg/api/types/image_types.go @@ -18,6 +18,8 @@ package types import ( "io" + + v1 "github.com/opencontainers/image-spec/specs-go/v1" ) // ImageListOptions specifies options for `nerdctl image list`. @@ -191,12 +193,13 @@ type ImagePullOptions struct { Stderr io.Writer GOptions GlobalCommandOptions VerifyOptions ImageVerifyOptions - // Unpack the image for the current single platform (auto/true/false) - Unpack string - // Pull content for a specific platform - Platform []string - // Pull content for all platforms - AllPlatforms bool + // Unpack the image for the current single platform. + // If nil, it will unpack automatically if only 1 platform is specified. + Unpack *bool + // Content for specific platforms. Empty if `--all-platforms` is true + OCISpecPlatform []v1.Platform + // Pull mode + Mode string // Suppress verbose output Quiet bool // multiaddr of IPFS API (default uses $IPFS_PATH env variable if defined or local directory ~/.ipfs) diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index b0ea6ac3ca9..0b4a49e3e51 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -110,6 +110,17 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op ocispecPlatforms = []ocispec.Platform{parsed} // no append } + imgPullOpts := types.ImagePullOptions{ + GOptions: globalOptions, + OCISpecPlatform: ocispecPlatforms, + Unpack: nil, + Mode: pullMode, + Quiet: quiet, + RFlags: types.RemoteSnapshotterFlags{}, + Stdout: stdout, + Stderr: stderr, + } + // IPFS reference if scheme, ref, err := referenceutil.ParseIPFSRefWithScheme(imageName); err == nil { var ipfsPath string @@ -124,8 +135,7 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op } ipfsPath = dir } - _, err = ipfs.EnsureImage(ctx, client, stdout, stderr, globalOptions.Snapshotter, scheme, ref, - pullMode, ocispecPlatforms, nil, quiet, ipfsPath, types.RemoteSnapshotterFlags{}) + _, err = ipfs.EnsureImage(ctx, client, scheme, ref, ipfsPath, imgPullOpts) return err } @@ -135,8 +145,7 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op return err } - _, err = imgutil.EnsureImage(ctx, client, stdout, stderr, globalOptions.Snapshotter, ref, - pullMode, globalOptions.InsecureRegistry, globalOptions.HostsDir, ocispecPlatforms, nil, quiet, types.RemoteSnapshotterFlags{}) + _, err = imgutil.EnsureImage(ctx, client, ref, imgPullOpts) return err } diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index dd0b596b6f8..22de1bc4135 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -130,7 +130,12 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa } rawRef := args[0] - ensuredImage, err = image.EnsureImage(ctx, client, rawRef, ocispecPlatforms, options.Pull, nil, false, options.ImagePullOpt) + options.ImagePullOpt.Mode = options.Pull + options.ImagePullOpt.OCISpecPlatform = ocispecPlatforms + options.ImagePullOpt.Unpack = nil + options.ImagePullOpt.Quiet = false + + ensuredImage, err = image.EnsureImage(ctx, client, rawRef, options.ImagePullOpt) if err != nil { return nil, nil, err } diff --git a/pkg/cmd/image/pull.go b/pkg/cmd/image/pull.go index 0a87df16d5a..8289057cb2a 100644 --- a/pkg/cmd/image/pull.go +++ b/pkg/cmd/image/pull.go @@ -26,26 +26,13 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/ipfs" - "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/nerdctl/v2/pkg/signutil" - "github.com/containerd/nerdctl/v2/pkg/strutil" - v1 "github.com/opencontainers/image-spec/specs-go/v1" ) // Pull pulls an image specified by `rawRef`. func Pull(ctx context.Context, client *containerd.Client, rawRef string, options types.ImagePullOptions) error { - ocispecPlatforms, err := platformutil.NewOCISpecPlatformSlice(options.AllPlatforms, options.Platform) - if err != nil { - return err - } - - unpack, err := strutil.ParseBoolOrAuto(options.Unpack) - if err != nil { - return err - } - - _, err = EnsureImage(ctx, client, rawRef, ocispecPlatforms, "always", unpack, options.Quiet, options) + _, err := EnsureImage(ctx, client, rawRef, options) if err != nil { return err } @@ -54,7 +41,7 @@ func Pull(ctx context.Context, client *containerd.Client, rawRef string, options } // EnsureImage pulls an image either from ipfs or from registry. -func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, ocispecPlatforms []v1.Platform, pull string, unpack *bool, quiet bool, options types.ImagePullOptions) (*imgutil.EnsuredImage, error) { +func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, options types.ImagePullOptions) (*imgutil.EnsuredImage, error) { var ensured *imgutil.EnsuredImage if scheme, ref, err := referenceutil.ParseIPFSRefWithScheme(rawRef); err == nil { @@ -75,8 +62,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, ipfsPath = dir } - ensured, err = ipfs.EnsureImage(ctx, client, options.Stdout, options.Stderr, options.GOptions.Snapshotter, scheme, ref, - pull, ocispecPlatforms, unpack, quiet, ipfsPath, options.RFlags) + ensured, err = ipfs.EnsureImage(ctx, client, scheme, ref, ipfsPath, options) if err != nil { return nil, err } @@ -88,8 +74,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, return nil, err } - ensured, err = imgutil.EnsureImage(ctx, client, options.Stdout, options.Stderr, options.GOptions.Snapshotter, ref, - pull, options.GOptions.InsecureRegistry, options.GOptions.HostsDir, ocispecPlatforms, unpack, quiet, options.RFlags) + ensured, err = imgutil.EnsureImage(ctx, client, ref, options) if err != nil { return nil, err } diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index f632004093f..0fb33eded2c 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -20,7 +20,6 @@ import ( "context" "encoding/json" "fmt" - "io" "reflect" "github.com/containerd/containerd" @@ -102,26 +101,24 @@ func GetExistingImage(ctx context.Context, client *containerd.Client, snapshotte // EnsureImage ensures the image. // // # When insecure is set, skips verifying certs, and also falls back to HTTP when the registry does not speak HTTPS -// -// FIXME: this func has too many args -func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter, rawRef string, mode PullMode, insecure bool, hostsDirs []string, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, rFlags types.RemoteSnapshotterFlags) (*EnsuredImage, error) { - switch mode { +func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, options types.ImagePullOptions) (*EnsuredImage, error) { + switch options.Mode { case "always", "missing", "never": // NOP default: - return nil, fmt.Errorf("unexpected pull mode: %q", mode) + return nil, fmt.Errorf("unexpected pull mode: %q", options.Mode) } // if not `always` pull and given one platform and image found locally, return existing image directly. - if mode != "always" && len(ocispecPlatforms) == 1 { - if res, err := GetExistingImage(ctx, client, snapshotter, rawRef, ocispecPlatforms[0]); err == nil { + if options.Mode != "always" && len(options.OCISpecPlatform) == 1 { + if res, err := GetExistingImage(ctx, client, options.GOptions.Snapshotter, rawRef, options.OCISpecPlatform[0]); err == nil { return res, nil } else if !errdefs.IsNotFound(err) { return nil, err } } - if mode == "never" { + if options.Mode == "never" { return nil, fmt.Errorf("image not available: %q", rawRef) } @@ -133,30 +130,30 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr refDomain := distributionref.Domain(named) var dOpts []dockerconfigresolver.Opt - if insecure { + if options.GOptions.InsecureRegistry { log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain) dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) } - dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(hostsDirs)) + dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(options.GOptions.HostsDir)) resolver, err := dockerconfigresolver.New(ctx, refDomain, dOpts...) if err != nil { return nil, err } - img, err := PullImage(ctx, client, stdout, stderr, snapshotter, resolver, ref, ocispecPlatforms, unpack, quiet, rFlags) + img, err := PullImage(ctx, client, resolver, ref, options) if err != nil { // In some circumstance (e.g. people just use 80 port to support pure http), the error will contain message like "dial tcp : connection refused". if !errutil.IsErrHTTPResponseToHTTPSClient(err) && !errutil.IsErrConnectionRefused(err) { return nil, err } - if insecure { + if options.GOptions.InsecureRegistry { log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", refDomain) dOpts = append(dOpts, dockerconfigresolver.WithPlainHTTP(true)) resolver, err = dockerconfigresolver.New(ctx, refDomain, dOpts...) if err != nil { return nil, err } - return PullImage(ctx, client, stdout, stderr, snapshotter, resolver, ref, ocispecPlatforms, unpack, quiet, rFlags) + return PullImage(ctx, client, resolver, ref, options) } log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain) log.G(ctx).Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)") @@ -195,7 +192,7 @@ func ResolveDigest(ctx context.Context, rawRef string, insecure bool, hostsDirs } // PullImage pulls an image using the specified resolver. -func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter string, resolver remotes.Resolver, ref string, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, rFlags types.RemoteSnapshotterFlags) (*EnsuredImage, error) { +func PullImage(ctx context.Context, client *containerd.Client, resolver remotes.Resolver, ref string, options types.ImagePullOptions) (*EnsuredImage, error) { ctx, done, err := client.WithLease(ctx) if err != nil { return nil, err @@ -206,24 +203,24 @@ func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io config := &pull.Config{ Resolver: resolver, RemoteOpts: []containerd.RemoteOpt{}, - Platforms: ocispecPlatforms, // empty for all-platforms + Platforms: options.OCISpecPlatform, // empty for all-platforms } - if !quiet { - config.ProgressOutput = stderr + if !options.Quiet { + config.ProgressOutput = options.Stderr } // unpack(B) if given 1 platform unless specified by `unpack` - unpackB := len(ocispecPlatforms) == 1 - if unpack != nil { - unpackB = *unpack - if unpackB && len(ocispecPlatforms) != 1 { + unpackB := len(options.OCISpecPlatform) == 1 + if options.Unpack != nil { + unpackB = *options.Unpack + if unpackB && len(options.OCISpecPlatform) != 1 { return nil, fmt.Errorf("unpacking requires a single platform to be specified (e.g., --platform=amd64)") } } - snOpt := getSnapshotterOpts(snapshotter) + snOpt := getSnapshotterOpts(options.GOptions.Snapshotter) if unpackB { - log.G(ctx).Debugf("The image will be unpacked for platform %q, snapshotter %q.", ocispecPlatforms[0], snapshotter) + log.G(ctx).Debugf("The image will be unpacked for platform %q, snapshotter %q.", options.OCISpecPlatform[0], options.GOptions.Snapshotter) imgcryptPayload := imgcrypt.Payload{} imgcryptUnpackOpt := encryption.WithUnpackConfigApplyOpts(encryption.WithDecryptedUnpack(&imgcryptPayload)) config.RemoteOpts = append(config.RemoteOpts, @@ -231,9 +228,9 @@ func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io containerd.WithUnpackOpts([]containerd.UnpackOpt{imgcryptUnpackOpt})) // different remote snapshotters will update pull.Config separately - snOpt.apply(config, ref, rFlags) + snOpt.apply(config, ref, options.RFlags) } else { - log.G(ctx).Debugf("The image will not be unpacked. Platforms=%v.", ocispecPlatforms) + log.G(ctx).Debugf("The image will not be unpacked. Platforms=%v.", options.OCISpecPlatform) } containerdImage, err = pull.Pull(ctx, client, ref, config) @@ -248,7 +245,7 @@ func PullImage(ctx context.Context, client *containerd.Client, stdout, stderr io Ref: ref, Image: containerdImage, ImageConfig: *imgConfig, - Snapshotter: snapshotter, + Snapshotter: options.GOptions.Snapshotter, Remote: snOpt.isRemote(), } return res, nil diff --git a/pkg/ipfs/image.go b/pkg/ipfs/image.go index 41e1b40f6cc..f0a8f36c219 100644 --- a/pkg/ipfs/image.go +++ b/pkg/ipfs/image.go @@ -41,12 +41,12 @@ import ( const ipfsPathEnv = "IPFS_PATH" // EnsureImage pull the specified image from IPFS. -func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr io.Writer, snapshotter string, scheme string, ref string, mode imgutil.PullMode, ocispecPlatforms []ocispec.Platform, unpack *bool, quiet bool, ipfsPath string, rFlags types.RemoteSnapshotterFlags) (*imgutil.EnsuredImage, error) { - switch mode { +func EnsureImage(ctx context.Context, client *containerd.Client, scheme, ref, ipfsPath string, options types.ImagePullOptions) (*imgutil.EnsuredImage, error) { + switch options.Mode { case "always", "missing", "never": // NOP default: - return nil, fmt.Errorf("unexpected pull mode: %q", mode) + return nil, fmt.Errorf("unexpected pull mode: %q", options.Mode) } switch scheme { case "ipfs", "ipns": @@ -56,15 +56,15 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr } // if not `always` pull and given one platform and image found locally, return existing image directly. - if mode != "always" && len(ocispecPlatforms) == 1 { - if res, err := imgutil.GetExistingImage(ctx, client, snapshotter, ref, ocispecPlatforms[0]); err == nil { + if options.Mode != "always" && len(options.OCISpecPlatform) == 1 { + if res, err := imgutil.GetExistingImage(ctx, client, options.GOptions.Snapshotter, ref, options.OCISpecPlatform[0]); err == nil { return res, nil } else if !errdefs.IsNotFound(err) { return nil, err } } - if mode == "never" { + if options.Mode == "never" { return nil, fmt.Errorf("image %q is not available", ref) } r, err := ipfs.NewResolver(ipfs.ResolverOptions{ @@ -74,7 +74,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, stdout, stderr if err != nil { return nil, err } - return imgutil.PullImage(ctx, client, stdout, stderr, snapshotter, r, ref, ocispecPlatforms, unpack, quiet, rFlags) + return imgutil.PullImage(ctx, client, r, ref, options) } // Push pushes the specified image to IPFS. From 5affa4fbe8e84626c68e661a79f85b053e0e78d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 22:14:41 +0000 Subject: [PATCH 0586/1066] build(deps): bump docker/build-push-action from 6.3.0 to 6.4.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.3.0 to 6.4.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.3.0...v6.4.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 6a2f93c2061..007931eb53f 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.3.0 + uses: docker/build-push-action@v6.4.0 with: context: . platforms: linux/amd64,linux/arm64 From 6eccd9af28bdef63e7a7e035ab182985d75e8a7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 22:35:14 +0000 Subject: [PATCH 0587/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.12.4 to 0.12.5 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.12.4 to 0.12.5. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.4...v0.12.5) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eafda312a60..7f2374ab7ee 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.2 - github.com/Microsoft/hcsshim v0.12.4 + github.com/Microsoft/hcsshim v0.12.5 github.com/awslabs/soci-snapshotter v0.6.1 github.com/compose-spec/compose-go/v2 v2.1.3 github.com/containerd/accelerated-container-image v1.1.3 diff --git a/go.sum b/go.sum index 3957163b05d..43ba1e97236 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= 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.12.4 h1:Ev7YUMHAHoWNm+aDSPzc5W9s6E2jyL1szpVDJeZ/Rr4= -github.com/Microsoft/hcsshim v0.12.4/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ= +github.com/Microsoft/hcsshim v0.12.5 h1:bpTInLlDy/nDRWFVcefDZZ1+U8tS+rz3MxjKgu9boo0= +github.com/Microsoft/hcsshim v0.12.5/go.mod h1:tIUGego4G1EN5Hb6KC90aDYiUI2dqLSTTOCjVNpOgZ8= github.com/awslabs/soci-snapshotter v0.6.1 h1:ggiuiCPReSNvfUL084Ujyp0glRNiCsZiaCh2rE580HA= github.com/awslabs/soci-snapshotter v0.6.1/go.mod h1:o9NuuMmvmcpc+jRSoJlQqSqrWCjMO1x67C65wmCme7E= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= From bbf2293d9e7649e8ca757d7317f08ceebf1403d6 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 12 Jul 2024 11:31:59 -0700 Subject: [PATCH 0588/1066] Fix shellscript issues Signed-off-by: apostasie --- .../ipfs-cluster/bootstrap.yaml.sh | 2 +- .../ipfs-stargz-snapshotter/bootstrap.yaml.sh | 10 +++--- .../ipfs/bootstrap.yaml.sh | 10 +++--- .../rootless/containerd-rootless-setuptool.sh | 14 +++----- extras/rootless/containerd-rootless.sh | 35 ++++++++++--------- hack/generate-release-note.sh | 10 +++--- 6 files changed, 37 insertions(+), 44 deletions(-) diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/bootstrap.yaml.sh b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/bootstrap.yaml.sh index cc1b29f579e..e77c9a7105e 100755 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/bootstrap.yaml.sh +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-cluster/bootstrap.yaml.sh @@ -28,7 +28,7 @@ done TMPIDFILE=$(mktemp) BOOTSTRAP_KEY=$(ipfs-key 2>"${TMPIDFILE}" | base64 -w 0) -ID=$(cat "${TMPIDFILE}" | grep "ID " | sed -E 's/[^:]*: (.*)/\1/') +ID=$(grep "ID " "${TMPIDFILE}" | sed -E 's/[^:]*: (.*)/\1/') rm "${TMPIDFILE}" BOOTSTRAP_PEER_PRIV_KEY=$(echo "${BOOTSTRAP_KEY}" | base64 -w 0) diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/bootstrap.yaml.sh b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/bootstrap.yaml.sh index 8905f617171..fc06a298e26 100755 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/bootstrap.yaml.sh +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs-stargz-snapshotter/bootstrap.yaml.sh @@ -19,12 +19,10 @@ set -eu -o pipefail -for d in ipfs-swarm-key-gen ; do - if ! command -v $d >/dev/null 2>&1 ; then - echo "$d not found" - exit 1 - fi -done +if ! command -v ipfs-swarm-key-gen >/dev/null 2>&1 ; then + echo "ipfs-swarm-key-gen not found" + exit 1 +fi SWARM_KEY=$(ipfs-swarm-key-gen | base64 | tr -d '\n') diff --git a/examples/nerdctl-ipfs-registry-kubernetes/ipfs/bootstrap.yaml.sh b/examples/nerdctl-ipfs-registry-kubernetes/ipfs/bootstrap.yaml.sh index 8905f617171..fc06a298e26 100755 --- a/examples/nerdctl-ipfs-registry-kubernetes/ipfs/bootstrap.yaml.sh +++ b/examples/nerdctl-ipfs-registry-kubernetes/ipfs/bootstrap.yaml.sh @@ -19,12 +19,10 @@ set -eu -o pipefail -for d in ipfs-swarm-key-gen ; do - if ! command -v $d >/dev/null 2>&1 ; then - echo "$d not found" - exit 1 - fi -done +if ! command -v ipfs-swarm-key-gen >/dev/null 2>&1 ; then + echo "ipfs-swarm-key-gen not found" + exit 1 +fi SWARM_KEY=$(ipfs-swarm-key-gen | base64 | tr -d '\n') diff --git a/extras/rootless/containerd-rootless-setuptool.sh b/extras/rootless/containerd-rootless-setuptool.sh index 747d5c41c87..27627640d51 100755 --- a/extras/rootless/containerd-rootless-setuptool.sh +++ b/extras/rootless/containerd-rootless-setuptool.sh @@ -29,19 +29,15 @@ set -eu # utility functions INFO() { - # https://github.com/koalaman/shellcheck/issues/1593 - # shellcheck disable=SC2039 - /bin/echo -e "\e[104m\e[97m[INFO]\e[49m\e[39m ${*}" + printf "\e[104m\e[97m[INFO]\e[49m\e[39m %s\n" "$*" } WARNING() { - # shellcheck disable=SC2039 - /bin/echo >&2 -e "\e[101m\e[97m[WARNING]\e[49m\e[39m ${*}" + >&2 printf "\e[101m\e[97m[WARNING]\e[49m\e[39m %s\n" "$*" } ERROR() { - # shellcheck disable=SC2039 - /bin/echo >&2 -e "\e[101m\e[97m[ERROR]\e[49m\e[39m ${*}" + >&2 printf "\e[101m\e[97m[ERROR]\e[49m\e[39m %s\n" "$*" } # constants @@ -143,8 +139,8 @@ propagate_env_from() { pid="$1" env="$(sed -e "s/\x0/'\n/g" <"/proc/${pid}/environ" | sed -Ee "s/^[^=]*=/export \0'/g")" shift - for key in $@; do - eval $(echo "$env" | grep "^export ${key=}") + for key in "$@"; do + eval "$(echo "$env" | grep "^export ${key=}")" done } diff --git a/extras/rootless/containerd-rootless.sh b/extras/rootless/containerd-rootless.sh index eff0e4241ea..f569484a574 100755 --- a/extras/rootless/containerd-rootless.sh +++ b/extras/rootless/containerd-rootless.sh @@ -60,14 +60,14 @@ fi : "${XDG_DATA_HOME:=$HOME/.local/share}" : "${XDG_CONFIG_HOME:=$HOME/.config}" -if [ -z $_CONTAINERD_ROOTLESS_CHILD ]; then +if [ -z "$_CONTAINERD_ROOTLESS_CHILD" ]; then if [ "$(id -u)" = "0" ]; then echo "Must not run as root" exit 1 fi case "$1" in "check" | "install" | "uninstall") - echo "Did you mean 'containerd-rootless-setuptool.sh $@' ?" + echo "Did you mean 'containerd-rootless-setuptool.sh $*' ?" exit 1 ;; esac @@ -81,19 +81,19 @@ if [ -z $_CONTAINERD_ROOTLESS_CHILD ]; then : "${CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS:=auto}" net=$CONTAINERD_ROOTLESS_ROOTLESSKIT_NET mtu=$CONTAINERD_ROOTLESS_ROOTLESSKIT_MTU - if [ -z $net ]; then + if [ -z "$net" ]; then if command -v slirp4netns >/dev/null 2>&1; then # If --netns-type is present in --help, slirp4netns is >= v0.4.0. if slirp4netns --help | grep -qw -- --netns-type; then net=slirp4netns - if [ -z $mtu ]; then + if [ -z "$mtu" ]; then mtu=65520 fi else echo "slirp4netns found but seems older than v0.4.0. Falling back to VPNKit." fi fi - if [ -z $net ]; then + if [ -z "$net" ]; then if command -v vpnkit >/dev/null 2>&1; then net=vpnkit else @@ -102,7 +102,7 @@ if [ -z $_CONTAINERD_ROOTLESS_CHILD ]; then fi fi fi - if [ -z $mtu ]; then + if [ -z "$mtu" ]; then mtu=1500 fi @@ -120,12 +120,12 @@ if [ -z $_CONTAINERD_ROOTLESS_CHILD ]; then case "$CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS" in auto) - if rootlesskit --help | grep -qw -- "--detach-netns"; then - CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS=--detach-netns $CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS + if rootlesskit --help | grep -qw -- "--detach-netns"; then + CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS="--detach-netns $CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS" fi ;; 1 | true) - CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS=--detach-netns $CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS + CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS="--detach-netns $CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS" ;; 0 | false) # NOP @@ -144,18 +144,19 @@ if [ -z $_CONTAINERD_ROOTLESS_CHILD ]; then # (by either systemd-networkd or NetworkManager) # * /run: copy-up is required so that we can create /run/containerd (hardcoded) in our namespace # * /var/lib: copy-up is required so that we can create /var/lib/containerd in our namespace + # shellcheck disable=SC2086 exec rootlesskit \ - --state-dir=$CONTAINERD_ROOTLESS_ROOTLESSKIT_STATE_DIR \ - --net=$net --mtu=$mtu \ - --slirp4netns-sandbox=$CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SANDBOX \ - --slirp4netns-seccomp=$CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SECCOMP \ - --disable-host-loopback --port-driver=$CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER \ + --state-dir="$CONTAINERD_ROOTLESS_ROOTLESSKIT_STATE_DIR" \ + --net="$net" --mtu="$mtu" \ + --slirp4netns-sandbox="$CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SANDBOX" \ + --slirp4netns-seccomp="$CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SECCOMP" \ + --disable-host-loopback --port-driver="$CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER" \ --copy-up=/etc --copy-up=/run --copy-up=/var/lib \ --propagation=rslave \ $CONTAINERD_ROOTLESS_ROOTLESSKIT_FLAGS \ - $0 $@ + "$0" "$@" else - [ $_CONTAINERD_ROOTLESS_CHILD = 1 ] + [ "$_CONTAINERD_ROOTLESS_CHILD" = 1 ] # Remove the *symlinks* for the existing files in the parent namespace if any, # so that we can create our own files in our mount namespace. # The actual files in the parent namespace are *not removed* by this rm command. @@ -193,5 +194,5 @@ else chcon system_u:object_r:iptables_var_run_t:s0 /run fi - exec containerd $@ + exec containerd "$@" fi diff --git a/hack/generate-release-note.sh b/hack/generate-release-note.sh index 87ce76b3f55..70276919be3 100755 --- a/hack/generate-release-note.sh +++ b/hack/generate-release-note.sh @@ -17,8 +17,8 @@ minimal_amd64tgz="$(find _output -name '*linux-amd64.tar.gz*' -and ! -name '*full*')" full_amd64tgz="$(find _output -name '*linux-amd64.tar.gz*' -and -name '*full*')" -minimal_amd64tgz_basename="$(basename ${minimal_amd64tgz})" -full_amd64tgz_basename="$(basename ${full_amd64tgz})" +minimal_amd64tgz_basename="$(basename "${minimal_amd64tgz}")" +full_amd64tgz_basename="$(basename "${full_amd64tgz}")" cat <<-EOX ## Changes @@ -37,7 +37,7 @@ Extract the archive to a path like \`/usr/local/bin\` or \`~/bin\` .

\`\`\` -$(tar tzvf ${minimal_amd64tgz}) +$(tar tzvf "${minimal_amd64tgz}") \`\`\`

@@ -49,7 +49,7 @@ Extract the archive to a path like \`/usr/local\` or \`~/.local\` .

\`\`\` -$(tar tzvf ${full_amd64tgz}) +$(tar tzvf "${full_amd64tgz}") \`\`\`

@@ -59,7 +59,7 @@ $(tar tzvf ${full_amd64tgz}) See \`share/doc/nerdctl-full/README.md\`: \`\`\`markdown -$(tar xOzf ${full_amd64tgz} share/doc/nerdctl-full/README.md) +$(tar xOzf "${full_amd64tgz}" share/doc/nerdctl-full/README.md) \`\`\`

From 579517532d96dfaec20930c71a90957adc12648a Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 16 Jul 2024 10:06:56 -0700 Subject: [PATCH 0589/1066] Account for availability delay of golang docker image Signed-off-by: apostasie --- hack/build-integration-canary.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hack/build-integration-canary.sh b/hack/build-integration-canary.sh index daddfe60ce1..8091a192034 100755 --- a/hack/build-integration-canary.sh +++ b/hack/build-integration-canary.sh @@ -111,6 +111,7 @@ _log::log(){ } log::init(){ + local _ll # Default log to warning if unspecified _ll="$(printf "LOG_LEVEL_%s" "${NERDCTL_CI_LOG_LEVEL:-warning}" | tr '[:lower:]' '[:upper:]')" # Default to 3 (warning) if unrecognized @@ -432,6 +433,10 @@ done GO_VERSION="$(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version)" GO_VERSION="${GO_VERSION##*go}" +# If a release candidate, docker hub may not have the corresponding image yet. +# So, soften the version to just "rc", as they provide that as an alias to the latest available rc on their side +# See https://github.com/containerd/nerdctl/issues/3223 +! grep -Eq "rc[0-9]+$" <<<"$GO_VERSION" || GO_VERSION="${GO_VERSION%rc[0-9]*}-rc" docker_args+=(--build-arg "GO_VERSION=$GO_VERSION") log::debug "${docker_args[*]} ." From cf0e6e6ef0a39e980aec34899fc01bde28d7a5c4 Mon Sep 17 00:00:00 2001 From: CodeChanning Date: Mon, 17 Jun 2024 10:59:33 -0700 Subject: [PATCH 0590/1066] feat: support for -a and --attach in run Signed-off-by: CodeChanning --- cmd/nerdctl/container_run.go | 25 +++++- cmd/nerdctl/container_run_test.go | 120 +++++++++++++++++++++++++++++ docs/command-reference.md | 3 +- pkg/api/types/container_types.go | 2 + pkg/containerutil/containerutil.go | 8 +- pkg/taskutil/taskutil.go | 55 ++++++++++++- 6 files changed, 207 insertions(+), 6 deletions(-) diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 9344cd2b2c1..eab36b8f917 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" @@ -69,6 +70,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 } @@ -304,6 +306,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 } @@ -325,6 +344,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) @@ -381,7 +404,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 diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index 127e763bced..5138d0f0296 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -533,3 +533,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/docs/command-reference.md b/docs/command-reference.md index 7c0c8c3ad76..29c17be1ed7 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -137,6 +137,7 @@ 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` @@ -387,7 +388,7 @@ 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*`, `--publish-all`, `--storage-opt`, `--userns`, `--volume-driver` diff --git a/pkg/api/types/container_types.go b/pkg/api/types/container_types.go index 16fd41301d7..13e798cecad 100644 --- a/pkg/api/types/container_types.go +++ b/pkg/api/types/container_types.go @@ -68,6 +68,8 @@ type ContainerCreateOptions struct { 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/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index d61a478ccd3..91424c42ff5 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -272,7 +272,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/taskutil/taskutil.go b/pkg/taskutil/taskutil.go index 101452f8b0e..b966a137d76 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 From eddbb4e3cd383fa300ecf67f9aa19428af30de82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 22:18:02 +0000 Subject: [PATCH 0591/1066] build(deps): bump github.com/moby/sys/signal in the moby-sys group Bumps the moby-sys group with 1 update: [github.com/moby/sys/signal](https://github.com/moby/sys). Updates `github.com/moby/sys/signal` from 0.7.0 to 0.7.1 - [Release notes](https://github.com/moby/sys/releases) - [Commits](https://github.com/moby/sys/compare/signal/v0.7.0...signal/v0.7.1) --- updated-dependencies: - dependency-name: github.com/moby/sys/signal dependency-type: direct:production update-type: version-update:semver-patch dependency-group: moby-sys ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9e3cecb4ad1..ca1968eb1a8 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/mapstructure v1.5.0 github.com/moby/sys/mount v0.3.3 - github.com/moby/sys/signal v0.7.0 + github.com/moby/sys/signal v0.7.1 github.com/moby/term v0.5.0 github.com/muesli/cancelreader v0.2.2 github.com/opencontainers/go-digest v1.0.0 diff --git a/go.sum b/go.sum index 05367ee5773..daf2756362d 100644 --- a/go.sum +++ b/go.sum @@ -203,8 +203,8 @@ github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStA github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -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/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0= +github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= 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= From 760f35606e4aa0416f956078d765133012995a48 Mon Sep 17 00:00:00 2001 From: Anatoli Babenia Date: Sat, 22 Jun 2024 11:05:06 +0300 Subject: [PATCH 0592/1066] Add `shellcheck` lint to CI Signed-off-by: Anatoli Babenia --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9e8054acff6..9f19acf6535 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,6 +32,8 @@ jobs: args: --verbose - name: yamllint-lint run: yamllint . + - name: shellcheck + run: shellcheck $(find . -name '*.sh') test-unit: runs-on: ubuntu-24.04 From 3e569488f7c77b75235b6b617aa260f4f7502d28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 22:08:22 +0000 Subject: [PATCH 0593/1066] build(deps): bump docker/build-push-action from 6.4.0 to 6.4.1 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.4.0 to 6.4.1. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.4.0...v6.4.1) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 007931eb53f..dd808b654f9 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.4.0 + uses: docker/build-push-action@v6.4.1 with: context: . platforms: linux/amd64,linux/arm64 From b7025537850946169a58932422619a25e6657385 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 22:24:09 +0000 Subject: [PATCH 0594/1066] build(deps): bump github.com/rootless-containers/rootlesskit/v2 Bumps [github.com/rootless-containers/rootlesskit/v2](https://github.com/rootless-containers/rootlesskit) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/rootless-containers/rootlesskit/releases) - [Commits](https://github.com/rootless-containers/rootlesskit/compare/v2.1.0...v2.2.0) --- updated-dependencies: - dependency-name: github.com/rootless-containers/rootlesskit/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ca1968eb1a8..0406ecfa083 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/opencontainers/runtime-spec v1.2.0 github.com/pelletier/go-toml/v2 v2.2.2 github.com/rootless-containers/bypass4netns v0.4.1 - github.com/rootless-containers/rootlesskit/v2 v2.1.0 + github.com/rootless-containers/rootlesskit/v2 v2.2.0 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/tidwall/gjson v1.17.1 diff --git a/go.sum b/go.sum index daf2756362d..4f410979315 100644 --- a/go.sum +++ b/go.sum @@ -256,8 +256,8 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rootless-containers/bypass4netns v0.4.1 h1:zyYM1uSG7/prAphD2vlJvx/MEKK91EjD2XaefGx5PKA= github.com/rootless-containers/bypass4netns v0.4.1/go.mod h1:slu3ygwy1x6ey78oBTNs7lpymyEimLBYoXOG76b+Q+Y= -github.com/rootless-containers/rootlesskit/v2 v2.1.0 h1:dKqduSlzo5TlTv7tTIoTct2cRUNQf+soqcs+6b1ynvE= -github.com/rootless-containers/rootlesskit/v2 v2.1.0/go.mod h1:W+5NaXv3l2sD4LiPxRWLOlY+p9H0+Ev71zel/zFRnLo= +github.com/rootless-containers/rootlesskit/v2 v2.2.0 h1:qTA3QyfsZSKmvKDL7m5lCl55OmJZXmKf381dSb5Ig9E= +github.com/rootless-containers/rootlesskit/v2 v2.2.0/go.mod h1:AyUlpgPnMv085smZXp5mt4D9q4mNjbHOcZwaVobRzyU= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= From b76605b66f3b084bd77f72de12e16adde50f2b4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 22:24:19 +0000 Subject: [PATCH 0595/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.1.3 to 2.1.4. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.1.3...v2.1.4) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ca1968eb1a8..ca3108f93a4 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.5 github.com/awslabs/soci-snapshotter v0.6.1 - github.com/compose-spec/compose-go/v2 v2.1.3 + github.com/compose-spec/compose-go/v2 v2.1.4 github.com/containerd/accelerated-container-image v1.1.4 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index daf2756362d..1e54240e1e5 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk= github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.1.3 h1:bD67uqLuL/XgkAK6ir3xZvNLFPxPScEi1KW7R5esrLE= -github.com/compose-spec/compose-go/v2 v2.1.3/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.1.4 h1:+1UKMvbBJo22Bpulgb9KAeZwRT99hANf3tDQVeG6ZJo= +github.com/compose-spec/compose-go/v2 v2.1.4/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.1.4 h1:9iFHrNRSFnta1A4z6HP1MVD7vH3hEd7jvJv9wnHHJHc= github.com/containerd/accelerated-container-image v1.1.4/go.mod h1:9mpTpL4W4yAsq2giHgo4B7wTFJgE59qCPh7dZTSpGCA= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= From 9229c0072fa4caa0644359753f9457a7d2557ff6 Mon Sep 17 00:00:00 2001 From: Anatoli Babenia Date: Thu, 18 Jul 2024 09:42:48 +0300 Subject: [PATCH 0596/1066] Reuse Makefile for CI commands Signed-off-by: Anatoli Babenia --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9f19acf6535..6eb1496a338 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,9 +31,9 @@ jobs: version: v1.59.1 args: --verbose - name: yamllint-lint - run: yamllint . + run: make lint-yaml - name: shellcheck - run: shellcheck $(find . -name '*.sh') + run: make lint-shell test-unit: runs-on: ubuntu-24.04 From e81fe541f91ae609dd41b5b8b48e185612021f9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jul 2024 22:07:58 +0000 Subject: [PATCH 0597/1066] build(deps): bump github.com/moby/sys/mount in the moby-sys group Bumps the moby-sys group with 1 update: [github.com/moby/sys/mount](https://github.com/moby/sys). Updates `github.com/moby/sys/mount` from 0.3.3 to 0.3.4 - [Release notes](https://github.com/moby/sys/releases) - [Commits](https://github.com/moby/sys/compare/mount/v0.3.3...mount/v0.3.4) --- updated-dependencies: - dependency-name: github.com/moby/sys/mount dependency-type: direct:production update-type: version-update:semver-patch dependency-group: moby-sys ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 7a2dce37b8f..689ed0585f6 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/klauspost/compress v1.17.9 github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/mapstructure v1.5.0 - github.com/moby/sys/mount v0.3.3 + github.com/moby/sys/mount v0.3.4 github.com/moby/sys/signal v0.7.1 github.com/moby/term v0.5.0 github.com/muesli/cancelreader v0.2.2 @@ -104,7 +104,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/locker v1.0.1 // indirect - github.com/moby/sys/mountinfo v0.7.1 // indirect + github.com/moby/sys/mountinfo v0.7.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.1.0 // indirect diff --git a/go.sum b/go.sum index 7fd14129f3d..953cbdbb56e 100644 --- a/go.sum +++ b/go.sum @@ -196,11 +196,10 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= -github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0= -github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= -github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= -github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/mount v0.3.4 h1:yn5jq4STPztkkzSKpZkLcmjue+bZJ0u2AuQY1iNI1Ww= +github.com/moby/sys/mount v0.3.4/go.mod h1:KcQJMbQdJHPlq5lcYT+/CjatWM4PuxKe+XLSVS4J6Os= +github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= +github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0= @@ -365,7 +364,6 @@ golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 579f75e73a4c476baa06a0666524346db09401ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 22:39:41 +0000 Subject: [PATCH 0598/1066] build(deps): bump docker/build-push-action from 6.4.1 to 6.5.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.4.1 to 6.5.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.4.1...v6.5.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index dd808b654f9..5def700d851 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.4.1 + uses: docker/build-push-action@v6.5.0 with: context: . platforms: linux/amd64,linux/arm64 From 83cf033f32d3794ed141458df1ffa6f745a51f70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 22:39:43 +0000 Subject: [PATCH 0599/1066] build(deps): bump docker/login-action from 3.2.0 to 3.3.0 Bumps [docker/login-action](https://github.com/docker/login-action) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: docker/login-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index dd808b654f9..1fef0bb9162 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -44,7 +44,7 @@ jobs: # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} if: github.event_name != 'pull_request' - uses: docker/login-action@v3.2.0 + uses: docker/login-action@v3.3.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} From 06f942c103e253c73c31fe00e56c3493fffbc720 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 22:45:36 +0000 Subject: [PATCH 0600/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.0.3+incompatible to 27.1.0+incompatible - [Commits](https://github.com/docker/cli/compare/v27.0.3...v27.1.0) Updates `github.com/docker/docker` from 27.0.3+incompatible to 27.1.0+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.0.3...v27.1.0) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 689ed0585f6..7d7aececdc4 100644 --- a/go.mod +++ b/go.mod @@ -30,8 +30,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.0 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.0.3+incompatible - github.com/docker/docker v27.0.3+incompatible + github.com/docker/cli v27.1.0+incompatible + github.com/docker/docker v27.1.0+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 953cbdbb56e..c1827bfabbc 100644 --- a/go.sum +++ b/go.sum @@ -87,10 +87,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.0.3+incompatible h1:usGs0/BoBW8MWxGeEtqPMkzOY56jZ6kYlSN5BLDioCQ= -github.com/docker/cli v27.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE= -github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.1.0+incompatible h1:P0KSYmPtNbmx59wHZvG6+rjivhKDRA1BvvWM0f5DgHc= +github.com/docker/cli v27.1.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= +github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 73f2241392b93ccaa540accd55b4e1bba811b706 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 22:45:53 +0000 Subject: [PATCH 0601/1066] build(deps): bump github.com/containernetworking/cni from 1.2.2 to 1.2.3 Bumps [github.com/containernetworking/cni](https://github.com/containernetworking/cni) from 1.2.2 to 1.2.3. - [Release notes](https://github.com/containernetworking/cni/releases) - [Commits](https://github.com/containernetworking/cni/compare/v1.2.2...v1.2.3) --- updated-dependencies: - dependency-name: github.com/containernetworking/cni dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 689ed0585f6..5a1ce9d2649 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/containerd/stargz-snapshotter/estargz v0.15.1 github.com/containerd/stargz-snapshotter/ipfs v0.15.1 github.com/containerd/typeurl/v2 v2.2.0 - github.com/containernetworking/cni v1.2.2 + github.com/containernetworking/cni v1.2.3 github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 diff --git a/go.sum b/go.sum index 953cbdbb56e..65347972ec6 100644 --- a/go.sum +++ b/go.sum @@ -65,8 +65,8 @@ github.com/containerd/typeurl v1.0.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= -github.com/containernetworking/cni v1.2.2 h1:9IbP6KJQQxVKo4hhnm8r50YcVKrJbJu3Dqw+Rbt1vYk= -github.com/containernetworking/cni v1.2.2/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= +github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= +github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sirVuPM= From d941b4f85b1f52b6d5bb1a51ff175b547d970ad6 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 23 Jul 2024 13:20:47 +0900 Subject: [PATCH 0602/1066] containerd/containerd/errdefs -> containerd/errdefs github.com/containerd/containerd/errdefs was moved to github.com/containerd/errdefs Signed-off-by: Akihiro Suda --- cmd/nerdctl/compose_ps.go | 2 +- cmd/nerdctl/compose_start.go | 2 +- cmd/nerdctl/container_run_network_linux_test.go | 2 +- cmd/nerdctl/container_update.go | 2 +- cmd/nerdctl/volume_create.go | 2 +- cmd/nerdctl/volume_create_test.go | 2 +- cmd/nerdctl/volume_inspect_test.go | 2 +- cmd/nerdctl/volume_namespace_test.go | 2 +- cmd/nerdctl/volume_remove_linux_test.go | 2 +- go.mod | 2 +- pkg/bypass4netnsutil/bypass.go | 2 +- pkg/cmd/builder/build.go | 2 +- pkg/cmd/compose/compose.go | 2 +- pkg/cmd/container/kill.go | 2 +- pkg/cmd/container/list.go | 2 +- pkg/cmd/container/logs.go | 2 +- pkg/cmd/container/remove.go | 2 +- pkg/cmd/container/run_mount.go | 2 +- pkg/cmd/container/stats.go | 2 +- pkg/cmd/container/stop.go | 2 +- pkg/cmd/image/tag.go | 2 +- pkg/cmd/namespace/remove.go | 2 +- pkg/cmd/network/create.go | 2 +- pkg/cmd/volume/rm.go | 2 +- pkg/composer/serviceparser/build.go | 2 +- pkg/containerinspector/containerinspector.go | 2 +- pkg/containerutil/cp_linux.go | 2 +- pkg/dnsutil/hostsstore/hostsstore.go | 2 +- pkg/dnsutil/hostsstore/updater.go | 2 +- pkg/formatter/formatter.go | 2 +- pkg/imgutil/commit/commit.go | 2 +- pkg/imgutil/converter/zstd.go | 2 +- pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go | 2 +- pkg/imgutil/jobs/jobs.go | 2 +- pkg/logging/json_logger.go | 2 +- pkg/logging/logging.go | 2 +- pkg/mountutil/mountutil_freebsd.go | 2 +- pkg/mountutil/mountutil_windows.go | 2 +- pkg/mountutil/volumestore/volumestore.go | 2 +- pkg/netutil/netutil.go | 2 +- pkg/rootlessutil/port_linux.go | 2 +- pkg/signalutil/signals.go | 2 +- pkg/strutil/strutil.go | 2 +- pkg/testutil/nettestutil/nettestutil.go | 2 +- 44 files changed, 44 insertions(+), 44 deletions(-) diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose_ps.go index 8d7d54e1b21..aa4fdd20268 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/v2/pkg/clientutil" diff --git a/cmd/nerdctl/compose_start.go b/cmd/nerdctl/compose_start.go index 0268ab4569b..f5e0682085e 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/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/containerutil" diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index 8228bf6ac44..a1d86e56c40 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/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index 534ceb4961b..d52d12a908b 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume_create.go index 9c8bfda26f1..c2c7f8ab760 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume_create.go @@ -19,7 +19,7 @@ package main import ( "fmt" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" diff --git a/cmd/nerdctl/volume_create_test.go b/cmd/nerdctl/volume_create_test.go index 6e599ec2567..5b94bbe6389 100644 --- a/cmd/nerdctl/volume_create_test.go +++ b/cmd/nerdctl/volume_create_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/icmd" ) diff --git a/cmd/nerdctl/volume_inspect_test.go b/cmd/nerdctl/volume_inspect_test.go index 13dde1e8585..dfaca86484f 100644 --- a/cmd/nerdctl/volume_inspect_test.go +++ b/cmd/nerdctl/volume_inspect_test.go @@ -25,7 +25,7 @@ import ( "strings" "testing" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" diff --git a/cmd/nerdctl/volume_namespace_test.go b/cmd/nerdctl/volume_namespace_test.go index 745025dba45..9eb1aa32551 100644 --- a/cmd/nerdctl/volume_namespace_test.go +++ b/cmd/nerdctl/volume_namespace_test.go @@ -19,7 +19,7 @@ package main import ( "testing" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/icmd" ) diff --git a/cmd/nerdctl/volume_remove_linux_test.go b/cmd/nerdctl/volume_remove_linux_test.go index 8394a37ed5c..73e63dd1b4d 100644 --- a/cmd/nerdctl/volume_remove_linux_test.go +++ b/cmd/nerdctl/volume_remove_linux_test.go @@ -21,7 +21,7 @@ import ( "strings" "testing" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" diff --git a/go.mod b/go.mod index ed566165c7c..7665b4dd31a 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/containerd/containerd v1.7.19 github.com/containerd/containerd/api v1.7.19 github.com/containerd/continuity v0.4.3 + github.com/containerd/errdefs v0.1.0 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.10 github.com/containerd/imgcrypt v1.1.11 @@ -74,7 +75,6 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/cilium/ebpf v0.15.0 // indirect - github.com/containerd/errdefs v0.1.0 // indirect github.com/containerd/go-runc v1.1.0 // indirect github.com/containerd/ttrpc v1.2.5 // indirect github.com/containerd/typeurl v1.0.2 // indirect diff --git a/pkg/bypass4netnsutil/bypass.go b/pkg/bypass4netnsutil/bypass.go index 9e69952b70d..2008d457f80 100644 --- a/pkg/bypass4netnsutil/bypass.go +++ b/pkg/bypass4netnsutil/bypass.go @@ -23,7 +23,7 @@ import ( "net" "path/filepath" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" gocni "github.com/containerd/go-cni" "github.com/containerd/nerdctl/v2/pkg/annotations" b4nnapi "github.com/rootless-containers/bypass4netns/pkg/api" diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 0e9e39fbc53..e5df76cf27e 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -29,9 +29,9 @@ 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/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 0b4a49e3e51..aff935ad08d 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -24,7 +24,7 @@ import ( "path/filepath" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/composer" diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index d185ff09be3..cc97c1dd0f7 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -26,7 +26,7 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" gocni "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index c4279ad40d6..f2189c4907c 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -25,9 +25,9 @@ import ( "time" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/pkg/progress" "github.com/containerd/containerd/snapshots" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerdutil" diff --git a/pkg/cmd/container/logs.go b/pkg/cmd/container/logs.go index 1cc79c02bf2..a20dcd9fb86 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/api/types/cri" diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 3bf655b6118..c86cfeff46d 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index 329a2cf5d95..0fc0c216612 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -30,12 +30,12 @@ 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idgen" diff --git a/pkg/cmd/container/stats.go b/pkg/cmd/container/stats.go index de44e7226e0..129480cb7c2 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" diff --git a/pkg/cmd/container/stop.go b/pkg/cmd/container/stop.go index 35457835d0d..59104016c3d 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/image/tag.go b/pkg/cmd/image/tag.go index 4543f2a070d..0c4030e1342 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/referenceutil" diff --git a/pkg/cmd/namespace/remove.go b/pkg/cmd/namespace/remove.go index a4de8514e87..ecb24e10e9e 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/v2/pkg/api/types" ) diff --git a/pkg/cmd/network/create.go b/pkg/cmd/network/create.go index 43f1f96d6ff..dd60901ea63 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/netutil" ) diff --git a/pkg/cmd/volume/rm.go b/pkg/cmd/volume/rm.go index b8f2173fce7..9333abad302 100644 --- a/pkg/cmd/volume/rm.go +++ b/pkg/cmd/volume/rm.go @@ -23,7 +23,7 @@ import ( "fmt" "github.com/containerd/containerd" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" diff --git a/pkg/composer/serviceparser/build.go b/pkg/composer/serviceparser/build.go index 48bd5f88e30..ce39d67a163 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/v2/types" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/reflectutil" diff --git a/pkg/containerinspector/containerinspector.go b/pkg/containerinspector/containerinspector.go index c60f90baca3..3ac41551e75 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/v2/pkg/inspecttypes/native" "github.com/containerd/typeurl/v2" diff --git a/pkg/containerutil/cp_linux.go b/pkg/containerutil/cp_linux.go index 7e6ed4928b7..0d918e526e2 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/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/tarutil" diff --git a/pkg/dnsutil/hostsstore/hostsstore.go b/pkg/dnsutil/hostsstore/hostsstore.go index 1efe3002f37..7783da1da27 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/v2/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 e52ef802e47..5c68e52e89d 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/v2/pkg/netutil" ) diff --git a/pkg/formatter/formatter.go b/pkg/formatter/formatter.go index e8258bde35a..7b3199d6be3 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/v2/pkg/portutil" "github.com/docker/go-units" diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index 982ce2a846a..9d43cb31a3e 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -31,11 +31,11 @@ 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/rootfs" "github.com/containerd/containerd/snapshots" + "github.com/containerd/errdefs" "github.com/containerd/log" imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" diff --git a/pkg/imgutil/converter/zstd.go b/pkg/imgutil/converter/zstd.go index 6d85dabc5ed..1de2355cdd7 100644 --- a/pkg/imgutil/converter/zstd.go +++ b/pkg/imgutil/converter/zstd.go @@ -23,10 +23,10 @@ import ( "github.com/containerd/containerd/archive/compression" "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/nerdctl/v2/pkg/api/types" "github.com/klauspost/compress/zstd" ocispec "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go index f58cfde0543..bad0a33c444 100644 --- a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go +++ b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go @@ -23,10 +23,10 @@ import ( "fmt" "os" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" dockerconfig "github.com/containerd/containerd/remotes/docker/config" + "github.com/containerd/errdefs" "github.com/containerd/log" dockercliconfig "github.com/docker/cli/cli/config" "github.com/docker/cli/cli/config/credentials" 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/logging/json_logger.go b/pkg/logging/json_logger.go index 68ac48740b7..defd6e8174d 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -28,8 +28,8 @@ import ( "strings" "time" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/runtime/v2/logging" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/logging/jsonfile" "github.com/containerd/nerdctl/v2/pkg/strutil" 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_freebsd.go b/pkg/mountutil/mountutil_freebsd.go index dd9433af559..396b772bb2f 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/v2/pkg/mountutil/volumestore" ) diff --git a/pkg/mountutil/mountutil_windows.go b/pkg/mountutil/mountutil_windows.go index 7d9ff965349..447aaca5cb1 100644 --- a/pkg/mountutil/mountutil_windows.go +++ b/pkg/mountutil/mountutil_windows.go @@ -29,8 +29,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/v2/pkg/mountutil/volumestore" ) diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index a9a50a0f8e3..627e78abafe 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -23,8 +23,8 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/identifiers" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/lockutil" diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 3bf69ded3dc..637c8fd96d5 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/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/labels" diff --git a/pkg/rootlessutil/port_linux.go b/pkg/rootlessutil/port_linux.go index e8b166102eb..968d08245ae 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/v2/pkg/api/client" "github.com/rootless-containers/rootlesskit/v2/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/testutil/nettestutil/nettestutil.go b/pkg/testutil/nettestutil/nettestutil.go index be9d14fb8f3..4937b8acc21 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) { From e86fa4c5bcfb629b764b63410ecd1b706fff28cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 05:23:45 +0000 Subject: [PATCH 0603/1066] build(deps): bump github.com/containerd/containerd Bumps the containerd group with 1 update: [github.com/containerd/containerd](https://github.com/containerd/containerd). Updates `github.com/containerd/containerd` from 1.7.19 to 1.7.20 - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v1.7.19...v1.7.20) --- updated-dependencies: - dependency-name: github.com/containerd/containerd dependency-type: direct:production update-type: version-update:semver-patch dependency-group: containerd ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7665b4dd31a..c2d711ba351 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/containerd/accelerated-container-image v1.1.4 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd v1.7.19 + github.com/containerd/containerd v1.7.20 github.com/containerd/containerd/api v1.7.19 github.com/containerd/continuity v0.4.3 github.com/containerd/errdefs v0.1.0 diff --git a/go.sum b/go.sum index 377f988e636..901e6c3c419 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGD github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= 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.19 h1:/xQ4XRJ0tamDkdzrrBAUy/LE5nCcxFKdBm4EcPrSMEE= -github.com/containerd/containerd v1.7.19/go.mod h1:h4FtNYUUMB4Phr6v+xG89RYKj9XccvbNSCKjdufCrkc= +github.com/containerd/containerd v1.7.20 h1:Sl6jQYk3TRavaU83h66QMbI2Nqg9Jm6qzwX57Vsn1SQ= +github.com/containerd/containerd v1.7.20/go.mod h1:52GsS5CwquuqPuLncsXwG0t2CiUce+KsNHJZQJvAgR0= 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= From 4d70ed0bc7a3392c13abc0743aea915d63da4003 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 15:02:06 +0000 Subject: [PATCH 0604/1066] build(deps): bump github.com/awslabs/soci-snapshotter Bumps [github.com/awslabs/soci-snapshotter](https://github.com/awslabs/soci-snapshotter) from 0.6.1 to 0.7.0. - [Release notes](https://github.com/awslabs/soci-snapshotter/releases) - [Changelog](https://github.com/awslabs/soci-snapshotter/blob/main/RELEASES.md) - [Commits](https://github.com/awslabs/soci-snapshotter/compare/v0.6.1...v0.7.0) --- updated-dependencies: - dependency-name: github.com/awslabs/soci-snapshotter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c2d711ba351..64b2c7f1341 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.5 - github.com/awslabs/soci-snapshotter v0.6.1 + github.com/awslabs/soci-snapshotter v0.7.0 github.com/compose-spec/compose-go/v2 v2.1.4 github.com/containerd/accelerated-container-image v1.1.4 github.com/containerd/cgroups/v3 v3.0.3 diff --git a/go.sum b/go.sum index 901e6c3c419..f613cea9624 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.5 h1:bpTInLlDy/nDRWFVcefDZZ1+U8tS+rz3MxjKgu9boo0= github.com/Microsoft/hcsshim v0.12.5/go.mod h1:tIUGego4G1EN5Hb6KC90aDYiUI2dqLSTTOCjVNpOgZ8= -github.com/awslabs/soci-snapshotter v0.6.1 h1:ggiuiCPReSNvfUL084Ujyp0glRNiCsZiaCh2rE580HA= -github.com/awslabs/soci-snapshotter v0.6.1/go.mod h1:o9NuuMmvmcpc+jRSoJlQqSqrWCjMO1x67C65wmCme7E= +github.com/awslabs/soci-snapshotter v0.7.0 h1:p8hKjVNlT3Z8W0ZcsdCjJ5A3qUgD4A0zv6qHrcKjKEg= +github.com/awslabs/soci-snapshotter v0.7.0/go.mod h1:o4LaCms6epXbSpYXcd49a+3QmdjsQAPpKywpp0Ls3TE= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= From fea8219d8156db175200371cd6ad4199029236ca Mon Sep 17 00:00:00 2001 From: CodeChanning Date: Wed, 3 Jul 2024 11:18:14 -0700 Subject: [PATCH 0605/1066] feat: add Status and ID as event attributes Signed-off-by: CodeChanning --- pkg/cmd/system/events.go | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/system/events.go b/pkg/cmd/system/events.go index cb313eca2a7..08a890e3942 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,28 @@ 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" +) + +func TopicToStatus(topic string) Status { + if strings.Contains(strings.ToUpper(topic), string(START)) { + return START + } + + return UNKNOWN +} + // 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() @@ -68,6 +86,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 { @@ -81,7 +100,18 @@ func Events(ctx context.Context, client *containerd.Client, options types.System } } if tmpl != nil { - out := EventOut{e.Timestamp, e.Namespace, e.Topic, string(out)} + 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 { + _, ok := data["container_id"] + if ok { + id = data["container_id"].(string) + } + } + + out := EventOut{e.Timestamp, id, e.Namespace, e.Topic, TopicToStatus(e.Topic), string(out)} var b bytes.Buffer if err := tmpl.Execute(&b, out); err != nil { return err From fa77fb49afa7cd48a72d9aa83f62b1364e4aeef0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 22:33:49 +0000 Subject: [PATCH 0606/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.1.0+incompatible to 27.1.1+incompatible - [Commits](https://github.com/docker/cli/compare/v27.1.0...v27.1.1) Updates `github.com/docker/docker` from 27.1.0+incompatible to 27.1.1+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.1.0...v27.1.1) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 64b2c7f1341..f5911aefc27 100644 --- a/go.mod +++ b/go.mod @@ -31,8 +31,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.0 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.1.0+incompatible - github.com/docker/docker v27.1.0+incompatible + github.com/docker/cli v27.1.1+incompatible + github.com/docker/docker v27.1.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index f613cea9624..3c501ee4881 100644 --- a/go.sum +++ b/go.sum @@ -87,10 +87,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.1.0+incompatible h1:P0KSYmPtNbmx59wHZvG6+rjivhKDRA1BvvWM0f5DgHc= -github.com/docker/cli v27.1.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.1.0+incompatible h1:rEHVQc4GZ0MIQKifQPHSFGV/dVgaZafgRf8fCPtDYBs= -github.com/docker/docker v27.1.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= +github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= +github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 68e7ad349239396e45dbfe07c2384d247e1f4a21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 22:34:03 +0000 Subject: [PATCH 0607/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.1.4 to 2.1.5. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.1.4...v2.1.5) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 64b2c7f1341..d91ce6184d9 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.5 github.com/awslabs/soci-snapshotter v0.7.0 - github.com/compose-spec/compose-go/v2 v2.1.4 + github.com/compose-spec/compose-go/v2 v2.1.5 github.com/containerd/accelerated-container-image v1.1.4 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index f613cea9624..f4da9f026b6 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk= github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.1.4 h1:+1UKMvbBJo22Bpulgb9KAeZwRT99hANf3tDQVeG6ZJo= -github.com/compose-spec/compose-go/v2 v2.1.4/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.1.5 h1:6YoC9ik3NXdSYtgRn51EMZ2DxzGPyGjZ8M0B7mXTXeQ= +github.com/compose-spec/compose-go/v2 v2.1.5/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.1.4 h1:9iFHrNRSFnta1A4z6HP1MVD7vH3hEd7jvJv9wnHHJHc= github.com/containerd/accelerated-container-image v1.1.4/go.mod h1:9mpTpL4W4yAsq2giHgo4B7wTFJgE59qCPh7dZTSpGCA= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= From cc0f6437989a58a769c63bc00994d298df042c9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jul 2024 02:54:15 +0000 Subject: [PATCH 0608/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.3.0 to 0.3.1. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Changelog](https://github.com/cyphar/filepath-securejoin/blob/main/CHANGELOG.md) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.3.0...v0.3.1) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f5911aefc27..5c78d53a22f 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.7.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.3.0 + github.com/cyphar/filepath-securejoin v0.3.1 github.com/distribution/reference v0.6.0 github.com/docker/cli v27.1.1+incompatible github.com/docker/docker v27.1.1+incompatible diff --git a/go.sum b/go.sum index 3c501ee4881..10009d0bb0c 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.3.0 h1:tXpmbiaeBrS/K2US8nhgwdKYnfAOnVfkcLPKFgFHeA0= -github.com/cyphar/filepath-securejoin v0.3.0/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= +github.com/cyphar/filepath-securejoin v0.3.1 h1:1V7cHiaW+C+39wEfpH6XlLBQo3j/PciWFrgfCLS8XrE= +github.com/cyphar/filepath-securejoin v0.3.1/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= 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= From e8a993b270a66ccbdc6d65ae8cd77c03fa3a0463 Mon Sep 17 00:00:00 2001 From: xyz-li Date: Mon, 15 Jul 2024 14:21:47 +0800 Subject: [PATCH 0609/1066] fix: sort images&containers by created_at Signed-off-by: xyz-li --- cmd/nerdctl/container_list_linux_test.go | 24 ++++++++++++++++++++++++ cmd/nerdctl/image_list_test.go | 24 ++++++++++++++++++++++++ pkg/cmd/container/list.go | 12 +++++++----- pkg/cmd/image/list.go | 5 +++++ 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/cmd/nerdctl/container_list_linux_test.go b/cmd/nerdctl/container_list_linux_test.go index ea48531487c..48d442d303a 100644 --- a/cmd/nerdctl/container_list_linux_test.go +++ b/cmd/nerdctl/container_list_linux_test.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "os" + "slices" "strings" "testing" @@ -575,3 +576,26 @@ func TestContainerListWithFilter(t *testing.T) { return nil }) } + +func TestContainerListCheckCreatedTime(t *testing.T) { + base, _ := preparePsTestContainer(t, "checkCreatedTimeA", true) + preparePsTestContainer(t, "checkCreatedTimeB", true) + preparePsTestContainer(t, "checkCreatedTimeC", false) + preparePsTestContainer(t, "checkCreatedTimeD", false) + + var createdTimes []string + + base.Cmd("ps", "--format", "'{{json .CreatedAt}}'", "-a").AssertOutWithFunc(func(stdout string) error { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 4 { + return fmt.Errorf("expected at least 4 lines, got %d", len(lines)) + } + createdTimes = append(createdTimes, lines...) + return nil + }) + + slices.Reverse(createdTimes) + if !slices.IsSorted(createdTimes) { + t.Errorf("expected containers in decending order") + } +} diff --git a/cmd/nerdctl/image_list_test.go b/cmd/nerdctl/image_list_test.go index bb989137d6d..993a30eae52 100644 --- a/cmd/nerdctl/image_list_test.go +++ b/cmd/nerdctl/image_list_test.go @@ -18,6 +18,7 @@ package main import ( "fmt" + "slices" "strings" "testing" @@ -133,3 +134,26 @@ CMD ["echo", "nerdctl-build-notag-string"] base.Cmd("images", "--filter", "dangling=true").AssertOutContains("") base.Cmd("images", "--filter", "dangling=false").AssertOutNotContains("") } + +func TestImageListCheckCreatedTime(t *testing.T) { + base := testutil.NewBase(t) + + base.Cmd("pull", testutil.CommonImage).AssertOK() + base.Cmd("pull", testutil.NginxAlpineImage).AssertOK() + + var createdTimes []string + + base.Cmd("images", "--format", "'{{json .CreatedAt}}'").AssertOutWithFunc(func(stdout string) error { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 2 { + return fmt.Errorf("expected at least 4 lines, got %d", len(lines)) + } + createdTimes = append(createdTimes, lines...) + return nil + }) + + slices.Reverse(createdTimes) + if !slices.IsSorted(createdTimes) { + t.Errorf("expected images in decending order") + } +} diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index f2189c4907c..f30d73a4991 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -62,13 +62,15 @@ func filterContainers(ctx context.Context, client *containerd.Client, filters [] return nil, err } containers = filterCtx.MatchesFilters(ctx) + + sort.Slice(containers, func(i, j int) bool { + infoI, _ := containers[i].Info(ctx, containerd.WithoutRefreshedMetadata) + infoJ, _ := containers[j].Info(ctx, containerd.WithoutRefreshedMetadata) + return infoI.CreatedAt.After(infoJ.CreatedAt) + }) + if lastN > 0 { all = true - sort.Slice(containers, func(i, j int) bool { - infoI, _ := containers[i].Info(ctx, containerd.WithoutRefreshedMetadata) - infoJ, _ := containers[j].Info(ctx, containerd.WithoutRefreshedMetadata) - return infoI.CreatedAt.After(infoJ.CreatedAt) - }) if lastN < len(containers) { containers = containers[:lastN] } diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 95266e8dc18..58f030deffa 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -23,6 +23,7 @@ import ( "errors" "fmt" "io" + "sort" "strings" "text/tabwriter" "text/template" @@ -108,6 +109,10 @@ func List(ctx context.Context, client *containerd.Client, filters, nameAndRefFil imageList = imgutil.FilterImages(imageList, beforeImages, sinceImages) } + + sort.Slice(imageList, func(i, j int) bool { + return imageList[i].CreatedAt.After(imageList[j].CreatedAt) + }) return imageList, nil } From 140c5fccf151f0037f78128cfa4e793abd1930a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:53:14 +0000 Subject: [PATCH 0610/1066] build(deps): bump golangci/golangci-lint-action from 6.0.1 to 6.1.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.0.1 to 6.1.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v6.0.1...v6.1.0) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6eb1496a338..db353390d13 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v6.0.1 + uses: golangci/golangci-lint-action@v6.1.0 with: version: v1.59.1 args: --verbose From c5e06081d5e1e07af31beb72410bbf8840599300 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 29 Jul 2024 20:30:02 -0700 Subject: [PATCH 0611/1066] Remove gjson dependency Signed-off-by: apostasie --- go.mod | 3 -- go.sum | 7 ---- pkg/inspecttypes/dockercompat/dockercompat.go | 35 +++++++++---------- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index aaf2291ec97..2e7113eb9ad 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,6 @@ require ( github.com/rootless-containers/rootlesskit/v2 v2.2.0 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 - github.com/tidwall/gjson v1.17.1 github.com/vishvananda/netlink v1.2.1-beta.2 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 @@ -122,8 +121,6 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/spaolacci/murmur3 v1.1.0 // 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.1 // indirect github.com/tinylib/msgp v1.2.0 // indirect github.com/vbatts/tar-split v0.11.5 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect diff --git a/go.sum b/go.sum index 4c3172ebf39..a1e57141a6a 100644 --- a/go.sum +++ b/go.sum @@ -281,13 +281,6 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= -github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= -github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= -github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index f23d27ff2d6..88538906a3b 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -45,7 +45,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/ocihook/state" "github.com/docker/go-connections/nat" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/tidwall/gjson" ) // From https://github.com/moby/moby/blob/v26.1.2/api/types/types.go#L34-L140 @@ -502,29 +501,29 @@ type Network struct { // Scope, Driver, etc. are omitted } +type structuredCNI struct { + Name string `json:"name"` + Plugins []struct { + Ipam struct { + Ranges [][]IPAMConfig `json:"ranges"` + } `json:"ipam"` + } `json:"plugins"` +} + func NetworkFromNative(n *native.Network) (*Network, error) { var res Network - nameResult := gjson.GetBytes(n.CNI, "name") - if s, ok := nameResult.Value().(string); ok { - res.Name = s + sCNI := &structuredCNI{} + err := json.Unmarshal(n.CNI, sCNI) + if err != nil { + return nil, err } - // flatten twice to get ipamRangesResult=[{ "subnet": "10.4.19.0/24", "gateway": "10.4.19.1" }] - ipamRangesResult := gjson.GetBytes(n.CNI, "plugins.#.ipam.ranges|@flatten|@flatten") - for _, f := range ipamRangesResult.Array() { - m := f.Map() - var cfg IPAMConfig - if x, ok := m["subnet"]; ok { - cfg.Subnet = x.String() - } - if x, ok := m["gateway"]; ok { - cfg.Gateway = x.String() - } - if x, ok := m["ipRange"]; ok { - cfg.IPRange = x.String() + res.Name = sCNI.Name + for _, plugin := range sCNI.Plugins { + for _, ranges := range plugin.Ipam.Ranges { + res.IPAM.Config = append(res.IPAM.Config, ranges...) } - res.IPAM.Config = append(res.IPAM.Config, cfg) } if n.NerdctlID != nil { From b60185e80d708894ebca0b37d7fdfaf094c01258 Mon Sep 17 00:00:00 2001 From: xyz-li Date: Tue, 30 Jul 2024 11:30:01 +0800 Subject: [PATCH 0612/1066] test: increase max-size && decrease log output Signed-off-by: xyz-li --- cmd/nerdctl/container_logs_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cmd/nerdctl/container_logs_test.go b/cmd/nerdctl/container_logs_test.go index ac036e74c52..8409c1d6cae 100644 --- a/cmd/nerdctl/container_logs_test.go +++ b/cmd/nerdctl/container_logs_test.go @@ -222,22 +222,23 @@ func TestTailFollowRotateLogs(t *testing.T) { containerName := testutil.Identifier(t) const sampleJSONLog = `{"log":"A\n","stream":"stdout","time":"2024-04-11T12:01:09.800288974Z"}` - const linesPerFile = 2 + const linesPerFile = 200 defer base.Cmd("rm", "-f", containerName).Run() base.Cmd("run", "-d", "--log-driver", "json-file", "--log-opt", fmt.Sprintf("max-size=%d", len(sampleJSONLog)*linesPerFile), "--log-opt", "max-file=10", "--name", containerName, testutil.CommonImage, - "sh", "-euc", "while true; do echo A; done").AssertOK() + "sh", "-euc", "while true; do echo A; usleep 100; done").AssertOK() tailLogCmd := base.Cmd("logs", "-f", containerName) - tailLogCmd.Timeout = 10000 * time.Millisecond - tailLogs := strings.Split(strings.TrimSpace(tailLogCmd.Run().Stdout()), "\n") + tailLogCmd.Timeout = 1000 * time.Millisecond + logRun := tailLogCmd.Run() + tailLogs := strings.Split(strings.TrimSpace(logRun.Stdout()), "\n") for _, line := range tailLogs { if line != "" { assert.Equal(t, "A", line) } } - assert.Equal(t, true, len(tailLogs) > linesPerFile) + assert.Equal(t, true, len(tailLogs) > linesPerFile, logRun.Stderr()) } From 915106fc68bf0eb170db066ff4c1ccd49cf49025 Mon Sep 17 00:00:00 2001 From: Sarun Rattanasiri Date: Wed, 31 Jul 2024 02:51:43 +0700 Subject: [PATCH 0613/1066] gracefully terminate containers on nerdctl compose down Signed-off-by: Sarun Rattanasiri --- pkg/composer/down.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/composer/down.go b/pkg/composer/down.go index 70d1041365a..b20f884b6f5 100644 --- a/pkg/composer/down.go +++ b/pkg/composer/down.go @@ -40,6 +40,10 @@ func (c *Composer) Down(ctx context.Context, downOptions DownOptions) error { if err != nil { return err } + // use default Options to stop service containers. + if err := c.stopContainers(ctx, containers, StopOptions{}); err != nil { + return err + } if err := c.removeContainers(ctx, containers, RemoveOptions{Stop: true, Volumes: downOptions.RemoveVolumes}); err != nil { return err } From 3b61610c3b27684eb817b899c3241f4cd4ec8eba Mon Sep 17 00:00:00 2001 From: xyz-li Date: Sat, 6 Jul 2024 21:24:38 +0800 Subject: [PATCH 0614/1066] fix: output log after log rotation Signed-off-by: xyz-li --- go.mod | 1 + go.sum | 2 + pkg/logging/cri_logger.go | 51 ++++++++++++++++++++- pkg/logging/cri_logger_test.go | 83 ++++++++++++++++++++++++++++++++++ pkg/logging/logging.go | 44 ++++++++++++++++++ pkg/logging/logs_other.go | 34 ++++++++++++++ pkg/logging/logs_windows.go | 54 ++++++++++++++++++++++ 7 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 pkg/logging/logs_other.go create mode 100644 pkg/logging/logs_windows.go diff --git a/go.mod b/go.mod index aaf2291ec97..26a574b8255 100644 --- a/go.mod +++ b/go.mod @@ -38,6 +38,7 @@ require ( github.com/fahedouch/go-logrotate v0.2.1 github.com/fatih/color v1.17.0 github.com/fluent/fluent-logger-golang v1.9.0 + github.com/fsnotify/fsnotify v1.7.0 github.com/ipfs/go-cid v0.4.1 github.com/klauspost/compress v1.17.9 github.com/mattn/go-isatty v0.0.20 diff --git a/go.sum b/go.sum index 4c3172ebf39..8070c0ca46c 100644 --- a/go.sum +++ b/go.sum @@ -111,6 +111,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-jose/go-jose/v4 v4.0.3 h1:o8aphO8Hv6RPmH+GfzVuyf7YXSBibp+8YyHdOoDESGo= github.com/go-jose/go-jose/v4 v4.0.3/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= diff --git a/pkg/logging/cri_logger.go b/pkg/logging/cri_logger.go index c3c3b35efc3..eada94c6add 100644 --- a/pkg/logging/cri_logger.go +++ b/pkg/logging/cri_logger.go @@ -25,6 +25,7 @@ package logging import ( "bufio" "bytes" + "context" "errors" "fmt" "io" @@ -35,6 +36,7 @@ import ( "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/logging/tail" + "github.com/fsnotify/fsnotify" ) // LogStreamType is the type of the stream in CRI container log. @@ -45,6 +47,9 @@ const ( Stdout LogStreamType = "stdout" // Stderr is the stream type for stderr. Stderr LogStreamType = "stderr" + + // logForceCheckPeriod is the period to check for a new read + logForceCheckPeriod = 1 * time.Second ) // LogTag is the tag of a log line in CRI container log. @@ -89,7 +94,9 @@ func ReadLogs(opts *LogViewOptions, stdout, stderr io.Writer, stopChannel chan o if err != nil { return fmt.Errorf("failed to open log file %q: %v", logPath, err) } - defer f.Close() + defer func() { + f.Close() + }() // Search start point based on tail line. start, err := tail.FindTailLineStartIndex(f, opts.Tail) @@ -101,6 +108,8 @@ func ReadLogs(opts *LogViewOptions, stdout, stderr io.Writer, stopChannel chan o return fmt.Errorf("failed to seek in log file %q: %v", logPath, err) } + var watcher *fsnotify.Watcher + limitedMode := (opts.Tail > 0) && (!opts.Follow) limitedNum := opts.Tail // Start parsing the logs. @@ -110,6 +119,9 @@ func ReadLogs(opts *LogViewOptions, stdout, stderr io.Writer, stopChannel chan o isNewLine := true writer := newLogWriter(stdout, stderr, opts) msg := &logMessage{} + baseName := filepath.Base(logPath) + dir := filepath.Dir(logPath) + for { select { case <-stopChannel: @@ -126,13 +138,48 @@ func ReadLogs(opts *LogViewOptions, stdout, stderr io.Writer, stopChannel chan o return fmt.Errorf("failed to read log file %q: %v", logPath, err) } if opts.Follow { - // Reset seek so that if this is an incomplete line, // it will be read again. if _, err := f.Seek(-int64(len(l)), io.SeekCurrent); err != nil { return fmt.Errorf("failed to reset seek in log file %q: %v", logPath, err) } + if watcher == nil { + // Initialize the watcher if it has not been initialized yet. + if watcher, err = NewLogFileWatcher(dir); err != nil { + return err + } + defer watcher.Close() + // If we just created the watcher, try again to read as we might have missed + // the event. + continue + } + + var recreated bool + // Wait until the next log change. + recreated, err = startTail(context.Background(), baseName, watcher) + if err != nil { + return err + } + if recreated { + newF, err := openFileShareDelete(logPath) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + //If the user application outputs logs too quickly, + //There is a slight possibility that nerdctl has just rotated the log file, + //try opening it once more. + time.Sleep(10 * time.Millisecond) + } + newF, err = openFileShareDelete(logPath) + if err != nil { + return fmt.Errorf("failed to open cri logfile %q: %w", logPath, err) + } + } + f.Close() + f = newF + r = bufio.NewReader(f) + } + // If the container exited consume data until the next EOF continue } diff --git a/pkg/logging/cri_logger_test.go b/pkg/logging/cri_logger_test.go index 3788a3c706b..c8207d3c341 100644 --- a/pkg/logging/cri_logger_test.go +++ b/pkg/logging/cri_logger_test.go @@ -28,6 +28,7 @@ import ( "fmt" "io" "os" + "path/filepath" "reflect" "testing" "time" @@ -230,3 +231,85 @@ func TestReadLogsLimitsWithTimestamps(t *testing.T) { t.Errorf("should have two lines, lineCount= %d", lineCount) } } + +func TestReadRotatedLog(t *testing.T) { + tmpDir := t.TempDir() + file, err := os.CreateTemp(tmpDir, "logfile") + if err != nil { + t.Errorf("unable to create temp file, error: %s", err.Error()) + } + stdoutBuf := &bytes.Buffer{} + stderrBuf := &bytes.Buffer{} + containerStoped := make(chan os.Signal) + // Start to follow the container's log. + fileName := file.Name() + go func() { + lvOpts := &LogViewOptions{ + Follow: true, + LogPath: fileName, + } + _ = ReadLogs(lvOpts, stdoutBuf, stderrBuf, containerStoped) + }() + + // log in stdout + expectedStdout := "line0line2line4line6line8" + // log in stderr + expectedStderr := "line1line3line5line7line9" + + dir := filepath.Dir(file.Name()) + baseName := filepath.Base(file.Name()) + + // Write 10 lines to log file. + // Let ReadLogs start. + time.Sleep(50 * time.Millisecond) + + for line := 0; line < 10; line++ { + // Write the first three lines to log file + now := time.Now().Format(time.RFC3339Nano) + if line%2 == 0 { + file.WriteString(fmt.Sprintf( + "%s stdout P line%d\n", now, line)) + } else { + file.WriteString(fmt.Sprintf( + "%s stderr P line%d\n", now, line)) + } + + time.Sleep(1 * time.Millisecond) + + if line == 5 { + file.Close() + // Pretend to rotate the log. + rotatedName := fmt.Sprintf("%s.%s", baseName, time.Now().Format("220060102-150405")) + rotatedName = filepath.Join(dir, rotatedName) + if err := os.Rename(filepath.Join(dir, baseName), rotatedName); err != nil { + t.Errorf("failed to rotate log %q to %q, error: %s", file.Name(), rotatedName, err.Error()) + return + } + + time.Sleep(20 * time.Millisecond) + newF := filepath.Join(dir, baseName) + if file, err = os.Create(newF); err != nil { + t.Errorf("unable to create new log file, error: %s", err.Error()) + return + } + } + } + + // Finished writing into the file, close it, so we can delete it later. + err = file.Close() + if err != nil { + t.Errorf("could not close file, error: %s", err.Error()) + } + + time.Sleep(2 * time.Second) + // Make the function ReadLogs end. + close(containerStoped) + + if expectedStdout != stdoutBuf.String() { + t.Errorf("expected: %s, acoutal: %s", expectedStdout, stdoutBuf.String()) + } + + if expectedStderr != stderrBuf.String() { + t.Errorf("expected: %s, acoutal: %s", expectedStderr, stderrBuf.String()) + } +} diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index c89dbd6085c..3644d8b79a6 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -27,10 +27,12 @@ import ( "path/filepath" "sort" "sync" + "time" "github.com/containerd/containerd/runtime/v2/logging" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/fsnotify/fsnotify" "github.com/muesli/cancelreader" ) @@ -217,3 +219,45 @@ func loggerFunc(dataStore string) (logging.LoggerFunc, error) { return nil }, nil } + +func NewLogFileWatcher(dir string) (*fsnotify.Watcher, error) { + watcher, err := fsnotify.NewWatcher() + if err != nil { + return nil, fmt.Errorf("failed to create fsnotify watcher: %v", err) + } + if err = watcher.Add(dir); err != nil { + watcher.Close() + return nil, fmt.Errorf("failed to watch directory %q: %w", dir, err) + } + return watcher, nil +} + +// startTail wait for the next log write. +// the boolean value indicates if the log file was recreated; +// the error is error happens during waiting new logs. +func startTail(ctx context.Context, logName string, w *fsnotify.Watcher) (bool, error) { + errRetry := 5 + for { + select { + case <-ctx.Done(): + return false, fmt.Errorf("context cancelled") + case e := <-w.Events: + switch { + case e.Has(fsnotify.Write): + return false, nil + case e.Has(fsnotify.Create): + return filepath.Base(e.Name) == logName, nil + default: + log.L.Debugf("Received unexpected fsnotify event: %v, retrying", e) + } + case err := <-w.Errors: + log.L.Debugf("Received fsnotify watch error, retrying unless no more retries left, retries: %d, error: %s", errRetry, err) + if errRetry == 0 { + return false, err + } + errRetry-- + case <-time.After(logForceCheckPeriod): + return false, nil + } + } +} diff --git a/pkg/logging/logs_other.go b/pkg/logging/logs_other.go new file mode 100644 index 00000000000..6270efbe0fe --- /dev/null +++ b/pkg/logging/logs_other.go @@ -0,0 +1,34 @@ +//go:build !windows +// +build !windows + +/* + 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. +*/ + +/* +Forked from https://github.com/kubernetes/kubernetes/blob/cc60b26dee4768e3c5aa0515bbf4ba1824ad38dc/staging/src/k8s.io/cri-client/pkg/logs/logs_other.go +Copyright The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 +*/ +package logging + +import ( + "os" +) + +func openFileShareDelete(path string) (*os.File, error) { + // Noop. Only relevant for Windows. + return os.Open(path) +} diff --git a/pkg/logging/logs_windows.go b/pkg/logging/logs_windows.go new file mode 100644 index 00000000000..262ac0c2d42 --- /dev/null +++ b/pkg/logging/logs_windows.go @@ -0,0 +1,54 @@ +//go:build windows +// +build windows + +/* + 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. +*/ + +/* +Forked from https://github.com/kubernetes/kubernetes/blob/cc60b26dee4768e3c5aa0515bbf4ba1824ad38dc/staging/src/k8s.io/cri-client/pkg/logs/logs_windows.go +Copyright The Kubernetes Authors. +Licensed under the Apache License, Version 2.0 +*/ +package logging + +import ( + "os" + "syscall" +) + +// Based on Windows implementation of Windows' syscall.Open +// https://cs.opensource.google/go/go/+/refs/tags/go1.22.2:src/syscall/syscall_windows.go;l=342 +// In addition to syscall.Open, this function also adds the syscall.FILE_SHARE_DELETE flag to sharemode, +// which will allow us to read from the file without blocking the file from being deleted or renamed. +// This is essential for Log Rotation which is done by renaming the open file. Without this, the file rename would fail. +func openFileShareDelete(path string) (*os.File, error) { + pathp, err := syscall.UTF16PtrFromString(path) + if err != nil { + return nil, err + } + + var access uint32 = syscall.GENERIC_READ + var sharemode uint32 = syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE | syscall.FILE_SHARE_DELETE + var createmode uint32 = syscall.OPEN_EXISTING + var attrs uint32 = syscall.FILE_ATTRIBUTE_NORMAL + + handle, err := syscall.CreateFile(pathp, access, sharemode, nil, createmode, attrs, 0) + if err != nil { + return nil, err + } + + return os.NewFile(uintptr(handle), path), nil +} From 4b50583d988eac08ca7a4cf84cd21a921fb6be4f Mon Sep 17 00:00:00 2001 From: xyz-li Date: Fri, 12 Jul 2024 15:03:23 +0800 Subject: [PATCH 0615/1066] feat: tail JSON log Signed-off-by: xyz-li --- pkg/logging/json_logger.go | 187 ++++++++++++++----------------- pkg/logging/json_logger_test.go | 173 ++++++++++++++++++++++++++++ pkg/logging/jsonfile/jsonfile.go | 50 ++------- 3 files changed, 267 insertions(+), 143 deletions(-) create mode 100644 pkg/logging/json_logger_test.go diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index defd6e8174d..f76c053bca4 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -17,24 +17,24 @@ package logging import ( - "bufio" + "context" "errors" "fmt" "io" "os" - "os/exec" "path/filepath" "strconv" - "strings" "time" "github.com/containerd/containerd/runtime/v2/logging" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/logging/jsonfile" + "github.com/containerd/nerdctl/v2/pkg/logging/tail" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/docker/go-units" "github.com/fahedouch/go-logrotate" + "github.com/fsnotify/fsnotify" ) var JSONDriverLogOpts = []string{ @@ -142,9 +142,6 @@ func viewLogsJSONFile(lvopts LogViewOptions, stdout, stderr io.Writer, stopChann } } - if checkExecutableAvailableInPath("tail") { - return viewLogsJSONFileThroughTailExec(lvopts, logFilePath, stdout, stderr, stopChannel) - } return viewLogsJSONFileDirect(lvopts, logFilePath, stdout, stderr, stopChannel) } @@ -156,118 +153,100 @@ func viewLogsJSONFileDirect(lvopts LogViewOptions, jsonLogFilePath string, stdou if err != nil { return err } - defer fin.Close() - err = jsonfile.Decode(stdout, stderr, fin, lvopts.Timestamps, lvopts.Since, lvopts.Until, lvopts.Tail) - if err != nil { - return fmt.Errorf("error occurred while doing initial read of JSON logfile %q: %s", jsonLogFilePath, err) - } + defer func() { fin.Close() }() - if lvopts.Follow { - // Get the current file handler's seek. - lastPos, err := fin.Seek(0, io.SeekCurrent) - if err != nil { - return fmt.Errorf("error occurred while trying to seek JSON logfile %q at position %d: %s", jsonLogFilePath, lastPos, err) - } - fin.Close() - for { - select { - case <-stopChannel: - log.L.Debugf("received stop signal while re-reading JSON logfile, returning") + // Search start point based on tail line. + start, err := tail.FindTailLineStartIndex(fin, lvopts.Tail) + if err != nil { + return fmt.Errorf("failed to tail %d lines of JSON logfile %q: %w", lvopts.Tail, jsonLogFilePath, err) + } + + if _, err := fin.Seek(start, io.SeekStart); err != nil { + return fmt.Errorf("failed to seek in log file %q from %d position: %w", jsonLogFilePath, start, err) + } + + limitedMode := (lvopts.Tail > 0) && (!lvopts.Follow) + limitedNum := lvopts.Tail + var stop bool + var watcher *fsnotify.Watcher + baseName := filepath.Base(jsonLogFilePath) + dir := filepath.Dir(jsonLogFilePath) + retryTimes := 2 + backBytes := 0 + + for { + select { + case <-stopChannel: + log.L.Debug("received stop signal while re-reading JSON logfile, returning") + return nil + default: + if stop || (limitedMode && limitedNum == 0) { + log.L.Debugf("finished parsing log JSON filefile, path: %s", jsonLogFilePath) return nil - default: - // Re-open the file and seek to the last-consumed offset. - fin, err = os.OpenFile(jsonLogFilePath, os.O_RDONLY, 0400) - if err != nil { - fin.Close() - return fmt.Errorf("error occurred while trying to re-open JSON logfile %q: %s", jsonLogFilePath, err) + } + + if line, err := jsonfile.Decode(stdout, stderr, fin, lvopts.Timestamps, lvopts.Since, lvopts.Until); err != nil { + if len(line) > 0 { + time.Sleep(5 * time.Millisecond) + if retryTimes == 0 { + log.L.Infof("finished parsing log JSON filefile, path: %s, line: %s", jsonLogFilePath, string(line)) + return fmt.Errorf("error occurred while doing read of JSON logfile %q: %s, retryTimes: %d", jsonLogFilePath, err, retryTimes) + } + retryTimes-- + backBytes = len(line) + } else { + return fmt.Errorf("error occurred while doing read of JSON logfile %q: %s", jsonLogFilePath, err) } - _, err = fin.Seek(lastPos, 0) + } else { + retryTimes = 2 + backBytes = 0 + } + + if lvopts.Follow { + // Get the current file handler's seek. + lastPos, err := fin.Seek(int64(-backBytes), io.SeekCurrent) if err != nil { - fin.Close() return fmt.Errorf("error occurred while trying to seek JSON logfile %q at position %d: %s", jsonLogFilePath, lastPos, err) } - err = jsonfile.Decode(stdout, stderr, fin, lvopts.Timestamps, lvopts.Since, lvopts.Until, 0) - if err != nil { - fin.Close() - return fmt.Errorf("error occurred while doing follow-up decoding of JSON logfile %q at starting position %d: %s", jsonLogFilePath, lastPos, err) + if watcher == nil { + // Initialize the watcher if it has not been initialized yet. + if watcher, err = NewLogFileWatcher(dir); err != nil { + return err + } + defer watcher.Close() + // If we just created the watcher, try again to read as we might have missed + // the event. + continue } - // Record current file seek position before looping again. - lastPos, err = fin.Seek(0, io.SeekCurrent) + var recreated bool + // Wait until the next log change. + recreated, err = startTail(context.Background(), baseName, watcher) if err != nil { + return err + } + if recreated { + newF, err := openFileShareDelete(jsonLogFilePath) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + //If the user application outputs logs too quickly, + //There is a slight possibility that nerdctl has just rotated the log file, + //try opening it once more. + time.Sleep(10 * time.Millisecond) + } + newF, err = openFileShareDelete(jsonLogFilePath) + if err != nil { + return fmt.Errorf("failed to open JSON logfile %q: %w", jsonLogFilePath, err) + } + } fin.Close() - return fmt.Errorf("error occurred while trying to seek JSON logfile %q at current position: %s", jsonLogFilePath, err) + fin = newF } - fin.Close() + continue } + stop = true // Give the OS a second to breathe before re-opening the file: - time.Sleep(time.Second) - } - } - return nil -} - -// Loads logs through the `tail` executable. -func viewLogsJSONFileThroughTailExec(lvopts LogViewOptions, jsonLogFilePath string, stdout, stderr io.Writer, stopChannel chan os.Signal) error { - var args []string - - args = append(args, "-n") - if lvopts.Tail == 0 { - args = append(args, "+0") - } else { - args = append(args, strconv.FormatUint(uint64(lvopts.Tail), 10)) - } - - if lvopts.Follow { - // using the `-F` to follow the file name instead of descriptor and retry if inaccessible - args = append(args, "-F") - } - args = append(args, jsonLogFilePath) - cmd := exec.Command("tail", args...) - - cmdStdout, err := cmd.StdoutPipe() - if err != nil { - return err - } - - cmdStderr, err := cmd.StderrPipe() - if err != nil { - return err - } - - if err := cmd.Start(); err != nil { - return err - } - - // filter the unwanted error message of the tail - go filterTailStderr(cmdStderr) - - // Setup killing goroutine: - go func() { - <-stopChannel - log.L.Debugf("killing tail logs process with PID: %d", cmd.Process.Pid) - cmd.Process.Kill() - }() - - return jsonfile.Decode(stdout, stderr, cmdStdout, lvopts.Timestamps, lvopts.Since, lvopts.Until, 0) -} - -func filterTailStderr(reader io.Reader) error { - scanner := bufio.NewScanner(reader) - for scanner.Scan() { - line := scanner.Text() - if strings.HasSuffix(line, "has appeared; following new file") || - strings.HasSuffix(line, "has become inaccessible: No such file or directory") || - strings.HasSuffix(line, "has been replaced; following new file") || - strings.HasSuffix(line, ": No such file or directory") { - continue } - fmt.Fprintln(os.Stderr, line) } - - if err := scanner.Err(); err != nil { - return err - } - return nil } diff --git a/pkg/logging/json_logger_test.go b/pkg/logging/json_logger_test.go new file mode 100644 index 00000000000..76014d761df --- /dev/null +++ b/pkg/logging/json_logger_test.go @@ -0,0 +1,173 @@ +/* + 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 logging + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "path/filepath" + "testing" + "time" +) + +func TestReadRotatedJSONLog(t *testing.T) { + tmpDir := t.TempDir() + file, err := os.CreateTemp(tmpDir, "logfile") + if err != nil { + t.Errorf("unable to create temp file, error: %s", err.Error()) + } + stdoutBuf := &bytes.Buffer{} + stderrBuf := &bytes.Buffer{} + containerStopped := make(chan os.Signal) + // Start to follow the container's log. + fileName := file.Name() + go func() { + lvOpts := LogViewOptions{ + Follow: true, + LogPath: fileName, + } + viewLogsJSONFileDirect(lvOpts, file.Name(), stdoutBuf, stderrBuf, containerStopped) + }() + + // log in stdout + expectedStdout := "line0\nline1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\n" + dir := filepath.Dir(file.Name()) + baseName := filepath.Base(file.Name()) + + // Write 10 lines to log file. + // Let ReadLogs start. + time.Sleep(50 * time.Millisecond) + + type logContent struct { + Log string `json:"log"` + Stream string `json:"stream"` + Time string `json:"time"` + } + + for line := 0; line < 10; line++ { + // Write the first three lines to log file + log := logContent{} + log.Log = fmt.Sprintf("line%d\n", line) + log.Stream = "stdout" + log.Time = time.Now().Format(time.RFC3339Nano) + time.Sleep(1 * time.Millisecond) + logData, _ := json.Marshal(log) + file.Write(logData) + + if line == 5 { + file.Close() + // Pretend to rotate the log. + rotatedName := fmt.Sprintf("%s.%s", baseName, time.Now().Format("20060102-150405")) + rotatedName = filepath.Join(dir, rotatedName) + if err := os.Rename(filepath.Join(dir, baseName), rotatedName); err != nil { + t.Errorf("failed to rotate log %q to %q, error: %s", file.Name(), rotatedName, err.Error()) + return + } + + time.Sleep(20 * time.Millisecond) + newF := filepath.Join(dir, baseName) + if file, err = os.Create(newF); err != nil { + t.Errorf("unable to create new log file, error: %s", err.Error()) + return + } + } + } + + // Finished writing into the file, close it, so we can delete it later. + err = file.Close() + if err != nil { + t.Errorf("could not close file, error: %s", err.Error()) + } + + time.Sleep(2 * time.Second) + // Make the function ReadLogs end. + close(containerStopped) + + if expectedStdout != stdoutBuf.String() { + t.Errorf("expected: %s, acoutal: %s", expectedStdout, stdoutBuf.String()) + } +} + +func TestReadJSONLogs(t *testing.T) { + file, err := os.CreateTemp("", "TestFollowLogs") + if err != nil { + t.Fatalf("unable to create temp file") + } + defer os.Remove(file.Name()) + file.WriteString(`{"log":"line1\n","stream":"stdout","time":"2024-07-12T03:09:24.916296732Z"}` + "\n") + file.WriteString(`{"log":"line2\n","stream":"stdout","time":"2024-07-12T03:09:24.916296732Z"}` + "\n") + file.WriteString(`{"log":"line3\n","stream":"stdout","time":"2024-07-12T03:09:24.916296732Z"}` + "\n") + + stopChan := make(chan os.Signal) + testCases := []struct { + name string + logViewOptions LogViewOptions + expected string + }{ + { + name: "default log options should output all lines", + logViewOptions: LogViewOptions{ + LogPath: file.Name(), + Tail: 0, + }, + expected: "line1\nline2\nline3\n", + }, + { + name: "using Tail 2 should output last 2 lines", + logViewOptions: LogViewOptions{ + LogPath: file.Name(), + Tail: 2, + }, + expected: "line2\nline3\n", + }, + { + name: "using Tail 4 should output all lines when the log has less than 4 lines", + logViewOptions: LogViewOptions{ + LogPath: file.Name(), + Tail: 4, + }, + expected: "line1\nline2\nline3\n", + }, + { + name: "using Tail 0 should output all", + logViewOptions: LogViewOptions{ + LogPath: file.Name(), + Tail: 0, + }, + expected: "line1\nline2\nline3\n", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + stdoutBuf := bytes.NewBuffer(nil) + stderrBuf := bytes.NewBuffer(nil) + err = viewLogsJSONFileDirect(tc.logViewOptions, file.Name(), stdoutBuf, stderrBuf, stopChan) + + if err != nil { + t.Fatalf(err.Error()) + } + if stderrBuf.Len() > 0 { + t.Fatalf("Stderr: %v", stderrBuf.String()) + } + if actual := stdoutBuf.String(); tc.expected != actual { + t.Fatalf("Actual output does not match expected.\nActual: %v\nExpected: %v\n", actual, tc.expected) + } + }) + } +} diff --git a/pkg/logging/jsonfile/jsonfile.go b/pkg/logging/jsonfile/jsonfile.go index cb951534281..eebcff7cd96 100644 --- a/pkg/logging/jsonfile/jsonfile.go +++ b/pkg/logging/jsonfile/jsonfile.go @@ -17,7 +17,6 @@ package jsonfile import ( - "container/ring" "encoding/json" "fmt" "io" @@ -128,12 +127,7 @@ func writeEntry(e *Entry, stdout, stderr io.Writer, refTime time.Time, timestamp return nil } -func Decode(stdout, stderr io.Writer, r io.Reader, timestamps bool, since string, until string, tail uint) error { - var buff *ring.Ring - if tail != 0 { - buff = ring.New(int(tail)) - } - +func Decode(stdout, stderr io.Writer, r io.Reader, timestamps bool, since string, until string) ([]byte, error) { dec := json.NewDecoder(r) now := time.Now() for { @@ -141,41 +135,19 @@ func Decode(stdout, stderr io.Writer, r io.Reader, timestamps bool, since string if err := dec.Decode(&e); err == io.EOF { break } else if err != nil { - return err - } - - if buff == nil { - // Write out the entry directly - err := writeEntry(&e, stdout, stderr, now, timestamps, since, until) + line, err := io.ReadAll(dec.Buffered()) if err != nil { - log.L.Errorf("error while writing log entry to output stream: %s", err) + return nil, err } - } else { - // Else place the entry in a ring buffer - buff.Value = &e - buff = buff.Next() + return line, err } - } - if buff != nil { - // The ring should now contain up to `tail` elements and be set to - // internally point to the oldest element in the ring. - buff.Do(func(e interface{}) { - if e == nil { - // unallocated ring element - return - } - cast, ok := e.(*Entry) - if !ok { - log.L.Errorf("failed to cast Entry struct: %#v", e) - return - } - - err := writeEntry(cast, stdout, stderr, now, timestamps, since, until) - if err != nil { - log.L.Errorf("error while writing log entry to output stream: %s", err) - } - }) + // Write out the entry directly + err := writeEntry(&e, stdout, stderr, now, timestamps, since, until) + if err != nil { + log.L.Errorf("error while writing log entry to output stream: %s", err) + } } - return nil + + return nil, nil } From 4d3f6988380ef196b7be38f64eb026b07b72155d Mon Sep 17 00:00:00 2001 From: David Son Date: Wed, 31 Jul 2024 22:13:50 +0000 Subject: [PATCH 0616/1066] Add SOCI handler wrapper As part of upgrading nerdctl to containerd v2, we must update dependencies to depend on v2 as well. As SOCI maintainers do not wish to upgrade to containerd v2 yet, this is a workaround to avoid depending on SOCI library. We can revert this change if we wish once SOCI updates to containerd v2. Signed-off-by: David Son --- go.mod | 2 +- go.sum | 2 - pkg/imgutil/snapshotter.go | 4 +- pkg/snapshotterutil/socisource.go | 110 ++++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 pkg/snapshotterutil/socisource.go diff --git a/go.mod b/go.mod index 2e7113eb9ad..f5bfb9bd3fc 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.5 - github.com/awslabs/soci-snapshotter v0.7.0 github.com/compose-spec/compose-go/v2 v2.1.5 github.com/containerd/accelerated-container-image v1.1.4 github.com/containerd/cgroups/v3 v3.0.3 @@ -118,6 +117,7 @@ require ( github.com/pelletier/go-toml v1.9.5 // indirect github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/procfs v0.12.0 // 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-20230803200340-78284954bff6 // indirect diff --git a/go.sum b/go.sum index a1e57141a6a..04b3fcbe470 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,6 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.5 h1:bpTInLlDy/nDRWFVcefDZZ1+U8tS+rz3MxjKgu9boo0= github.com/Microsoft/hcsshim v0.12.5/go.mod h1:tIUGego4G1EN5Hb6KC90aDYiUI2dqLSTTOCjVNpOgZ8= -github.com/awslabs/soci-snapshotter v0.7.0 h1:p8hKjVNlT3Z8W0ZcsdCjJ5A3qUgD4A0zv6qHrcKjKEg= -github.com/awslabs/soci-snapshotter v0.7.0/go.mod h1:o4LaCms6epXbSpYXcd49a+3QmdjsQAPpKywpp0Ls3TE= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= diff --git a/pkg/imgutil/snapshotter.go b/pkg/imgutil/snapshotter.go index 9fd30e72f8c..0c787767eea 100644 --- a/pkg/imgutil/snapshotter.go +++ b/pkg/imgutil/snapshotter.go @@ -19,13 +19,13 @@ package imgutil import ( "strings" - socisource "github.com/awslabs/soci-snapshotter/fs/source" "github.com/containerd/containerd" "github.com/containerd/containerd/images" ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" + "github.com/containerd/nerdctl/v2/pkg/snapshotterutil" "github.com/containerd/stargz-snapshotter/fs/source" ) @@ -115,5 +115,5 @@ func stargzExtraLabels(f func(images.Handler) images.Handler, rFlags types.Remot } func sociExtraLabels(f func(images.Handler) images.Handler, rFlags types.RemoteSnapshotterFlags) func(images.Handler) images.Handler { - return socisource.AppendDefaultLabelsHandlerWrapper(rFlags.SociIndexDigest, f) + return snapshotterutil.SociAppendDefaultLabelsHandlerWrapper(rFlags.SociIndexDigest, f) } diff --git a/pkg/snapshotterutil/socisource.go b/pkg/snapshotterutil/socisource.go new file mode 100644 index 00000000000..85088388d90 --- /dev/null +++ b/pkg/snapshotterutil/socisource.go @@ -0,0 +1,110 @@ +/* + 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. +*/ + +/* + Copyright The Soci Snapshotter 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. +*/ + +// Taken from https://github.com/awslabs/soci-snapshotter/blob/237fc956b8366e49927c84fcfee9a2defbb8f53c/fs/source/source.go +// to avoid taking dependency, as maintainers do not wish to upgrade to containerd v2 yet. + +package snapshotterutil + +import ( + "context" + "fmt" + "strings" + + "github.com/containerd/containerd/images" + "github.com/containerd/containerd/labels" + ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" +) + +const ( + // TargetSizeLabel is a label which contains layer size. + TargetSizeLabel = "containerd.io/snapshot/remote/soci.size" + + // targetImageLayersSizeLabel is a label which contains layer sizes contained in + // the target image. + targetImageLayersSizeLabel = "containerd.io/snapshot/remote/image.layers.size" + + // TargetSociIndexDigestLabel is a label which contains the digest of the soci index. + TargetSociIndexDigestLabel = "containerd.io/snapshot/remote/soci.index.digest" +) + +// SociAppendDefaultLabelsHandlerWrapper makes a handler which appends image's basic +// information to each layer descriptor as annotations during unpack. These +// annotations will be passed to this remote snapshotter as labels and used to +// construct source information. +func SociAppendDefaultLabelsHandlerWrapper(indexDigest string, wrapper func(images.Handler) images.Handler) func(f images.Handler) images.Handler { + return func(f images.Handler) images.Handler { + return images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { + children, err := wrapper(f).Handle(ctx, desc) + if err != nil { + return nil, err + } + switch desc.MediaType { + case ocispec.MediaTypeImageManifest, images.MediaTypeDockerSchema2Manifest: + for i := range children { + c := &children[i] + if images.IsLayerType(c.MediaType) { + if c.Annotations == nil { + c.Annotations = make(map[string]string) + } + + c.Annotations[TargetSizeLabel] = fmt.Sprintf("%d", c.Size) + c.Annotations[TargetSociIndexDigestLabel] = indexDigest + + remainingLayerDigestsCount := len(strings.Split(c.Annotations[ctdsnapshotters.TargetImageLayersLabel], ",")) + + var layerSizes string + /* + We must ensure that the counts of layer sizes and layer digests are equal. + We will limit the # of neighboring label sizes to equal the # of neighboring + layer digests for any given layer. + */ + for _, l := range children[i : i+remainingLayerDigestsCount] { + if images.IsLayerType(l.MediaType) { + ls := fmt.Sprintf("%d,", l.Size) + // This avoids the label hits the size limitation. + // Skipping layers is allowed here and only affects performance. + if err := labels.Validate(targetImageLayersSizeLabel, layerSizes+ls); err != nil { + break + } + layerSizes += ls + } + } + c.Annotations[targetImageLayersSizeLabel] = strings.TrimSuffix(layerSizes, ",") + } + } + } + return children, nil + }) + } +} From c6c7e132712e73cb14ff41e075319741cf11496d Mon Sep 17 00:00:00 2001 From: yy Date: Fri, 2 Aug 2024 10:33:43 +0800 Subject: [PATCH 0617/1066] add unpack commit images. Signed-off-by: yy --- pkg/imgutil/commit/commit.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index 9d43cb31a3e..0320d95e895 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -169,6 +169,13 @@ func Commit(ctx context.Context, client *containerd.Client, container containerd return emptyDigest, fmt.Errorf("failed to create new image %s: %w", opts.Ref, err) } } + + // unpack the image to snapshotter + cimg := containerd.NewImage(client, img) + if err := cimg.Unpack(ctx, snName); err != nil { + return emptyDigest, err + } + return configDigest, nil } From 99fdb17f044ae55a2645f0ba4bae7f6da7b2bdcb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 22:13:06 +0000 Subject: [PATCH 0618/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.13.13 to 0.14.0. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.13.13...v0.14.0) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2e7113eb9ad..74f6eb25855 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/containerd/go-cni v1.1.10 github.com/containerd/imgcrypt v1.1.11 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.13.13 + github.com/containerd/nydus-snapshotter v0.14.0 github.com/containerd/platforms v0.2.1 github.com/containerd/stargz-snapshotter v0.15.1 github.com/containerd/stargz-snapshotter/estargz v0.15.1 diff --git a/go.sum b/go.sum index a1e57141a6a..8f65bdce04b 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,8 @@ github.com/containerd/imgcrypt v1.1.11 h1:3RULIeLouE7B5l9NzMq0HdPWG0DP5deEVxB5UK github.com/containerd/imgcrypt v1.1.11/go.mod h1:nXL4jp1GrtO758b16DVsxaHHzu9PravAsKARYmyHR58= 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.13 h1:4eCKSNjmozLQ038G2a3X8DEwmrsHsRPMdVGX+zjcaTc= -github.com/containerd/nydus-snapshotter v0.13.13/go.mod h1:VPVKQ3jmHFIcUIV2yiQ1kImZuBFS3GXDohKs9mRABVE= +github.com/containerd/nydus-snapshotter v0.14.0 h1:6/eAi6d7MjaeLLuMO8Udfe5GVsDudmrDNO4SGETMBco= +github.com/containerd/nydus-snapshotter v0.14.0/go.mod h1:TT4jv2SnIDxEBu4H2YOvWQHPOap031ydTaHTuvc5VQk= 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= From 56791faa8b4f79ec8bcd81aa629245c05368b17e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 22:39:02 +0000 Subject: [PATCH 0619/1066] build(deps): bump the golang-x group with 2 updates Bumps the golang-x group with 2 updates: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys). Updates `golang.org/x/sync` from 0.7.0 to 0.8.0 - [Commits](https://github.com/golang/sync/compare/v0.7.0...v0.8.0) Updates `golang.org/x/sys` from 0.22.0 to 0.23.0 - [Commits](https://github.com/golang/sys/compare/v0.22.0...v0.23.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index db415b812c7..900c9f75c38 100644 --- a/go.mod +++ b/go.mod @@ -60,8 +60,8 @@ require ( go.uber.org/mock v0.4.0 golang.org/x/crypto v0.25.0 golang.org/x/net v0.27.0 - golang.org/x/sync v0.7.0 - golang.org/x/sys v0.22.0 + golang.org/x/sync v0.8.0 + golang.org/x/sys v0.23.0 golang.org/x/term v0.22.0 golang.org/x/text v0.16.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 6b78e08a4d5..1faab005720 100644 --- a/go.sum +++ b/go.sum @@ -347,8 +347,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -363,8 +363,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 93dfdaabfde394859b5f74b070733de758d37529 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 22:21:38 +0000 Subject: [PATCH 0620/1066] build(deps): bump the golang-x group with 4 updates Bumps the golang-x group with 4 updates: [golang.org/x/crypto](https://github.com/golang/crypto), [golang.org/x/net](https://github.com/golang/net), [golang.org/x/term](https://github.com/golang/term) and [golang.org/x/text](https://github.com/golang/text). Updates `golang.org/x/crypto` from 0.25.0 to 0.26.0 - [Commits](https://github.com/golang/crypto/compare/v0.25.0...v0.26.0) Updates `golang.org/x/net` from 0.27.0 to 0.28.0 - [Commits](https://github.com/golang/net/compare/v0.27.0...v0.28.0) Updates `golang.org/x/term` from 0.22.0 to 0.23.0 - [Commits](https://github.com/golang/term/compare/v0.22.0...v0.23.0) Updates `golang.org/x/text` from 0.16.0 to 0.17.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.16.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 900c9f75c38..b2072df7c81 100644 --- a/go.mod +++ b/go.mod @@ -58,12 +58,12 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.25.0 - golang.org/x/net v0.27.0 + golang.org/x/crypto v0.26.0 + golang.org/x/net v0.28.0 golang.org/x/sync v0.8.0 golang.org/x/sys v0.23.0 - golang.org/x/term v0.22.0 - golang.org/x/text v0.16.0 + golang.org/x/term v0.23.0 + golang.org/x/text v0.17.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) diff --git a/go.sum b/go.sum index 1faab005720..0c666e98302 100644 --- a/go.sum +++ b/go.sum @@ -320,8 +320,8 @@ go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= @@ -339,8 +339,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -365,12 +365,12 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From 7df0fbd6a6093a0eff589a899f83cc579c638f19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 22:21:49 +0000 Subject: [PATCH 0621/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.1.5 to 2.1.6. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.1.5...v2.1.6) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 900c9f75c38..ce62ae34448 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.5 - github.com/compose-spec/compose-go/v2 v2.1.5 + github.com/compose-spec/compose-go/v2 v2.1.6 github.com/containerd/accelerated-container-image v1.1.4 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index 1faab005720..f441eeeace5 100644 --- a/go.sum +++ b/go.sum @@ -21,8 +21,8 @@ github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk= github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.1.5 h1:6YoC9ik3NXdSYtgRn51EMZ2DxzGPyGjZ8M0B7mXTXeQ= -github.com/compose-spec/compose-go/v2 v2.1.5/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.1.6 h1:d0Cs0DffmOwmSzs0YPHwKCskknGq2jfGg4uGowlEpps= +github.com/compose-spec/compose-go/v2 v2.1.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.1.4 h1:9iFHrNRSFnta1A4z6HP1MVD7vH3hEd7jvJv9wnHHJHc= github.com/containerd/accelerated-container-image v1.1.4/go.mod h1:9mpTpL4W4yAsq2giHgo4B7wTFJgE59qCPh7dZTSpGCA= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= From 4cc911dfb576e01660203dc34a9a1e8c016cb848 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 22:24:15 +0000 Subject: [PATCH 0622/1066] build(deps): bump docker/build-push-action from 6.5.0 to 6.6.1 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.5.0 to 6.6.1. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.5.0...v6.6.1) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 08789ee9b4d..fc435888a3d 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.5.0 + uses: docker/build-push-action@v6.6.1 with: context: . platforms: linux/amd64,linux/arm64 From 0721f443c97d0032c836599733a0b1d4fb7ca738 Mon Sep 17 00:00:00 2001 From: CodeChanning Date: Wed, 3 Jul 2024 11:18:14 -0700 Subject: [PATCH 0623/1066] feat: adding filter infrastructure + status and event filter Signed-off-by: CodeChanning --- cmd/nerdctl/system_events.go | 6 + cmd/nerdctl/system_events_linux_test.go | 111 +++++++++++++++++ docs/command-reference.md | 4 +- pkg/api/types/system_types.go | 2 + pkg/cmd/system/events.go | 151 +++++++++++++++++++----- 5 files changed, 243 insertions(+), 31 deletions(-) create mode 100644 cmd/nerdctl/system_events_linux_test.go diff --git a/cmd/nerdctl/system_events.go b/cmd/nerdctl/system_events.go index db41ab17dba..889d3a1df9f 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..16a0a954ac0 --- /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/v2/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 29c17be1ed7..459d4c1bba5 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1275,8 +1275,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/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/cmd/system/events.go b/pkg/cmd/system/events.go index 08a890e3942..7f902920066 100644 --- a/pkg/cmd/system/events.go +++ b/pkg/cmd/system/events.go @@ -48,18 +48,101 @@ type EventOut struct { type Status string const ( - START Status = "START" - UNKNOWN Status = "UNKNOWN" + 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.ToUpper(topic), string(START)) { + 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() @@ -77,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 { @@ -99,37 +186,41 @@ func Events(ctx context.Context, client *containerd.Client, options types.System continue } } - if tmpl != nil { - 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 { - _, ok := data["container_id"] - if ok { - id = data["container_id"].(string) - } + 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 { + _, ok := data["container_id"] + if ok { + id = data["container_id"].(string) } + } - out := EventOut{e.Timestamp, id, e.Namespace, e.Topic, TopicToStatus(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 - } - } else { - if _, err := fmt.Fprintln( - options.Stdout, - e.Timestamp, - e.Namespace, - e.Topic, - string(out), - ); err != nil { - return err + 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 + } } } + } } } From 8cef1ce7019e901fbadb69f633a713e5efc3c3b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 22:04:09 +0000 Subject: [PATCH 0624/1066] build(deps): bump golang.org/x/sys in the golang-x group Bumps the golang-x group with 1 update: [golang.org/x/sys](https://github.com/golang/sys). Updates `golang.org/x/sys` from 0.23.0 to 0.24.0 - [Commits](https://github.com/golang/sys/compare/v0.23.0...v0.24.0) --- updated-dependencies: - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 39a7716776b..8f8f4c5986b 100644 --- a/go.mod +++ b/go.mod @@ -61,7 +61,7 @@ require ( golang.org/x/crypto v0.26.0 golang.org/x/net v0.28.0 golang.org/x/sync v0.8.0 - golang.org/x/sys v0.23.0 + golang.org/x/sys v0.24.0 golang.org/x/term v0.23.0 golang.org/x/text v0.17.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 25609ee8fe3..88097402c07 100644 --- a/go.sum +++ b/go.sum @@ -363,8 +363,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 98cc3689c54b16ff5f06a7a6cd5db66434dcde8e Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 24 Jun 2024 17:21:14 -0700 Subject: [PATCH 0625/1066] Containerd v2 Signed-off-by: apostasie --- Dockerfile | 6 +- cmd/nerdctl/apparmor_inspect_linux.go | 4 +- cmd/nerdctl/apparmor_list_linux.go | 3 +- cmd/nerdctl/apparmor_load_linux.go | 3 +- cmd/nerdctl/apparmor_unload_linux.go | 3 +- cmd/nerdctl/builder.go | 3 +- cmd/nerdctl/builder_build.go | 4 +- cmd/nerdctl/completion.go | 5 +- cmd/nerdctl/completion_linux.go | 3 +- cmd/nerdctl/compose.go | 3 +- cmd/nerdctl/compose_build.go | 3 +- cmd/nerdctl/compose_config.go | 3 +- cmd/nerdctl/compose_create.go | 3 +- cmd/nerdctl/compose_down.go | 3 +- cmd/nerdctl/compose_exec.go | 3 +- cmd/nerdctl/compose_images.go | 11 +- cmd/nerdctl/compose_kill.go | 3 +- cmd/nerdctl/compose_logs.go | 3 +- cmd/nerdctl/compose_pause.go | 3 +- cmd/nerdctl/compose_port.go | 3 +- cmd/nerdctl/compose_ps.go | 9 +- cmd/nerdctl/compose_pull.go | 3 +- cmd/nerdctl/compose_restart.go | 3 +- cmd/nerdctl/compose_run.go | 3 +- cmd/nerdctl/compose_start.go | 7 +- cmd/nerdctl/compose_stop.go | 3 +- cmd/nerdctl/compose_top.go | 5 +- cmd/nerdctl/compose_up_linux_test.go | 9 +- cmd/nerdctl/container_attach.go | 2 +- cmd/nerdctl/container_commit.go | 3 +- cmd/nerdctl/container_cp_linux.go | 3 +- cmd/nerdctl/container_diff.go | 11 +- cmd/nerdctl/container_exec.go | 5 +- cmd/nerdctl/container_inspect.go | 4 +- cmd/nerdctl/container_inspect_linux_test.go | 5 +- cmd/nerdctl/container_kill.go | 2 +- cmd/nerdctl/container_list.go | 4 +- cmd/nerdctl/container_logs.go | 3 +- cmd/nerdctl/container_pause.go | 5 +- cmd/nerdctl/container_port.go | 4 +- cmd/nerdctl/container_prune.go | 3 +- cmd/nerdctl/container_remove.go | 3 +- cmd/nerdctl/container_restart.go | 3 +- .../container_run_cgroup_linux_test.go | 2 +- cmd/nerdctl/container_run_linux.go | 2 +- .../container_run_log_driver_syslog_test.go | 3 +- cmd/nerdctl/container_run_mount_linux_test.go | 7 +- cmd/nerdctl/container_run_network.go | 3 +- cmd/nerdctl/container_run_test.go | 2 +- cmd/nerdctl/container_start.go | 2 +- cmd/nerdctl/container_stats.go | 5 +- cmd/nerdctl/container_stop.go | 5 +- cmd/nerdctl/container_top.go | 6 +- cmd/nerdctl/container_unpause.go | 6 +- cmd/nerdctl/container_update.go | 11 +- cmd/nerdctl/container_wait.go | 5 +- cmd/nerdctl/image_convert.go | 3 +- cmd/nerdctl/image_encrypt_linux_test.go | 4 +- cmd/nerdctl/image_history.go | 9 +- cmd/nerdctl/image_inspect.go | 3 +- cmd/nerdctl/image_load.go | 3 +- cmd/nerdctl/image_prune.go | 3 +- cmd/nerdctl/image_pull.go | 3 +- cmd/nerdctl/image_push.go | 3 +- cmd/nerdctl/image_remove.go | 3 +- cmd/nerdctl/image_tag.go | 4 +- cmd/nerdctl/inspect.go | 4 +- cmd/nerdctl/internal_oci_hook.go | 4 +- cmd/nerdctl/ipfs_registry_serve.go | 3 +- cmd/nerdctl/login.go | 4 +- cmd/nerdctl/main.go | 10 +- cmd/nerdctl/main_linux.go | 3 +- cmd/nerdctl/main_test.go | 4 +- cmd/nerdctl/main_unix.go | 3 +- cmd/nerdctl/namespace.go | 5 +- cmd/nerdctl/namespace_create.go | 3 +- cmd/nerdctl/namespace_inspect.go | 3 +- cmd/nerdctl/namespace_update.go | 3 +- cmd/nerdctl/network_create.go | 6 +- cmd/nerdctl/network_inspect.go | 3 +- cmd/nerdctl/network_list.go | 3 +- cmd/nerdctl/network_prune.go | 3 +- cmd/nerdctl/network_remove_linux_test.go | 5 +- cmd/nerdctl/system_events.go | 3 +- cmd/nerdctl/system_prune.go | 3 +- cmd/nerdctl/volume_create.go | 4 +- cmd/nerdctl/volume_inspect.go | 3 +- cmd/nerdctl/volume_list.go | 4 +- cmd/nerdctl/volume_prune.go | 3 +- cmd/nerdctl/volume_remove.go | 3 +- go.mod | 56 +-- go.sum | 116 +++--- pkg/apparmorutil/apparmorutil_linux.go | 4 +- pkg/bypass4netnsutil/bypass4netnsutil.go | 4 +- pkg/cioutil/container_io.go | 6 +- pkg/cioutil/container_io_unix.go | 2 +- pkg/cioutil/container_io_windows.go | 2 +- pkg/clientutil/client.go | 9 +- pkg/cmd/apparmor/inspect_linux.go | 2 +- pkg/cmd/apparmor/load_linux.go | 2 +- pkg/cmd/builder/build.go | 6 +- pkg/cmd/compose/compose.go | 2 +- pkg/cmd/container/attach.go | 4 +- pkg/cmd/container/commit.go | 2 +- pkg/cmd/container/cp_linux.go | 2 +- pkg/cmd/container/create.go | 8 +- pkg/cmd/container/exec.go | 4 +- pkg/cmd/container/exec_linux.go | 2 +- pkg/cmd/container/inspect.go | 4 +- pkg/cmd/container/kill.go | 4 +- pkg/cmd/container/list.go | 6 +- pkg/cmd/container/list_util.go | 4 +- pkg/cmd/container/logs.go | 2 +- pkg/cmd/container/pause.go | 2 +- pkg/cmd/container/prune.go | 2 +- pkg/cmd/container/remove.go | 6 +- pkg/cmd/container/rename.go | 2 +- pkg/cmd/container/restart.go | 2 +- pkg/cmd/container/run_cgroup_freebsd.go | 2 +- pkg/cmd/container/run_cgroup_linux.go | 4 +- pkg/cmd/container/run_cgroup_windows.go | 2 +- pkg/cmd/container/run_freebsd.go | 6 +- pkg/cmd/container/run_gpus.go | 4 +- pkg/cmd/container/run_linux.go | 8 +- pkg/cmd/container/run_mount.go | 12 +- pkg/cmd/container/run_restart.go | 6 +- pkg/cmd/container/run_runtime.go | 12 +- pkg/cmd/container/run_security_linux.go | 8 +- pkg/cmd/container/run_ulimit.go | 4 +- pkg/cmd/container/run_user.go | 4 +- pkg/cmd/container/run_windows.go | 6 +- pkg/cmd/container/start.go | 2 +- pkg/cmd/container/stats.go | 4 +- pkg/cmd/container/stop.go | 2 +- pkg/cmd/container/top.go | 2 +- pkg/cmd/container/top_unix.go | 2 +- pkg/cmd/container/top_windows.go | 2 +- pkg/cmd/container/unpause.go | 2 +- pkg/cmd/container/wait.go | 2 +- pkg/cmd/image/convert.go | 10 +- pkg/cmd/image/crypt.go | 6 +- pkg/cmd/image/inspect.go | 4 +- pkg/cmd/image/list.go | 8 +- pkg/cmd/image/load.go | 8 +- pkg/cmd/image/prune.go | 4 +- pkg/cmd/image/pull.go | 2 +- pkg/cmd/image/push.go | 16 +- pkg/cmd/image/remove.go | 4 +- pkg/cmd/image/save.go | 4 +- pkg/cmd/image/tag.go | 2 +- pkg/cmd/login/login.go | 13 +- pkg/cmd/namespace/create.go | 2 +- pkg/cmd/namespace/inspect.go | 4 +- pkg/cmd/namespace/namespace_freebsd.go | 2 +- pkg/cmd/namespace/namespace_linux.go | 4 +- pkg/cmd/namespace/namespace_windows.go | 2 +- pkg/cmd/namespace/remove.go | 2 +- pkg/cmd/namespace/update.go | 2 +- pkg/cmd/network/prune.go | 2 +- pkg/cmd/network/remove.go | 2 +- pkg/cmd/system/events.go | 4 +- pkg/cmd/system/info.go | 6 +- pkg/cmd/system/prune.go | 2 +- pkg/cmd/volume/list.go | 2 +- pkg/cmd/volume/prune.go | 2 +- pkg/cmd/volume/rm.go | 2 +- pkg/composer/composer.go | 4 +- pkg/composer/container.go | 2 +- pkg/composer/copy.go | 2 +- pkg/composer/create.go | 3 +- pkg/composer/exec.go | 2 +- pkg/composer/kill.go | 3 +- pkg/composer/logs.go | 2 +- pkg/composer/orphans.go | 2 +- pkg/composer/pause.go | 5 +- pkg/composer/restart.go | 2 +- pkg/composer/rm.go | 2 +- pkg/composer/run.go | 3 +- pkg/composer/serviceparser/build.go | 2 +- pkg/composer/serviceparser/serviceparser.go | 4 +- pkg/composer/stop.go | 2 +- pkg/composer/up_service.go | 4 +- pkg/config/config.go | 7 +- pkg/consoleutil/consoleutil_unix.go | 3 +- pkg/containerdutil/content.go | 4 +- pkg/containerdutil/helpers.go | 2 +- pkg/containerdutil/snapshotter.go | 4 +- pkg/containerinspector/containerinspector.go | 2 +- pkg/containerutil/config.go | 4 +- .../container_network_manager.go | 6 +- .../container_network_manager_linux.go | 4 +- .../container_network_manager_other.go | 4 +- .../container_network_manager_windows.go | 6 +- pkg/containerutil/containerutil.go | 10 +- pkg/containerutil/cp_linux.go | 4 +- pkg/defaults/defaults_linux.go | 4 +- pkg/eventutil/eventutil.go | 2 +- pkg/formatter/formatter.go | 8 +- pkg/idutil/containerwalker/containerwalker.go | 2 +- pkg/idutil/imagewalker/imagewalker.go | 4 +- pkg/imageinspector/imageinspector.go | 6 +- pkg/imgutil/commit/commit.go | 16 +- pkg/imgutil/converter/zstd.go | 10 +- .../dockerconfigresolver.go | 6 +- pkg/imgutil/filtering.go | 4 +- pkg/imgutil/imgutil.go | 10 +- pkg/imgutil/jobs/jobs.go | 6 +- pkg/imgutil/pull/pull.go | 6 +- pkg/imgutil/push/push.go | 16 +- pkg/imgutil/snapshotter.go | 6 +- pkg/imgutil/snapshotter_test.go | 4 +- pkg/infoutil/infoutil.go | 14 +- pkg/infoutil/infoutil_freebsd.go | 2 +- pkg/infoutil/infoutil_linux.go | 2 +- pkg/infoutil/infoutil_windows.go | 4 +- pkg/infoutil/infoutil_windows_test.go | 3 +- pkg/inspecttypes/dockercompat/dockercompat.go | 4 +- .../dockercompat/dockercompat_test.go | 4 +- pkg/inspecttypes/native/container.go | 4 +- pkg/inspecttypes/native/image.go | 2 +- pkg/ipcutil/ipcutil.go | 6 +- pkg/ipfs/image.go | 8 +- pkg/ipfs/registry.go | 4 +- pkg/lockutil/lockutil_unix.go | 3 +- pkg/lockutil/lockutil_windows.go | 3 +- pkg/logging/fluentd_logger.go | 2 +- pkg/logging/journald_logger.go | 2 +- pkg/logging/json_logger.go | 2 +- pkg/logging/logging.go | 2 +- pkg/logging/syslog_logger.go | 2 +- pkg/mountutil/mountutil.go | 6 +- pkg/mountutil/mountutil_freebsd.go | 2 +- pkg/mountutil/mountutil_linux.go | 11 +- pkg/mountutil/mountutil_linux_test.go | 4 +- pkg/mountutil/mountutil_windows.go | 2 +- pkg/mountutil/volumestore/volumestore.go | 2 +- pkg/namestore/namestore.go | 2 +- pkg/netutil/netutil.go | 4 +- pkg/ocihook/ocihook_linux.go | 2 +- pkg/platformutil/layers.go | 4 +- pkg/rootlessutil/child_linux.go | 2 +- pkg/signalutil/signals.go | 2 +- pkg/snapshotterutil/socisource.go | 6 +- pkg/sysinfo/cgroup2_linux.go | 168 +++++++++ pkg/sysinfo/doc.go | 21 ++ pkg/sysinfo/numcpu.go | 38 ++ pkg/sysinfo/numcpu_linux.go | 40 +++ pkg/sysinfo/numcpu_other.go | 31 ++ pkg/sysinfo/numcpu_windows.go | 59 ++++ pkg/sysinfo/sysinfo.go | 193 ++++++++++ pkg/sysinfo/sysinfo_linux.go | 329 ++++++++++++++++++ pkg/sysinfo/sysinfo_linux_test.go | 147 ++++++++ pkg/sysinfo/sysinfo_other.go | 31 ++ pkg/sysinfo/sysinfo_test.go | 49 +++ pkg/taskutil/taskutil.go | 7 +- .../testregistry/testregistry_linux.go | 5 +- pkg/testutil/testutil.go | 2 +- pkg/testutil/testutil_windows.go | 3 +- 258 files changed, 1760 insertions(+), 549 deletions(-) create mode 100644 pkg/sysinfo/cgroup2_linux.go create mode 100644 pkg/sysinfo/doc.go create mode 100644 pkg/sysinfo/numcpu.go create mode 100644 pkg/sysinfo/numcpu_linux.go create mode 100644 pkg/sysinfo/numcpu_other.go create mode 100644 pkg/sysinfo/numcpu_windows.go create mode 100644 pkg/sysinfo/sysinfo.go create mode 100644 pkg/sysinfo/sysinfo_linux.go create mode 100644 pkg/sysinfo/sysinfo_linux_test.go create mode 100644 pkg/sysinfo/sysinfo_other.go create mode 100644 pkg/sysinfo/sysinfo_test.go diff --git a/Dockerfile b/Dockerfile index 9746b272409..dca67237b11 100644 --- a/Dockerfile +++ b/Dockerfile @@ -319,7 +319,7 @@ RUN curl -o nydus-static.tgz -fsSL --proto '=https' --tlsv1.2 "https://github.co mv nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/bin/ && \ rm nydus-static.tgz CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/v2/cmd/nerdctl/...", \ - "--", "-timeout=30m", "-args", "-test.kill-daemon"] + "--", "-timeout=60m", "-args", "-test.kill-daemon"] FROM test-integration AS test-integration-rootless # Install SSH for creating systemd user session. @@ -345,7 +345,7 @@ COPY ./Dockerfile.d/test-integration-rootless.sh / CMD ["/test-integration-rootless.sh", \ "gotestsum", "--format=testname", "--rerun-fails=2", "--raw-command", \ "--", "/usr/local/go/bin/go", "tool", "test2json", "-t", "-p", "github.com/containerd/nerdctl/v2/cmd/nerdctl", \ - "/usr/local/bin/nerdctl.test", "-test.v", "-test.timeout=30m", "-test.kill-daemon"] + "/usr/local/bin/nerdctl.test", "-test.v", "-test.timeout=60m", "-test.kill-daemon"] # test for CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=slirp4netns FROM test-integration-rootless AS test-integration-rootless-port-slirp4netns @@ -354,6 +354,6 @@ RUN chown -R rootless:rootless /home/rootless/.config FROM test-integration AS test-integration-ipv6 CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/v2/cmd/nerdctl/...", \ - "--", "-timeout=30m", "-args", "-test.kill-daemon", "-test.ipv6"] + "--", "-timeout=60m", "-args", "-test.kill-daemon", "-test.ipv6"] FROM base AS demo diff --git a/cmd/nerdctl/apparmor_inspect_linux.go b/cmd/nerdctl/apparmor_inspect_linux.go index 18a4e3afd00..681826bf82e 100644 --- a/cmd/nerdctl/apparmor_inspect_linux.go +++ b/cmd/nerdctl/apparmor_inspect_linux.go @@ -19,11 +19,11 @@ package main import ( "fmt" - "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/apparmor" "github.com/containerd/nerdctl/v2/pkg/defaults" - "github.com/spf13/cobra" ) func newApparmorInspectCommand() *cobra.Command { diff --git a/cmd/nerdctl/apparmor_list_linux.go b/cmd/nerdctl/apparmor_list_linux.go index 99cc8eb5aa6..e650e3ea21a 100644 --- a/cmd/nerdctl/apparmor_list_linux.go +++ b/cmd/nerdctl/apparmor_list_linux.go @@ -17,9 +17,10 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/apparmor" - "github.com/spf13/cobra" ) func newApparmorLsCommand() *cobra.Command { diff --git a/cmd/nerdctl/apparmor_load_linux.go b/cmd/nerdctl/apparmor_load_linux.go index a7e25c3f71e..0c04ae47783 100644 --- a/cmd/nerdctl/apparmor_load_linux.go +++ b/cmd/nerdctl/apparmor_load_linux.go @@ -19,9 +19,10 @@ package main import ( "fmt" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/cmd/apparmor" "github.com/containerd/nerdctl/v2/pkg/defaults" - "github.com/spf13/cobra" ) func newApparmorLoadCommand() *cobra.Command { diff --git a/cmd/nerdctl/apparmor_unload_linux.go b/cmd/nerdctl/apparmor_unload_linux.go index 1fb5c840c4a..8ab8e1bf2c6 100644 --- a/cmd/nerdctl/apparmor_unload_linux.go +++ b/cmd/nerdctl/apparmor_unload_linux.go @@ -19,9 +19,10 @@ package main import ( "fmt" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/cmd/apparmor" "github.com/containerd/nerdctl/v2/pkg/defaults" - "github.com/spf13/cobra" ) func newApparmorUnloadCommand() *cobra.Command { diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index 71a8b5a42de..1ae4d230c3b 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -22,9 +22,10 @@ import ( "os/exec" "strings" + "github.com/spf13/cobra" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" - "github.com/spf13/cobra" ) func newBuilderCommand() *cobra.Command { diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index 0fa319a1eb6..46e04ed00b4 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -23,13 +23,13 @@ import ( "strconv" "strings" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/builder" "github.com/containerd/nerdctl/v2/pkg/strutil" - - "github.com/spf13/cobra" ) func newBuildCommand() *cobra.Command { diff --git a/cmd/nerdctl/completion.go b/cmd/nerdctl/completion.go index ebd8d47c8bd..f36bc7b1ba7 100644 --- a/cmd/nerdctl/completion.go +++ b/cmd/nerdctl/completion.go @@ -20,11 +20,12 @@ import ( "context" "time" - "github.com/containerd/containerd" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/netutil" - "github.com/spf13/cobra" ) func shellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { diff --git a/cmd/nerdctl/completion_linux.go b/cmd/nerdctl/completion_linux.go index 52baa8b974a..12dd8297b3e 100644 --- a/cmd/nerdctl/completion_linux.go +++ b/cmd/nerdctl/completion_linux.go @@ -17,8 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/v2/pkg/apparmorutil" "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" ) func shellCompleteApparmorProfiles(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { diff --git a/cmd/nerdctl/compose.go b/cmd/nerdctl/compose.go index c64e719d4db..927f2024dd3 100644 --- a/cmd/nerdctl/compose.go +++ b/cmd/nerdctl/compose.go @@ -17,8 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/pkg/composer" ) func newComposeCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_build.go b/cmd/nerdctl/compose_build.go index 9a001af2c57..d607d17b2f4 100644 --- a/cmd/nerdctl/compose_build.go +++ b/cmd/nerdctl/compose_build.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeBuildCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_config.go b/cmd/nerdctl/compose_config.go index 5a2b0be9820..c920c77f441 100644 --- a/cmd/nerdctl/compose_config.go +++ b/cmd/nerdctl/compose_config.go @@ -19,10 +19,11 @@ package main import ( "fmt" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeConfigCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_create.go b/cmd/nerdctl/compose_create.go index 14c757aaab8..e420984e933 100644 --- a/cmd/nerdctl/compose_create.go +++ b/cmd/nerdctl/compose_create.go @@ -19,10 +19,11 @@ package main import ( "errors" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeCreateCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_down.go b/cmd/nerdctl/compose_down.go index 19a5fe52bd6..6bcc152963d 100644 --- a/cmd/nerdctl/compose_down.go +++ b/cmd/nerdctl/compose_down.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeDownCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_exec.go b/cmd/nerdctl/compose_exec.go index dee9ae91612..f8f4019bc42 100644 --- a/cmd/nerdctl/compose_exec.go +++ b/cmd/nerdctl/compose_exec.go @@ -19,10 +19,11 @@ package main import ( "errors" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeExecCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_images.go b/cmd/nerdctl/compose_images.go index 80ef81855eb..45d66a15b8e 100644 --- a/cmd/nerdctl/compose_images.go +++ b/cmd/nerdctl/compose_images.go @@ -22,17 +22,18 @@ import ( "strings" "text/tabwriter" - "github.com/containerd/containerd" - "github.com/containerd/containerd/pkg/progress" - "github.com/containerd/containerd/snapshots" + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" + + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/progress" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/spf13/cobra" - "golang.org/x/sync/errgroup" ) func newComposeImagesCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_kill.go b/cmd/nerdctl/compose_kill.go index 5a7cee00917..f6d6a1d6352 100644 --- a/cmd/nerdctl/compose_kill.go +++ b/cmd/nerdctl/compose_kill.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeKillCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_logs.go b/cmd/nerdctl/compose_logs.go index 46bd2df7203..79af0310b6d 100644 --- a/cmd/nerdctl/compose_logs.go +++ b/cmd/nerdctl/compose_logs.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeLogsCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_pause.go b/cmd/nerdctl/compose_pause.go index 7cf24cfb78b..b280d5cf950 100644 --- a/cmd/nerdctl/compose_pause.go +++ b/cmd/nerdctl/compose_pause.go @@ -17,9 +17,10 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" - "github.com/spf13/cobra" ) func newComposePauseCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_port.go b/cmd/nerdctl/compose_port.go index 2156bd917e4..95035e833dd 100644 --- a/cmd/nerdctl/compose_port.go +++ b/cmd/nerdctl/compose_port.go @@ -20,10 +20,11 @@ import ( "fmt" "strconv" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposePortCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose_ps.go index aa4fdd20268..ad43b5c0768 100644 --- a/cmd/nerdctl/compose_ps.go +++ b/cmd/nerdctl/compose_ps.go @@ -23,8 +23,11 @@ import ( "text/tabwriter" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/runtime/restart" + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" + + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/runtime/restart" "github.com/containerd/errdefs" gocni "github.com/containerd/go-cni" "github.com/containerd/log" @@ -34,8 +37,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/portutil" - "github.com/spf13/cobra" - "golang.org/x/sync/errgroup" ) func newComposePsCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_pull.go b/cmd/nerdctl/compose_pull.go index babe2e65752..738c0b955e9 100644 --- a/cmd/nerdctl/compose_pull.go +++ b/cmd/nerdctl/compose_pull.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposePullCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_restart.go b/cmd/nerdctl/compose_restart.go index 46ba6d31887..a68f6e52408 100644 --- a/cmd/nerdctl/compose_restart.go +++ b/cmd/nerdctl/compose_restart.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeRestartCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_run.go b/cmd/nerdctl/compose_run.go index 0cfe5cfd535..122e6be23bf 100644 --- a/cmd/nerdctl/compose_run.go +++ b/cmd/nerdctl/compose_run.go @@ -20,10 +20,11 @@ import ( "errors" "fmt" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeRunCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_start.go b/cmd/nerdctl/compose_start.go index f5e0682085e..509ae1a1e05 100644 --- a/cmd/nerdctl/compose_start.go +++ b/cmd/nerdctl/compose_start.go @@ -21,14 +21,15 @@ import ( "fmt" "os" - "github.com/containerd/containerd" + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/labels" - "github.com/spf13/cobra" - "golang.org/x/sync/errgroup" ) func newComposeStartCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_stop.go b/cmd/nerdctl/compose_stop.go index ab6053d1d5a..07bd789178e 100644 --- a/cmd/nerdctl/compose_stop.go +++ b/cmd/nerdctl/compose_stop.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeStopCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_top.go b/cmd/nerdctl/compose_top.go index 52ea6a71800..70cd9ac1f54 100644 --- a/cmd/nerdctl/compose_top.go +++ b/cmd/nerdctl/compose_top.go @@ -19,14 +19,15 @@ package main import ( "fmt" - "github.com/containerd/containerd" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/labels" - "github.com/spf13/cobra" ) func newComposeTopCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_up_linux_test.go b/cmd/nerdctl/compose_up_linux_test.go index d060bada8c6..94fccd05a02 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/cmd/nerdctl/compose_up_linux_test.go @@ -23,16 +23,15 @@ import ( "testing" "time" + "github.com/docker/go-connections/nat" + "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/docker/go-connections/nat" - "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" - - "gotest.tools/v3/assert" - "gotest.tools/v3/icmd" ) func TestComposeUp(t *testing.T) { diff --git a/cmd/nerdctl/container_attach.go b/cmd/nerdctl/container_attach.go index 4c8067322ae..cc6fe7d58c9 100644 --- a/cmd/nerdctl/container_attach.go +++ b/cmd/nerdctl/container_attach.go @@ -17,7 +17,7 @@ package main import ( - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/cmd/nerdctl/container_commit.go b/cmd/nerdctl/container_commit.go index 2b56c1de641..96c79cbc66d 100644 --- a/cmd/nerdctl/container_commit.go +++ b/cmd/nerdctl/container_commit.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newCommitCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_cp_linux.go b/cmd/nerdctl/container_cp_linux.go index 9f38c394af7..3a2c2aa84e1 100644 --- a/cmd/nerdctl/container_cp_linux.go +++ b/cmd/nerdctl/container_cp_linux.go @@ -19,11 +19,12 @@ package main import ( "fmt" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/spf13/cobra" ) func newCpCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index 7731327d3e2..00f228f9fc9 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -23,9 +23,12 @@ import ( "path/filepath" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/mount" + "github.com/opencontainers/image-spec/identity" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/continuity/fs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" @@ -35,8 +38,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/platforms" - "github.com/opencontainers/image-spec/identity" - "github.com/spf13/cobra" ) func newDiffCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_exec.go b/cmd/nerdctl/container_exec.go index 751c3915190..7c879e288a8 100644 --- a/cmd/nerdctl/container_exec.go +++ b/cmd/nerdctl/container_exec.go @@ -19,11 +19,12 @@ package main import ( "errors" - "github.com/containerd/containerd" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newExecCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_inspect.go b/cmd/nerdctl/container_inspect.go index cd3c01871df..e178724617e 100644 --- a/cmd/nerdctl/container_inspect.go +++ b/cmd/nerdctl/container_inspect.go @@ -19,11 +19,11 @@ package main import ( "fmt" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - - "github.com/spf13/cobra" ) func newContainerInspectCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_inspect_linux_test.go b/cmd/nerdctl/container_inspect_linux_test.go index 58ceb359d74..a1aca0d1a3c 100644 --- a/cmd/nerdctl/container_inspect_linux_test.go +++ b/cmd/nerdctl/container_inspect_linux_test.go @@ -21,11 +21,12 @@ import ( "strings" "testing" + "github.com/docker/go-connections/nat" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/testutil" - "github.com/docker/go-connections/nat" - "gotest.tools/v3/assert" ) func TestContainerInspectContainsPortConfig(t *testing.T) { diff --git a/cmd/nerdctl/container_kill.go b/cmd/nerdctl/container_kill.go index fe0e26ca501..4c859ab6775 100644 --- a/cmd/nerdctl/container_kill.go +++ b/cmd/nerdctl/container_kill.go @@ -17,7 +17,7 @@ package main import ( - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container_list.go index 549df18ca08..e66e7a6584e 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container_list.go @@ -24,12 +24,12 @@ import ( "text/tabwriter" "text/template" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/formatter" - - "github.com/spf13/cobra" ) func newPsCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_logs.go b/cmd/nerdctl/container_logs.go index 27e5dec0250..2e66c91e09e 100644 --- a/cmd/nerdctl/container_logs.go +++ b/cmd/nerdctl/container_logs.go @@ -20,10 +20,11 @@ import ( "fmt" "strconv" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newLogsCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_pause.go b/cmd/nerdctl/container_pause.go index bf8cf4f0107..f66f2a9753b 100644 --- a/cmd/nerdctl/container_pause.go +++ b/cmd/nerdctl/container_pause.go @@ -17,11 +17,12 @@ package main import ( - "github.com/containerd/containerd" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newPauseCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_port.go b/cmd/nerdctl/container_port.go index 072df21ba25..df98022ad73 100644 --- a/cmd/nerdctl/container_port.go +++ b/cmd/nerdctl/container_port.go @@ -22,11 +22,11 @@ import ( "strconv" "strings" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" - - "github.com/spf13/cobra" ) func newPortCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_prune.go b/cmd/nerdctl/container_prune.go index 1d1e19afa6d..fc2bdcc9457 100644 --- a/cmd/nerdctl/container_prune.go +++ b/cmd/nerdctl/container_prune.go @@ -20,10 +20,11 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newContainerPruneCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_remove.go b/cmd/nerdctl/container_remove.go index 20588a32408..bdd415f836e 100644 --- a/cmd/nerdctl/container_remove.go +++ b/cmd/nerdctl/container_remove.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newRmCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_restart.go b/cmd/nerdctl/container_restart.go index 906c7ff6486..caf05341746 100644 --- a/cmd/nerdctl/container_restart.go +++ b/cmd/nerdctl/container_restart.go @@ -19,10 +19,11 @@ package main import ( "time" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newRestartCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_run_cgroup_linux_test.go b/cmd/nerdctl/container_run_cgroup_linux_test.go index 106060bf365..7f7e6c0d2f9 100644 --- a/cmd/nerdctl/container_run_cgroup_linux_test.go +++ b/cmd/nerdctl/container_run_cgroup_linux_test.go @@ -24,7 +24,7 @@ import ( "testing" "github.com/containerd/cgroups/v3" - "github.com/containerd/containerd/pkg/userns" + "github.com/containerd/containerd/v2/pkg/userns" "github.com/containerd/continuity/testutil/loopback" "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/testutil" diff --git a/cmd/nerdctl/container_run_linux.go b/cmd/nerdctl/container_run_linux.go index 6ee1eeb2f9f..cdbfa19f8d9 100644 --- a/cmd/nerdctl/container_run_linux.go +++ b/cmd/nerdctl/container_run_linux.go @@ -19,7 +19,7 @@ package main import ( "strings" - "github.com/containerd/containerd/pkg/cap" + "github.com/containerd/containerd/v2/pkg/cap" "github.com/spf13/cobra" ) diff --git a/cmd/nerdctl/container_run_log_driver_syslog_test.go b/cmd/nerdctl/container_run_log_driver_syslog_test.go index ca0ea993e7c..7e836c61149 100644 --- a/cmd/nerdctl/container_run_log_driver_syslog_test.go +++ b/cmd/nerdctl/container_run_log_driver_syslog_test.go @@ -25,11 +25,12 @@ import ( "testing" "time" + syslog "github.com/yuchanns/srslog" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testca" "github.com/containerd/nerdctl/v2/pkg/testutil/testsyslog" - syslog "github.com/yuchanns/srslog" ) func runSyslogTest(t *testing.T, networks []string, syslogFacilities map[string]syslog.Priority, fmtValidFuncs map[string]func(string, string, string, string, syslog.Priority, bool) error) { diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container_run_mount_linux_test.go index ee8a8b6d14a..ea97047ec9c 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container_run_mount_linux_test.go @@ -23,11 +23,12 @@ import ( "strings" "testing" - "github.com/containerd/containerd/mount" - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/containerd/nerdctl/v2/pkg/testutil" mobymount "github.com/moby/sys/mount" "gotest.tools/v3/assert" + + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRunVolume(t *testing.T) { diff --git a/cmd/nerdctl/container_run_network.go b/cmd/nerdctl/container_run_network.go index 64822221d4e..3e4444267d9 100644 --- a/cmd/nerdctl/container_run_network.go +++ b/cmd/nerdctl/container_run_network.go @@ -19,11 +19,12 @@ package main import ( "net" + "github.com/spf13/cobra" + gocni "github.com/containerd/go-cni" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/portutil" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/spf13/cobra" ) func loadNetworkFlags(cmd *cobra.Command) (types.NetworkOptions, error) { diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index 5138d0f0296..16ada61828d 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -398,7 +398,7 @@ RUN echo '\ "path/filepath" \n\ "sync" \n\ \n\ - "github.com/containerd/containerd/runtime/v2/logging"\n\ + "github.com/containerd/containerd/v2/core/runtime/v2/logging"\n\ )\n\ func main() {\n\ diff --git a/cmd/nerdctl/container_start.go b/cmd/nerdctl/container_start.go index bd67d40f092..09fec22cc68 100644 --- a/cmd/nerdctl/container_start.go +++ b/cmd/nerdctl/container_start.go @@ -17,7 +17,7 @@ package main import ( - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/cmd/nerdctl/container_stats.go b/cmd/nerdctl/container_stats.go index f8281c12328..9f39942e6f9 100644 --- a/cmd/nerdctl/container_stats.go +++ b/cmd/nerdctl/container_stats.go @@ -17,11 +17,12 @@ package main import ( - "github.com/containerd/containerd" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newStatsCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_stop.go b/cmd/nerdctl/container_stop.go index 0398e36ae44..31f2751981c 100644 --- a/cmd/nerdctl/container_stop.go +++ b/cmd/nerdctl/container_stop.go @@ -19,11 +19,12 @@ package main import ( "time" - "github.com/containerd/containerd" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newStopCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_top.go b/cmd/nerdctl/container_top.go index c51b23d7242..b5434dfd7c0 100644 --- a/cmd/nerdctl/container_top.go +++ b/cmd/nerdctl/container_top.go @@ -20,14 +20,14 @@ import ( "errors" "fmt" - "github.com/containerd/containerd" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - - "github.com/spf13/cobra" ) func newTopCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_unpause.go b/cmd/nerdctl/container_unpause.go index 26909f790b2..190ea8e6ffe 100644 --- a/cmd/nerdctl/container_unpause.go +++ b/cmd/nerdctl/container_unpause.go @@ -17,12 +17,12 @@ package main import ( - "github.com/containerd/containerd" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - - "github.com/spf13/cobra" ) func newUnpauseCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index d52d12a908b..6de1edcaa1a 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -23,8 +23,12 @@ import ( "fmt" "runtime" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" + "github.com/docker/go-units" + runtimespec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" @@ -34,9 +38,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/typeurl/v2" - "github.com/docker/go-units" - runtimespec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/spf13/cobra" ) type updateResourceOptions struct { diff --git a/cmd/nerdctl/container_wait.go b/cmd/nerdctl/container_wait.go index 98156c44175..e9e456f9d4d 100644 --- a/cmd/nerdctl/container_wait.go +++ b/cmd/nerdctl/container_wait.go @@ -17,11 +17,12 @@ package main import ( - "github.com/containerd/containerd" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newWaitCommand() *cobra.Command { diff --git a/cmd/nerdctl/image_convert.go b/cmd/nerdctl/image_convert.go index 0b27e593d77..355a2e9737a 100644 --- a/cmd/nerdctl/image_convert.go +++ b/cmd/nerdctl/image_convert.go @@ -19,10 +19,11 @@ package main import ( "compress/gzip" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" - "github.com/spf13/cobra" ) const imageConvertHelp = `Convert an image format. diff --git a/cmd/nerdctl/image_encrypt_linux_test.go b/cmd/nerdctl/image_encrypt_linux_test.go index f6ba49ab5f1..e48e1769efb 100644 --- a/cmd/nerdctl/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image_encrypt_linux_test.go @@ -24,8 +24,8 @@ import ( "path/filepath" "testing" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index b420e53b447..6bb75a8ad77 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -28,15 +28,16 @@ import ( "text/template" "time" - "github.com/containerd/containerd" + "github.com/docker/go-units" + "github.com/opencontainers/image-spec/identity" + "github.com/spf13/cobra" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imgutil" - "github.com/docker/go-units" - "github.com/opencontainers/image-spec/identity" - "github.com/spf13/cobra" ) func newHistoryCommand() *cobra.Command { diff --git a/cmd/nerdctl/image_inspect.go b/cmd/nerdctl/image_inspect.go index 28a4ffe8a3f..9cc7fbdc81f 100644 --- a/cmd/nerdctl/image_inspect.go +++ b/cmd/nerdctl/image_inspect.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" - "github.com/spf13/cobra" ) func newImageInspectCommand() *cobra.Command { diff --git a/cmd/nerdctl/image_load.go b/cmd/nerdctl/image_load.go index 39c027d42fa..5e8e5a4228d 100644 --- a/cmd/nerdctl/image_load.go +++ b/cmd/nerdctl/image_load.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" - "github.com/spf13/cobra" ) func newLoadCommand() *cobra.Command { diff --git a/cmd/nerdctl/image_prune.go b/cmd/nerdctl/image_prune.go index 0f42f9e9828..56dd8797f1a 100644 --- a/cmd/nerdctl/image_prune.go +++ b/cmd/nerdctl/image_prune.go @@ -20,10 +20,11 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" - "github.com/spf13/cobra" ) func newImagePruneCommand() *cobra.Command { diff --git a/cmd/nerdctl/image_pull.go b/cmd/nerdctl/image_pull.go index 36c4fa617a5..afe8717aa4c 100644 --- a/cmd/nerdctl/image_pull.go +++ b/cmd/nerdctl/image_pull.go @@ -17,12 +17,13 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/spf13/cobra" ) func newPullCommand() *cobra.Command { diff --git a/cmd/nerdctl/image_push.go b/cmd/nerdctl/image_push.go index 132318b82ad..e04f8b5ef41 100644 --- a/cmd/nerdctl/image_push.go +++ b/cmd/nerdctl/image_push.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" - "github.com/spf13/cobra" ) const ( diff --git a/cmd/nerdctl/image_remove.go b/cmd/nerdctl/image_remove.go index 26dfdefe4c2..f61a39ac6cc 100644 --- a/cmd/nerdctl/image_remove.go +++ b/cmd/nerdctl/image_remove.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" - "github.com/spf13/cobra" ) func newRmiCommand() *cobra.Command { diff --git a/cmd/nerdctl/image_tag.go b/cmd/nerdctl/image_tag.go index b6eede91c90..abf96ab28cf 100644 --- a/cmd/nerdctl/image_tag.go +++ b/cmd/nerdctl/image_tag.go @@ -17,11 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" - - "github.com/spf13/cobra" ) func newTagCommand() *cobra.Command { diff --git a/cmd/nerdctl/inspect.go b/cmd/nerdctl/inspect.go index fa74d587786..150b8e7dfcd 100644 --- a/cmd/nerdctl/inspect.go +++ b/cmd/nerdctl/inspect.go @@ -20,14 +20,14 @@ import ( "context" "fmt" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" - - "github.com/spf13/cobra" ) func newInspectCommand() *cobra.Command { diff --git a/cmd/nerdctl/internal_oci_hook.go b/cmd/nerdctl/internal_oci_hook.go index bb76c19bb31..455b41daf7e 100644 --- a/cmd/nerdctl/internal_oci_hook.go +++ b/cmd/nerdctl/internal_oci_hook.go @@ -20,10 +20,10 @@ import ( "errors" "os" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/ocihook" - - "github.com/spf13/cobra" ) func newInternalOCIHookCommandCommand() *cobra.Command { diff --git a/cmd/nerdctl/ipfs_registry_serve.go b/cmd/nerdctl/ipfs_registry_serve.go index 67a120919bf..c02b32937a1 100644 --- a/cmd/nerdctl/ipfs_registry_serve.go +++ b/cmd/nerdctl/ipfs_registry_serve.go @@ -17,9 +17,10 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/ipfs" - "github.com/spf13/cobra" ) const ( diff --git a/cmd/nerdctl/login.go b/cmd/nerdctl/login.go index 9aea0501f88..d8d27415167 100644 --- a/cmd/nerdctl/login.go +++ b/cmd/nerdctl/login.go @@ -21,11 +21,11 @@ import ( "io" "strings" + "github.com/spf13/cobra" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/login" - - "github.com/spf13/cobra" ) func newLoginCommand() *cobra.Command { diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 42e5eb7d925..4c5e00272fd 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -25,6 +25,11 @@ import ( "strings" "time" + "github.com/fatih/color" + "github.com/pelletier/go-toml/v2" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/config" ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" @@ -32,11 +37,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/logging" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/version" - "github.com/fatih/color" - "github.com/pelletier/go-toml/v2" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" ) const ( diff --git a/cmd/nerdctl/main_linux.go b/cmd/nerdctl/main_linux.go index 5f1f5ae9355..1512c05a678 100644 --- a/cmd/nerdctl/main_linux.go +++ b/cmd/nerdctl/main_linux.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/spf13/cobra" ) func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { diff --git a/cmd/nerdctl/main_test.go b/cmd/nerdctl/main_test.go index 5310ad1cb72..b8400730133 100644 --- a/cmd/nerdctl/main_test.go +++ b/cmd/nerdctl/main_test.go @@ -21,7 +21,7 @@ import ( "path/filepath" "testing" - "github.com/containerd/containerd" + "github.com/containerd/containerd/v2/defaults" "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) @@ -55,7 +55,7 @@ snapshotter = "dummy-snapshotter-via-toml" base := testutil.NewBase(t) // [Default] - base.Cmd("info", "-f", "{{.Driver}}").AssertOutExactly(containerd.DefaultSnapshotter + "\n") + base.Cmd("info", "-f", "{{.Driver}}").AssertOutExactly(defaults.DefaultSnapshotter + "\n") // [TOML, Default] base.Env = append(base.Env, "NERDCTL_TOML="+tomlPath) diff --git a/cmd/nerdctl/main_unix.go b/cmd/nerdctl/main_unix.go index d804550fd19..2a768500566 100644 --- a/cmd/nerdctl/main_unix.go +++ b/cmd/nerdctl/main_unix.go @@ -19,11 +19,12 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/spf13/cobra" ) func shellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { diff --git a/cmd/nerdctl/namespace.go b/cmd/nerdctl/namespace.go index 20d188f3f57..ecd41989026 100644 --- a/cmd/nerdctl/namespace.go +++ b/cmd/nerdctl/namespace.go @@ -23,11 +23,12 @@ import ( "strings" "text/tabwriter" - "github.com/containerd/containerd/namespaces" + "github.com/spf13/cobra" + + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" - "github.com/spf13/cobra" ) func newNamespaceCommand() *cobra.Command { diff --git a/cmd/nerdctl/namespace_create.go b/cmd/nerdctl/namespace_create.go index ae4b9e08b68..ee77ba54daf 100644 --- a/cmd/nerdctl/namespace_create.go +++ b/cmd/nerdctl/namespace_create.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" - "github.com/spf13/cobra" ) func newNamespaceCreateCommand() *cobra.Command { diff --git a/cmd/nerdctl/namespace_inspect.go b/cmd/nerdctl/namespace_inspect.go index 669d2002a60..5df289b35f1 100644 --- a/cmd/nerdctl/namespace_inspect.go +++ b/cmd/nerdctl/namespace_inspect.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" - "github.com/spf13/cobra" ) func newNamespaceInspectCommand() *cobra.Command { diff --git a/cmd/nerdctl/namespace_update.go b/cmd/nerdctl/namespace_update.go index aeabcf3aef7..782d43d7b4f 100644 --- a/cmd/nerdctl/namespace_update.go +++ b/cmd/nerdctl/namespace_update.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" - "github.com/spf13/cobra" ) func newNamespacelabelUpdateCommand() *cobra.Command { diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index c5fba0cac6b..9cb0191f35e 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -19,12 +19,12 @@ package main import ( "fmt" - "github.com/containerd/containerd/identifiers" + "github.com/spf13/cobra" + + "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" "github.com/containerd/nerdctl/v2/pkg/strutil" - - "github.com/spf13/cobra" ) func newNetworkCreateCommand() *cobra.Command { diff --git a/cmd/nerdctl/network_inspect.go b/cmd/nerdctl/network_inspect.go index f1cf21d1c9e..ad3bb6eaa91 100644 --- a/cmd/nerdctl/network_inspect.go +++ b/cmd/nerdctl/network_inspect.go @@ -17,9 +17,10 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" - "github.com/spf13/cobra" ) func newNetworkInspectCommand() *cobra.Command { diff --git a/cmd/nerdctl/network_list.go b/cmd/nerdctl/network_list.go index 0e98257f492..de0f35e5d54 100644 --- a/cmd/nerdctl/network_list.go +++ b/cmd/nerdctl/network_list.go @@ -17,9 +17,10 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" - "github.com/spf13/cobra" ) func newNetworkLsCommand() *cobra.Command { diff --git a/cmd/nerdctl/network_prune.go b/cmd/nerdctl/network_prune.go index 89e24ad2cf4..6e1430b22e7 100644 --- a/cmd/nerdctl/network_prune.go +++ b/cmd/nerdctl/network_prune.go @@ -20,10 +20,11 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/network" - "github.com/spf13/cobra" ) var networkDriversToKeep = []string{"host", "none", DefaultNetworkDriver} diff --git a/cmd/nerdctl/network_remove_linux_test.go b/cmd/nerdctl/network_remove_linux_test.go index 9ac5267a46a..eed01050c36 100644 --- a/cmd/nerdctl/network_remove_linux_test.go +++ b/cmd/nerdctl/network_remove_linux_test.go @@ -19,10 +19,11 @@ package main import ( "testing" - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/vishvananda/netlink" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestNetworkRemove(t *testing.T) { diff --git a/cmd/nerdctl/system_events.go b/cmd/nerdctl/system_events.go index db41ab17dba..3754279cea2 100644 --- a/cmd/nerdctl/system_events.go +++ b/cmd/nerdctl/system_events.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/system" - "github.com/spf13/cobra" ) func newEventsCommand() *cobra.Command { diff --git a/cmd/nerdctl/system_prune.go b/cmd/nerdctl/system_prune.go index bfe1b8257d3..f521d223381 100644 --- a/cmd/nerdctl/system_prune.go +++ b/cmd/nerdctl/system_prune.go @@ -20,11 +20,12 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/system" - "github.com/spf13/cobra" ) func newSystemPruneCommand() *cobra.Command { diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume_create.go index c2c7f8ab760..55d50b7b3ec 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume_create.go @@ -19,11 +19,11 @@ package main import ( "fmt" + "github.com/spf13/cobra" + "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" - - "github.com/spf13/cobra" ) func newVolumeCreateCommand() *cobra.Command { diff --git a/cmd/nerdctl/volume_inspect.go b/cmd/nerdctl/volume_inspect.go index 302b047f734..9c76242b7f3 100644 --- a/cmd/nerdctl/volume_inspect.go +++ b/cmd/nerdctl/volume_inspect.go @@ -17,9 +17,10 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" - "github.com/spf13/cobra" ) func newVolumeInspectCommand() *cobra.Command { diff --git a/cmd/nerdctl/volume_list.go b/cmd/nerdctl/volume_list.go index 5f01f6c5146..b0a7f0783e1 100644 --- a/cmd/nerdctl/volume_list.go +++ b/cmd/nerdctl/volume_list.go @@ -17,11 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - - "github.com/spf13/cobra" ) func newVolumeLsCommand() *cobra.Command { diff --git a/cmd/nerdctl/volume_prune.go b/cmd/nerdctl/volume_prune.go index a6fa42392e9..1cc8d1168ce 100644 --- a/cmd/nerdctl/volume_prune.go +++ b/cmd/nerdctl/volume_prune.go @@ -20,10 +20,11 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" - "github.com/spf13/cobra" ) func newVolumePruneCommand() *cobra.Command { diff --git a/cmd/nerdctl/volume_remove.go b/cmd/nerdctl/volume_remove.go index 0d237c10b6f..4acc340e172 100644 --- a/cmd/nerdctl/volume_remove.go +++ b/cmd/nerdctl/volume_remove.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" - "github.com/spf13/cobra" ) func newVolumeRmCommand() *cobra.Command { diff --git a/go.mod b/go.mod index 39a7716776b..0186bab9329 100644 --- a/go.mod +++ b/go.mod @@ -1,28 +1,33 @@ module github.com/containerd/nerdctl/v2 -go 1.21.12 +go 1.22.0 + +// FIXME: +// github.com/docker/docker/pkg/sysinfo has been replaced by a fork kept under ./pkg2/sysinfo +// as Moby is not going to move to containerd v2 anytime soon or fix these transient dependencies. +// We should still move back to upstream in the future, and remove our copy. require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.5 github.com/compose-spec/compose-go/v2 v2.1.6 - github.com/containerd/accelerated-container-image v1.1.4 + github.com/containerd/accelerated-container-image v1.1.5-0.20240712041225-3c4dd559fed4 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd v1.7.20 - github.com/containerd/containerd/api v1.7.19 + github.com/containerd/containerd/api v1.8.0-rc.2 + github.com/containerd/containerd/v2 v2.0.0-rc.3 github.com/containerd/continuity v0.4.3 github.com/containerd/errdefs v0.1.0 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.10 - github.com/containerd/imgcrypt v1.1.11 + github.com/containerd/imgcrypt v1.2.0-rc1.0.20240709223013-f3769dc3e47f github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.14.0 + github.com/containerd/nydus-snapshotter v0.14.1-0.20240806063146-8fa319bfe9c5 github.com/containerd/platforms v0.2.1 - github.com/containerd/stargz-snapshotter v0.15.1 - github.com/containerd/stargz-snapshotter/estargz v0.15.1 - github.com/containerd/stargz-snapshotter/ipfs v0.15.1 + github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 + github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319 + github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319 github.com/containerd/typeurl/v2 v2.2.0 github.com/containernetworking/cni v1.2.3 github.com/containernetworking/plugins v1.5.1 @@ -43,6 +48,7 @@ require ( github.com/mattn/go-isatty v0.0.20 github.com/mitchellh/mapstructure v1.5.0 github.com/moby/sys/mount v0.3.4 + github.com/moby/sys/mountinfo v0.7.2 github.com/moby/sys/signal v0.7.1 github.com/moby/term v0.5.0 github.com/muesli/cancelreader v0.2.2 @@ -69,20 +75,19 @@ require ( ) require ( - github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect - github.com/cilium/ebpf v0.15.0 // indirect + github.com/cilium/ebpf v0.16.0 // indirect github.com/containerd/go-runc v1.1.0 // indirect + github.com/containerd/plugin v0.1.0 // indirect github.com/containerd/ttrpc v1.2.5 // indirect - github.com/containerd/typeurl v1.0.2 // indirect github.com/containers/ocicrypt v1.2.0 // indirect github.com/djherbis/times v1.6.0 // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect - github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-jose/go-jose/v4 v4.0.3 // indirect + github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-viper/mapstructure/v2 v2.0.0 // indirect @@ -91,9 +96,6 @@ 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.6.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -103,10 +105,9 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/locker v1.0.1 // indirect - github.com/moby/sys/mountinfo v0.7.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.1.0 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/symlink v0.3.0 // indirect + github.com/moby/sys/user v0.2.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect @@ -114,14 +115,14 @@ require ( github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-varint v0.0.7 // indirect + github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect github.com/opencontainers/selinux v1.11.0 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/procfs v0.12.0 // 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-20230803200340-78284954bff6 // indirect + github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/tinylib/msgp v1.2.0 // indirect github.com/vbatts/tar-split v0.11.5 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect @@ -133,10 +134,13 @@ require ( go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect - golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect - google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect + golang.org/x/mod v0.20.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect lukechampine.com/blake3 v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect + tags.cncf.io/container-device-interface v0.8.0 // indirect + tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect ) diff --git a/go.sum b/go.sum index 25609ee8fe3..0e67e74e1ed 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= @@ -14,25 +14,27 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.5 h1:bpTInLlDy/nDRWFVcefDZZ1+U8tS+rz3MxjKgu9boo0= github.com/Microsoft/hcsshim v0.12.5/go.mod h1:tIUGego4G1EN5Hb6KC90aDYiUI2dqLSTTOCjVNpOgZ8= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk= -github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso= +github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= +github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/compose-spec/compose-go/v2 v2.1.6 h1:d0Cs0DffmOwmSzs0YPHwKCskknGq2jfGg4uGowlEpps= github.com/compose-spec/compose-go/v2 v2.1.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= -github.com/containerd/accelerated-container-image v1.1.4 h1:9iFHrNRSFnta1A4z6HP1MVD7vH3hEd7jvJv9wnHHJHc= -github.com/containerd/accelerated-container-image v1.1.4/go.mod h1:9mpTpL4W4yAsq2giHgo4B7wTFJgE59qCPh7dZTSpGCA= +github.com/containerd/accelerated-container-image v1.1.5-0.20240712041225-3c4dd559fed4 h1:9anPRQFoKFkeWr++u+fMOLR2srAjIRms7dqbrouLAXo= +github.com/containerd/accelerated-container-image v1.1.5-0.20240712041225-3c4dd559fed4/go.mod h1:BbY0iTEYD6XZV84E99yjUbs46EGI0CVQrjqb/Wgx9nE= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= 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.20 h1:Sl6jQYk3TRavaU83h66QMbI2Nqg9Jm6qzwX57Vsn1SQ= -github.com/containerd/containerd v1.7.20/go.mod h1:52GsS5CwquuqPuLncsXwG0t2CiUce+KsNHJZQJvAgR0= -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/containerd/api v1.8.0-rc.2 h1:EnWLDKWWbIRzuy71L20P3VF/DhxSaDEocsovKPdW5Oo= +github.com/containerd/containerd/api v1.8.0-rc.2/go.mod h1:VgMSK19YOLolP4a1/b5vlVkTo8MzMoLPZnvD1PNWeGg= +github.com/containerd/containerd/v2 v2.0.0-rc.3 h1:rRISeKYnunLx8Byw8FQ/a62mTMtcr6ESGptS4+MwLaQ= +github.com/containerd/containerd/v2 v2.0.0-rc.3/go.mod h1:UBHR1DgWRQcEOINFkR94m0VC0MgKd3qg9LVPnudv9vs= 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= @@ -43,24 +45,24 @@ github.com/containerd/go-cni v1.1.10 h1:c2U73nld7spSWfiJwSh/8W9DK+/qQwYM2rngIhCy github.com/containerd/go-cni v1.1.10/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA= github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U= -github.com/containerd/imgcrypt v1.1.11 h1:3RULIeLouE7B5l9NzMq0HdPWG0DP5deEVxB5UKxyUoU= -github.com/containerd/imgcrypt v1.1.11/go.mod h1:nXL4jp1GrtO758b16DVsxaHHzu9PravAsKARYmyHR58= +github.com/containerd/imgcrypt v1.2.0-rc1.0.20240709223013-f3769dc3e47f h1:VuW2PlwpES6W86asOw+ysYEpARdlPkwpM6DsT4sbv8U= +github.com/containerd/imgcrypt v1.2.0-rc1.0.20240709223013-f3769dc3e47f/go.mod h1:F9roK2DzKlFnV+h+ZJy/r2FoS28bIvxKgdcoV7o8Sms= 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.14.0 h1:6/eAi6d7MjaeLLuMO8Udfe5GVsDudmrDNO4SGETMBco= -github.com/containerd/nydus-snapshotter v0.14.0/go.mod h1:TT4jv2SnIDxEBu4H2YOvWQHPOap031ydTaHTuvc5VQk= +github.com/containerd/nydus-snapshotter v0.14.1-0.20240806063146-8fa319bfe9c5 h1:NpscnGdkmWwlb0o2Q+rDO/kfoLObfY2sHwB6M5uF58Q= +github.com/containerd/nydus-snapshotter v0.14.1-0.20240806063146-8fa319bfe9c5/go.mod h1:t7X6QEMNSz69fl5e2pF56ibd4XJ6KH9dEBrLnSwyYQk= 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/plugin v0.1.0 h1:CYMyZk9beRAIe1FEKItbMLLAz/z16aXrGc+B+nv0fU4= +github.com/containerd/plugin v0.1.0/go.mod h1:j6HlpMtkiZMgT4UsfVNxPBUkwdw9KQGU6nCLfRxnq+w= +github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 h1:Td/dlhRp/kIk9W1rjXHSL87zZZiBQaKPV18OnoEREUA= +github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:dgo5lVziOOnWX8SxxHqYuc8ShsQou54eKLdahxFlHVc= +github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319 h1:BRxgmkGWi5vAvajiCwEK+xit4FeFU3GRjbiX4DKTLtM= +github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:9WSor0wu2swhtYoFkrjy3GHt7aNgKR2A7FhnpP+CH5o= +github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319 h1:WdmIerlurjZSoLI2w8014yzJY+q4qdO/A3ZJBEK7LQA= +github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:L/J/O36DzcGxq3drHM45sJRr/pEQTG5u+tbffVhP6r8= 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.2 h1:Chlt8zIieDbzQFzXzAeBEF92KhExuE4p9p92/QmY7aY= -github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= @@ -79,8 +81,9 @@ github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr github.com/cyphar/filepath-securejoin v0.3.1 h1:1V7cHiaW+C+39wEfpH6XlLBQo3j/PciWFrgfCLS8XrE= github.com/cyphar/filepath-securejoin v0.3.1/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= 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/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= @@ -93,8 +96,6 @@ github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZ github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -111,8 +112,8 @@ github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/ml github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-jose/go-jose/v4 v4.0.3 h1:o8aphO8Hv6RPmH+GfzVuyf7YXSBibp+8YyHdOoDESGo= -github.com/go-jose/go-jose/v4 v4.0.3/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= +github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= +github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -151,13 +152,13 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.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= @@ -167,6 +168,10 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= +github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM= +github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= @@ -184,6 +189,10 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= @@ -192,6 +201,7 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= @@ -200,18 +210,19 @@ github.com/moby/sys/mount v0.3.4 h1:yn5jq4STPztkkzSKpZkLcmjue+bZJ0u2AuQY1iNI1Ww= github.com/moby/sys/mount v0.3.4/go.mod h1:KcQJMbQdJHPlq5lcYT+/CjatWM4PuxKe+XLSVS4J6Os= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= -github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0= github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= -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/symlink v0.3.0 h1:GZX89mEZ9u53f97npBy4Rc3vJKj7JBDj/PN2I22GrNU= +github.com/moby/sys/symlink v0.3.0/go.mod h1:3eNdhduHmYPcgsJtZXW1W4XUJdZGBIkttZ8xKqPUJq0= +github.com/moby/sys/user v0.2.0 h1:OnpapJsRp25vkhw8TFG6OLJODNh/3rEwRWtJ3kakwRM= +github.com/moby/sys/user v0.2.0/go.mod h1:RYstrcWOJpVh+6qzUqp2bU3eaRpdiQeKGlKitaH0PM8= 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= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= @@ -234,20 +245,23 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= 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.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0= +github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI= +github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= @@ -258,6 +272,7 @@ github.com/rootless-containers/bypass4netns v0.4.1/go.mod h1:slu3ygwy1x6ey78oBTN github.com/rootless-containers/rootlesskit/v2 v2.2.0 h1:qTA3QyfsZSKmvKDL7m5lCl55OmJZXmKf381dSb5Ig9E= github.com/rootless-containers/rootlesskit/v2 v2.2.0/go.mod h1:AyUlpgPnMv085smZXp5mt4D9q4mNjbHOcZwaVobRzyU= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -273,6 +288,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -281,8 +297,11 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= +github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= @@ -323,13 +342,15 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -352,11 +373,12 @@ golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -390,10 +412,8 @@ 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-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= -google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 h1:OsSGQeIIsyOEOimVxLEIL4rwGcnrjOydQaiA2bOnZUM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= 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= @@ -425,3 +445,9 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +tags.cncf.io/container-device-interface v0.8.0 h1:8bCFo/g9WODjWx3m6EYl3GfUG31eKJbaggyBDxEldRc= +tags.cncf.io/container-device-interface v0.8.0/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y= +tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA= +tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws= diff --git a/pkg/apparmorutil/apparmorutil_linux.go b/pkg/apparmorutil/apparmorutil_linux.go index 38ea38c7f2d..aea0d321b47 100644 --- a/pkg/apparmorutil/apparmorutil_linux.go +++ b/pkg/apparmorutil/apparmorutil_linux.go @@ -23,8 +23,8 @@ import ( "strings" "sync" - "github.com/containerd/containerd/pkg/apparmor" - "github.com/containerd/containerd/pkg/userns" + "github.com/containerd/containerd/v2/pkg/apparmor" + "github.com/containerd/containerd/v2/pkg/userns" "github.com/containerd/log" ) diff --git a/pkg/bypass4netnsutil/bypass4netnsutil.go b/pkg/bypass4netnsutil/bypass4netnsutil.go index 6ba7c383a79..0d67e2c0546 100644 --- a/pkg/bypass4netnsutil/bypass4netnsutil.go +++ b/pkg/bypass4netnsutil/bypass4netnsutil.go @@ -23,8 +23,8 @@ import ( "path/filepath" "strconv" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/annotations" "github.com/opencontainers/runtime-spec/specs-go" b4nnoci "github.com/rootless-containers/bypass4netns/pkg/oci" diff --git a/pkg/cioutil/container_io.go b/pkg/cioutil/container_io.go index 24fb89186ba..1b0b1a01bfb 100644 --- a/pkg/cioutil/container_io.go +++ b/pkg/cioutil/container_io.go @@ -29,9 +29,9 @@ import ( "syscall" "time" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/defaults" - "github.com/containerd/containerd/pkg/process" + "github.com/containerd/containerd/v2/cmd/containerd-shim-runc-v2/process" + "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/containerd/v2/pkg/cio" ) const binaryIOProcTermTimeout = 12 * time.Second // Give logger process 10 seconds for cleanup diff --git a/pkg/cioutil/container_io_unix.go b/pkg/cioutil/container_io_unix.go index 1749a018c98..c9d23110940 100644 --- a/pkg/cioutil/container_io_unix.go +++ b/pkg/cioutil/container_io_unix.go @@ -26,7 +26,7 @@ import ( "sync" "syscall" - "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/fifo" ) diff --git a/pkg/cioutil/container_io_windows.go b/pkg/cioutil/container_io_windows.go index 6dde42f12a6..97e521b2c7f 100644 --- a/pkg/cioutil/container_io_windows.go +++ b/pkg/cioutil/container_io_windows.go @@ -22,7 +22,7 @@ import ( "os/exec" "github.com/Microsoft/go-winio" - "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" ) diff --git a/pkg/clientutil/client.go b/pkg/clientutil/client.go index 03a6105247b..2e4043eb6f0 100644 --- a/pkg/clientutil/client.go +++ b/pkg/clientutil/client.go @@ -24,8 +24,8 @@ import ( "runtime" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/namespaces" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/systemutil" @@ -33,8 +33,7 @@ import ( "github.com/opencontainers/go-digest" ) -func NewClient(ctx context.Context, namespace, address string, opts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { - +func NewClient(ctx context.Context, namespace, address string, opts ...containerd.Opt) (*containerd.Client, context.Context, context.CancelFunc, error) { ctx = namespaces.WithNamespace(ctx, namespace) address = strings.TrimPrefix(address, "unix://") @@ -56,7 +55,7 @@ func NewClient(ctx context.Context, namespace, address string, opts ...container return client, ctx, cancel, nil } -func NewClientWithPlatform(ctx context.Context, namespace, address, platform string, clientOpts ...containerd.ClientOpt) (*containerd.Client, context.Context, context.CancelFunc, error) { +func NewClientWithPlatform(ctx context.Context, namespace, address, platform string, clientOpts ...containerd.Opt) (*containerd.Client, context.Context, context.CancelFunc, error) { if platform != "" { if canExec, canExecErr := platformutil.CanExecProbably(platform); !canExec { warn := fmt.Sprintf("Platform %q seems incompatible with the host platform %q. If you see \"exec format error\", see https://github.com/containerd/nerdctl/blob/main/docs/multi-platform.md", diff --git a/pkg/cmd/apparmor/inspect_linux.go b/pkg/cmd/apparmor/inspect_linux.go index e24dc1f0a27..53e2652be4d 100644 --- a/pkg/cmd/apparmor/inspect_linux.go +++ b/pkg/cmd/apparmor/inspect_linux.go @@ -19,7 +19,7 @@ package apparmor import ( "fmt" - "github.com/containerd/containerd/contrib/apparmor" + "github.com/containerd/containerd/v2/contrib/apparmor" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/defaults" ) diff --git a/pkg/cmd/apparmor/load_linux.go b/pkg/cmd/apparmor/load_linux.go index aace881f288..73bf9f93d98 100644 --- a/pkg/cmd/apparmor/load_linux.go +++ b/pkg/cmd/apparmor/load_linux.go @@ -17,7 +17,7 @@ package apparmor import ( - "github.com/containerd/containerd/contrib/apparmor" + "github.com/containerd/containerd/v2/contrib/apparmor" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/defaults" ) diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index e5df76cf27e..449b5f2b998 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -28,9 +28,9 @@ import ( "strconv" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/images/archive" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/images/archive" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index aff935ad08d..0c57aaf869c 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -23,7 +23,7 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" diff --git a/pkg/cmd/container/attach.go b/pkg/cmd/container/attach.go index c7fda751628..31b480770f9 100644 --- a/pkg/cmd/container/attach.go +++ b/pkg/cmd/container/attach.go @@ -22,8 +22,8 @@ import ( "fmt" "github.com/containerd/console" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/consoleutil" diff --git a/pkg/cmd/container/commit.go b/pkg/cmd/container/commit.go index 4a6a98bc110..1814b926ebe 100644 --- a/pkg/cmd/container/commit.go +++ b/pkg/cmd/container/commit.go @@ -22,7 +22,7 @@ import ( "fmt" "strings" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/cp_linux.go b/pkg/cmd/container/cp_linux.go index 79466203894..19b8a69c8da 100644 --- a/pkg/cmd/container/cp_linux.go +++ b/pkg/cmd/container/cp_linux.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 22de1bc4135..1b8c3538293 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -29,10 +29,10 @@ import ( "strconv" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/cio" + "github.com/containerd/containerd/v2/pkg/oci" gocni "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/annotations" diff --git a/pkg/cmd/container/exec.go b/pkg/cmd/container/exec.go index 8beefcf1091..6fce2849d04 100644 --- a/pkg/cmd/container/exec.go +++ b/pkg/cmd/container/exec.go @@ -23,8 +23,8 @@ import ( "os" "github.com/containerd/console" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/consoleutil" diff --git a/pkg/cmd/container/exec_linux.go b/pkg/cmd/container/exec_linux.go index 28fb7c09028..cd3997020b0 100644 --- a/pkg/cmd/container/exec_linux.go +++ b/pkg/cmd/container/exec_linux.go @@ -17,7 +17,7 @@ package container import ( - "github.com/containerd/containerd/pkg/cap" + "github.com/containerd/containerd/v2/pkg/cap" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/cmd/container/inspect.go b/pkg/cmd/container/inspect.go index 564159e2a74..2e2c399c221 100644 --- a/pkg/cmd/container/inspect.go +++ b/pkg/cmd/container/inspect.go @@ -21,8 +21,8 @@ import ( "fmt" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/snapshots" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerdutil" diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index cc97c1dd0f7..661e465d6c8 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -24,8 +24,8 @@ import ( "strings" "syscall" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/errdefs" gocni "github.com/containerd/go-cni" "github.com/containerd/log" diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index f30d73a4991..206574d391c 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -24,9 +24,9 @@ import ( "strings" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/pkg/progress" - "github.com/containerd/containerd/snapshots" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/progress" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/cmd/container/list_util.go b/pkg/cmd/container/list_util.go index 50f1f8b7251..b1b1906b254 100644 --- a/pkg/cmd/container/list_util.go +++ b/pkg/cmd/container/list_util.go @@ -23,8 +23,8 @@ import ( "strings" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/containerutil" ) diff --git a/pkg/cmd/container/logs.go b/pkg/cmd/container/logs.go index a20dcd9fb86..1d9193e804b 100644 --- a/pkg/cmd/container/logs.go +++ b/pkg/cmd/container/logs.go @@ -23,7 +23,7 @@ import ( "os/signal" "syscall" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/cmd/container/pause.go b/pkg/cmd/container/pause.go index 11bcbd02613..0e3664ca7d1 100644 --- a/pkg/cmd/container/pause.go +++ b/pkg/cmd/container/pause.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/prune.go b/pkg/cmd/container/prune.go index cc36e77a126..3e6d33fba44 100644 --- a/pkg/cmd/container/prune.go +++ b/pkg/cmd/container/prune.go @@ -22,7 +22,7 @@ import ( "fmt" "strings" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index c86cfeff46d..d62130e0f83 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -25,9 +25,9 @@ import ( "runtime" "syscall" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/namespaces" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/cio" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/cmd/container/rename.go b/pkg/cmd/container/rename.go index 959bf68152e..cc9cf145fe8 100644 --- a/pkg/cmd/container/rename.go +++ b/pkg/cmd/container/rename.go @@ -21,7 +21,7 @@ import ( "fmt" "runtime" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" diff --git a/pkg/cmd/container/restart.go b/pkg/cmd/container/restart.go index a24a5f641d3..a67093c7122 100644 --- a/pkg/cmd/container/restart.go +++ b/pkg/cmd/container/restart.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/run_cgroup_freebsd.go b/pkg/cmd/container/run_cgroup_freebsd.go index fcf07cb7bb2..b250500f6cb 100644 --- a/pkg/cmd/container/run_cgroup_freebsd.go +++ b/pkg/cmd/container/run_cgroup_freebsd.go @@ -17,7 +17,7 @@ package container import ( - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/container/run_cgroup_linux.go b/pkg/cmd/container/run_cgroup_linux.go index b81b3c3c382..c979dd18bc8 100644 --- a/pkg/cmd/container/run_cgroup_linux.go +++ b/pkg/cmd/container/run_cgroup_linux.go @@ -23,8 +23,8 @@ import ( "path/filepath" "strings" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/infoutil" diff --git a/pkg/cmd/container/run_cgroup_windows.go b/pkg/cmd/container/run_cgroup_windows.go index fcf07cb7bb2..b250500f6cb 100644 --- a/pkg/cmd/container/run_cgroup_windows.go +++ b/pkg/cmd/container/run_cgroup_windows.go @@ -17,7 +17,7 @@ package container import ( - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/container/run_freebsd.go b/pkg/cmd/container/run_freebsd.go index 87a07a12753..962f74ad6fc 100644 --- a/pkg/cmd/container/run_freebsd.go +++ b/pkg/cmd/container/run_freebsd.go @@ -19,9 +19,9 @@ package container import ( "context" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/container/run_gpus.go b/pkg/cmd/container/run_gpus.go index 9c3891c053d..da8245299d4 100644 --- a/pkg/cmd/container/run_gpus.go +++ b/pkg/cmd/container/run_gpus.go @@ -23,8 +23,8 @@ import ( "strconv" "strings" - "github.com/containerd/containerd/contrib/nvidia" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/contrib/nvidia" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) diff --git a/pkg/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index 89fdb73cd8d..f1ac8099451 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -21,10 +21,10 @@ import ( "fmt" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/userns" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/containerd/v2/pkg/userns" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/bypass4netnsutil" diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index 0fc0c216612..c533692b279 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -28,12 +28,12 @@ import ( "strings" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/userns" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/containerd/v2/pkg/userns" "github.com/containerd/continuity/fs" "github.com/containerd/errdefs" "github.com/containerd/log" diff --git a/pkg/cmd/container/run_restart.go b/pkg/cmd/container/run_restart.go index b300dc0698d..d7b97d09389 100644 --- a/pkg/cmd/container/run_restart.go +++ b/pkg/cmd/container/run_restart.go @@ -21,8 +21,8 @@ import ( "fmt" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/runtime/restart" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/runtime/restart" "github.com/containerd/nerdctl/v2/pkg/strutil" ) @@ -32,7 +32,7 @@ func checkRestartCapabilities(ctx context.Context, client *containerd.Client, re case "", "no": return true, nil } - res, err := client.IntrospectionService().Plugins(ctx, []string{"id==restart"}) + res, err := client.IntrospectionService().Plugins(ctx, "id==restart") if err != nil { return false, err } diff --git a/pkg/cmd/container/run_runtime.go b/pkg/cmd/container/run_runtime.go index 279a10be629..94bb9acc165 100644 --- a/pkg/cmd/container/run_runtime.go +++ b/pkg/cmd/container/run_runtime.go @@ -20,17 +20,17 @@ import ( "context" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/plugin" - runcoptions "github.com/containerd/containerd/runtime/v2/runc/options" + runcoptions "github.com/containerd/containerd/api/types/runc/options" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/containerd/v2/plugins" "github.com/containerd/log" "github.com/opencontainers/runtime-spec/specs-go" ) func generateRuntimeCOpts(cgroupManager, runtimeStr string) ([]containerd.NewContainerOpts, error) { - runtime := plugin.RuntimeRuncV2 + runtime := plugins.RuntimeRuncV2 var ( runcOpts runcoptions.Options runtimeOpts interface{} = &runcOpts diff --git a/pkg/cmd/container/run_security_linux.go b/pkg/cmd/container/run_security_linux.go index 5b74cce49f9..3681c6845a1 100644 --- a/pkg/cmd/container/run_security_linux.go +++ b/pkg/cmd/container/run_security_linux.go @@ -21,10 +21,10 @@ import ( "strings" "sync" - "github.com/containerd/containerd/contrib/apparmor" - "github.com/containerd/containerd/contrib/seccomp" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/cap" + "github.com/containerd/containerd/v2/contrib/apparmor" + "github.com/containerd/containerd/v2/contrib/seccomp" + "github.com/containerd/containerd/v2/pkg/cap" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/apparmorutil" "github.com/containerd/nerdctl/v2/pkg/defaults" diff --git a/pkg/cmd/container/run_ulimit.go b/pkg/cmd/container/run_ulimit.go index 5b825a7ec16..6a83ea9f72d 100644 --- a/pkg/cmd/container/run_ulimit.go +++ b/pkg/cmd/container/run_ulimit.go @@ -20,8 +20,8 @@ import ( "context" "strings" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/pkg/cmd/container/run_user.go b/pkg/cmd/container/run_user.go index 7bc9324694b..f03342897e5 100644 --- a/pkg/cmd/container/run_user.go +++ b/pkg/cmd/container/run_user.go @@ -21,8 +21,8 @@ import ( "fmt" "strconv" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/oci" ) func generateUserOpts(user string) ([]oci.SpecOpts, error) { diff --git a/pkg/cmd/container/run_windows.go b/pkg/cmd/container/run_windows.go index 4e2f5fe07b5..7c550cc2a8b 100644 --- a/pkg/cmd/container/run_windows.go +++ b/pkg/cmd/container/run_windows.go @@ -22,9 +22,9 @@ import ( "fmt" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/pkg/cmd/container/start.go b/pkg/cmd/container/start.go index 926c521f6df..a29f900c831 100644 --- a/pkg/cmd/container/start.go +++ b/pkg/cmd/container/start.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/stats.go b/pkg/cmd/container/stats.go index 129480cb7c2..b36ae484eb2 100644 --- a/pkg/cmd/container/stats.go +++ b/pkg/cmd/container/stats.go @@ -27,9 +27,9 @@ import ( "text/template" "time" - "github.com/containerd/containerd" eventstypes "github.com/containerd/containerd/api/events" - "github.com/containerd/containerd/events" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/events" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/cmd/container/stop.go b/pkg/cmd/container/stop.go index 59104016c3d..a385cbd4bec 100644 --- a/pkg/cmd/container/stop.go +++ b/pkg/cmd/container/stop.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" diff --git a/pkg/cmd/container/top.go b/pkg/cmd/container/top.go index 2f4cae35c4c..d73fa02dcdb 100644 --- a/pkg/cmd/container/top.go +++ b/pkg/cmd/container/top.go @@ -32,7 +32,7 @@ import ( "strconv" "strings" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) diff --git a/pkg/cmd/container/top_unix.go b/pkg/cmd/container/top_unix.go index e5f04ef60d1..0504849673c 100644 --- a/pkg/cmd/container/top_unix.go +++ b/pkg/cmd/container/top_unix.go @@ -37,7 +37,7 @@ import ( "strings" "text/tabwriter" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" ) // containerTop was inspired from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L133-L189 diff --git a/pkg/cmd/container/top_windows.go b/pkg/cmd/container/top_windows.go index d5f68a35db9..eee445ae4b6 100644 --- a/pkg/cmd/container/top_windows.go +++ b/pkg/cmd/container/top_windows.go @@ -26,7 +26,7 @@ import ( "time" "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/typeurl/v2" "github.com/docker/go-units" ) diff --git a/pkg/cmd/container/unpause.go b/pkg/cmd/container/unpause.go index f0e6325e81f..bd6ba750d8e 100644 --- a/pkg/cmd/container/unpause.go +++ b/pkg/cmd/container/unpause.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/wait.go b/pkg/cmd/container/wait.go index f726f81cd3a..31bd2daaf79 100644 --- a/pkg/cmd/container/wait.go +++ b/pkg/cmd/container/wait.go @@ -22,7 +22,7 @@ import ( "fmt" "io" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) diff --git a/pkg/cmd/image/convert.go b/pkg/cmd/image/convert.go index 0cb9c560f8c..cbbbe60d8eb 100644 --- a/pkg/cmd/image/convert.go +++ b/pkg/cmd/image/convert.go @@ -26,11 +26,11 @@ import ( "strings" overlaybdconvert "github.com/containerd/accelerated-container-image/pkg/convertor" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/images/converter" - "github.com/containerd/containerd/images/converter/uncompress" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/images/converter" + "github.com/containerd/containerd/v2/core/images/converter/uncompress" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" diff --git a/pkg/cmd/image/crypt.go b/pkg/cmd/image/crypt.go index be134fcf972..a4f967b5726 100644 --- a/pkg/cmd/image/crypt.go +++ b/pkg/cmd/image/crypt.go @@ -21,9 +21,9 @@ import ( "errors" "fmt" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images/converter" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images/converter" "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/imgcrypt/images/encryption/parsehelpers" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/cmd/image/inspect.go b/pkg/cmd/image/inspect.go index aa54de9acb5..cd864fd2653 100644 --- a/pkg/cmd/image/inspect.go +++ b/pkg/cmd/image/inspect.go @@ -23,8 +23,8 @@ import ( "strings" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerdutil" diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 58f030deffa..aaae4d62adb 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -29,10 +29,10 @@ import ( "text/template" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/snapshots" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerdutil" diff --git a/pkg/cmd/image/load.go b/pkg/cmd/image/load.go index 1008900c88d..78b46b0dd8c 100644 --- a/pkg/cmd/image/load.go +++ b/pkg/cmd/image/load.go @@ -23,10 +23,10 @@ import ( "io" "os" - "github.com/containerd/containerd" - "github.com/containerd/containerd/archive/compression" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/images/archive" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/images/archive" + "github.com/containerd/containerd/v2/pkg/archive/compression" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" diff --git a/pkg/cmd/image/prune.go b/pkg/cmd/image/prune.go index f290925f689..d31e8aea005 100644 --- a/pkg/cmd/image/prune.go +++ b/pkg/cmd/image/prune.go @@ -20,8 +20,8 @@ import ( "context" "fmt" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil" diff --git a/pkg/cmd/image/pull.go b/pkg/cmd/image/pull.go index 8289057cb2a..7dd3c534748 100644 --- a/pkg/cmd/image/pull.go +++ b/pkg/cmd/image/pull.go @@ -22,7 +22,7 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/ipfs" diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index f8f2348b683..3c28cd91d40 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -23,14 +23,14 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/images/converter" - "github.com/containerd/containerd/reference" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" - dockerconfig "github.com/containerd/containerd/remotes/docker/config" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/images/converter" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + dockerconfig "github.com/containerd/containerd/v2/core/remotes/docker/config" + "github.com/containerd/containerd/v2/pkg/reference" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/errutil" diff --git a/pkg/cmd/image/remove.go b/pkg/cmd/image/remove.go index 824cd404cd6..53bd8b02a25 100644 --- a/pkg/cmd/image/remove.go +++ b/pkg/cmd/image/remove.go @@ -22,8 +22,8 @@ import ( "fmt" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" diff --git a/pkg/cmd/image/save.go b/pkg/cmd/image/save.go index db910323a89..8d6a2601269 100644 --- a/pkg/cmd/image/save.go +++ b/pkg/cmd/image/save.go @@ -20,8 +20,8 @@ import ( "context" "fmt" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images/archive" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images/archive" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/platformutil" diff --git a/pkg/cmd/image/tag.go b/pkg/cmd/image/tag.go index 0c4030e1342..ae450408165 100644 --- a/pkg/cmd/image/tag.go +++ b/pkg/cmd/image/tag.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 64573c7e0e5..744a7b5a256 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -27,18 +27,19 @@ import ( "os" "strings" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/remotes/docker/config" - "github.com/containerd/log" - "github.com/containerd/nerdctl/v2/pkg/api/types" - "github.com/containerd/nerdctl/v2/pkg/errutil" - "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" dockercliconfig "github.com/docker/cli/cli/config" dockercliconfigtypes "github.com/docker/cli/cli/config/types" "github.com/docker/docker/api/types/registry" "github.com/docker/docker/errdefs" "golang.org/x/net/context/ctxhttp" "golang.org/x/term" + + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes/docker/config" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/errutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" ) const unencryptedPasswordWarning = `WARNING: Your password will be stored unencrypted in %s. diff --git a/pkg/cmd/namespace/create.go b/pkg/cmd/namespace/create.go index 6f79e999797..91fef5fd094 100644 --- a/pkg/cmd/namespace/create.go +++ b/pkg/cmd/namespace/create.go @@ -19,7 +19,7 @@ package namespace import ( "context" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/namespace/inspect.go b/pkg/cmd/namespace/inspect.go index 3f602ef6187..761891692b9 100644 --- a/pkg/cmd/namespace/inspect.go +++ b/pkg/cmd/namespace/inspect.go @@ -19,8 +19,8 @@ package namespace import ( "context" - "github.com/containerd/containerd" - "github.com/containerd/containerd/namespaces" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" diff --git a/pkg/cmd/namespace/namespace_freebsd.go b/pkg/cmd/namespace/namespace_freebsd.go index a5448749201..a3a45d59168 100644 --- a/pkg/cmd/namespace/namespace_freebsd.go +++ b/pkg/cmd/namespace/namespace_freebsd.go @@ -17,7 +17,7 @@ package namespace import ( - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/pkg/namespaces" ) func namespaceDeleteOpts(cgroup bool) ([]namespaces.DeleteOpts, error) { diff --git a/pkg/cmd/namespace/namespace_linux.go b/pkg/cmd/namespace/namespace_linux.go index e13b331fa95..96255cdcb5e 100644 --- a/pkg/cmd/namespace/namespace_linux.go +++ b/pkg/cmd/namespace/namespace_linux.go @@ -17,8 +17,8 @@ package namespace import ( - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/runtime/opts" + "github.com/containerd/containerd/v2/core/runtime/opts" + "github.com/containerd/containerd/v2/pkg/namespaces" ) func namespaceDeleteOpts(cgroup bool) ([]namespaces.DeleteOpts, error) { diff --git a/pkg/cmd/namespace/namespace_windows.go b/pkg/cmd/namespace/namespace_windows.go index a5448749201..a3a45d59168 100644 --- a/pkg/cmd/namespace/namespace_windows.go +++ b/pkg/cmd/namespace/namespace_windows.go @@ -17,7 +17,7 @@ package namespace import ( - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/pkg/namespaces" ) func namespaceDeleteOpts(cgroup bool) ([]namespaces.DeleteOpts, error) { diff --git a/pkg/cmd/namespace/remove.go b/pkg/cmd/namespace/remove.go index ecb24e10e9e..e4b1f9c24f5 100644 --- a/pkg/cmd/namespace/remove.go +++ b/pkg/cmd/namespace/remove.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/cmd/namespace/update.go b/pkg/cmd/namespace/update.go index 3952f98a6cc..46694342af3 100644 --- a/pkg/cmd/namespace/update.go +++ b/pkg/cmd/namespace/update.go @@ -19,7 +19,7 @@ package namespace import ( "context" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/network/prune.go b/pkg/cmd/network/prune.go index 9294583947c..f5063463a9f 100644 --- a/pkg/cmd/network/prune.go +++ b/pkg/cmd/network/prune.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/netutil" diff --git a/pkg/cmd/network/remove.go b/pkg/cmd/network/remove.go index 133a2b47bba..c50d1649528 100644 --- a/pkg/cmd/network/remove.go +++ b/pkg/cmd/network/remove.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/netwalker" "github.com/containerd/nerdctl/v2/pkg/netutil" diff --git a/pkg/cmd/system/events.go b/pkg/cmd/system/events.go index 08a890e3942..c72191a7372 100644 --- a/pkg/cmd/system/events.go +++ b/pkg/cmd/system/events.go @@ -26,9 +26,9 @@ import ( "text/template" "time" - "github.com/containerd/containerd" _ "github.com/containerd/containerd/api/events" // Register grpc event types - "github.com/containerd/containerd/events" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/events" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" diff --git a/pkg/cmd/system/info.go b/pkg/cmd/system/info.go index 6fce7d68334..6d43f063a4c 100644 --- a/pkg/cmd/system/info.go +++ b/pkg/cmd/system/info.go @@ -24,13 +24,13 @@ import ( "strings" "text/template" - "github.com/containerd/containerd" - "github.com/containerd/containerd/api/services/introspection/v1" - "github.com/containerd/log" "github.com/docker/go-units" "golang.org/x/text/cases" "golang.org/x/text/language" + "github.com/containerd/containerd/api/services/introspection/v1" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/infoutil" diff --git a/pkg/cmd/system/prune.go b/pkg/cmd/system/prune.go index efc1d934261..71c4cfa85d6 100644 --- a/pkg/cmd/system/prune.go +++ b/pkg/cmd/system/prune.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/builder" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/pkg/cmd/volume/list.go b/pkg/cmd/volume/list.go index a0e275a10c0..e005d886a6a 100644 --- a/pkg/cmd/volume/list.go +++ b/pkg/cmd/volume/list.go @@ -25,7 +25,7 @@ import ( "text/tabwriter" "text/template" - "github.com/containerd/containerd/pkg/progress" + "github.com/containerd/containerd/v2/pkg/progress" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" diff --git a/pkg/cmd/volume/prune.go b/pkg/cmd/volume/prune.go index ab9728be34f..aa051d1cc55 100644 --- a/pkg/cmd/volume/prune.go +++ b/pkg/cmd/volume/prune.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/cmd/volume/rm.go b/pkg/cmd/volume/rm.go index 9333abad302..d7327845cf7 100644 --- a/pkg/cmd/volume/rm.go +++ b/pkg/cmd/volume/rm.go @@ -22,7 +22,7 @@ import ( "errors" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/composer/composer.go b/pkg/composer/composer.go index 16f97efcc93..2adf7459433 100644 --- a/pkg/composer/composer.go +++ b/pkg/composer/composer.go @@ -25,8 +25,8 @@ import ( composecli "github.com/compose-spec/compose-go/v2/cli" compose "github.com/compose-spec/compose-go/v2/types" - "github.com/containerd/containerd" - "github.com/containerd/containerd/identifiers" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/reflectutil" diff --git a/pkg/composer/container.go b/pkg/composer/container.go index 3a0169e74dc..53525457a87 100644 --- a/pkg/composer/container.go +++ b/pkg/composer/container.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/composer/copy.go b/pkg/composer/copy.go index 0442b5775ae..9e90e91e034 100644 --- a/pkg/composer/copy.go +++ b/pkg/composer/copy.go @@ -22,7 +22,7 @@ import ( "fmt" "strings" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/docker/docker/pkg/system" diff --git a/pkg/composer/create.go b/pkg/composer/create.go index f08ee0b50f3..5e261d00f07 100644 --- a/pkg/composer/create.go +++ b/pkg/composer/create.go @@ -23,11 +23,12 @@ import ( "path/filepath" "strings" + "golang.org/x/sync/errgroup" + "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" - "golang.org/x/sync/errgroup" ) // FYI: https://github.com/docker/compose/blob/v2.14.1/pkg/api/api.go#L423 diff --git a/pkg/composer/exec.go b/pkg/composer/exec.go index 1d8ab64f069..df1ae533714 100644 --- a/pkg/composer/exec.go +++ b/pkg/composer/exec.go @@ -24,7 +24,7 @@ import ( "strconv" "strings" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" diff --git a/pkg/composer/kill.go b/pkg/composer/kill.go index 04b14a870c0..204ad30690a 100644 --- a/pkg/composer/kill.go +++ b/pkg/composer/kill.go @@ -19,8 +19,9 @@ package composer import ( "context" - "github.com/containerd/log" "golang.org/x/sync/errgroup" + + "github.com/containerd/log" ) type KillOptions struct { diff --git a/pkg/composer/logs.go b/pkg/composer/logs.go index f1493004d3a..91889692e12 100644 --- a/pkg/composer/logs.go +++ b/pkg/composer/logs.go @@ -25,7 +25,7 @@ import ( "strings" "github.com/compose-spec/compose-go/v2/types" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/pipetagger" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" diff --git a/pkg/composer/orphans.go b/pkg/composer/orphans.go index 2df49253132..ed5028c3da0 100644 --- a/pkg/composer/orphans.go +++ b/pkg/composer/orphans.go @@ -20,7 +20,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/composer/pause.go b/pkg/composer/pause.go index 4817a5710d6..b89bfec4d67 100644 --- a/pkg/composer/pause.go +++ b/pkg/composer/pause.go @@ -22,10 +22,11 @@ import ( "io" "sync" - "github.com/containerd/containerd" + "golang.org/x/sync/errgroup" + + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/labels" - "golang.org/x/sync/errgroup" ) // Pause pauses service containers belonging to `services`. diff --git a/pkg/composer/restart.go b/pkg/composer/restart.go index 7768bb5e20d..d27b981d5dd 100644 --- a/pkg/composer/restart.go +++ b/pkg/composer/restart.go @@ -22,7 +22,7 @@ import ( "sync" "github.com/compose-spec/compose-go/v2/types" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/composer/rm.go b/pkg/composer/rm.go index 86cae7c9000..590028c4d0e 100644 --- a/pkg/composer/rm.go +++ b/pkg/composer/rm.go @@ -21,7 +21,7 @@ import ( "strings" "sync" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/formatter" diff --git a/pkg/composer/run.go b/pkg/composer/run.go index d63b388aa01..b7d6e88bd15 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -22,12 +22,13 @@ import ( "fmt" "sync" + "golang.org/x/sync/errgroup" + "github.com/compose-spec/compose-go/v2/format" "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/idgen" - "golang.org/x/sync/errgroup" ) type RunOptions struct { diff --git a/pkg/composer/serviceparser/build.go b/pkg/composer/serviceparser/build.go index ce39d67a163..ec95fc66591 100644 --- a/pkg/composer/serviceparser/build.go +++ b/pkg/composer/serviceparser/build.go @@ -23,7 +23,7 @@ import ( "strings" "github.com/compose-spec/compose-go/v2/types" - "github.com/containerd/containerd/identifiers" + "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/reflectutil" diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index b84fac42ede..8faed02ac07 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -29,8 +29,8 @@ import ( "time" "github.com/compose-spec/compose-go/v2/types" - "github.com/containerd/containerd/contrib/nvidia" - "github.com/containerd/containerd/identifiers" + "github.com/containerd/containerd/v2/contrib/nvidia" + "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) diff --git a/pkg/composer/stop.go b/pkg/composer/stop.go index 6baa0f9edb2..eac5266c664 100644 --- a/pkg/composer/stop.go +++ b/pkg/composer/stop.go @@ -21,7 +21,7 @@ import ( "fmt" "sync" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" diff --git a/pkg/composer/up_service.go b/pkg/composer/up_service.go index 8838eced927..70dd9e5b4d2 100644 --- a/pkg/composer/up_service.go +++ b/pkg/composer/up_service.go @@ -25,11 +25,11 @@ import ( "strings" "sync" + "golang.org/x/sync/errgroup" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" - - "golang.org/x/sync/errgroup" ) func (c *Composer) upServices(ctx context.Context, parsedServices []*serviceparser.Service, uo UpOptions) error { diff --git a/pkg/config/config.go b/pkg/config/config.go index 6c3273f9ea5..eaffe583260 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -17,9 +17,8 @@ package config import ( - "github.com/containerd/containerd" - "github.com/containerd/containerd/defaults" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/containerd/v2/pkg/namespaces" ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" ) @@ -49,7 +48,7 @@ func New() *Config { DebugFull: false, Address: defaults.DefaultAddress, Namespace: namespaces.Default, - Snapshotter: containerd.DefaultSnapshotter, + Snapshotter: defaults.DefaultSnapshotter, CNIPath: ncdefaults.CNIPath(), CNINetConfPath: ncdefaults.CNINetConfPath(), DataRoot: ncdefaults.DataRoot(), diff --git a/pkg/consoleutil/consoleutil_unix.go b/pkg/consoleutil/consoleutil_unix.go index 6ffd0cc4dda..d3bd02f0204 100644 --- a/pkg/consoleutil/consoleutil_unix.go +++ b/pkg/consoleutil/consoleutil_unix.go @@ -23,9 +23,10 @@ import ( "os" "os/signal" + "golang.org/x/sys/unix" + "github.com/containerd/console" "github.com/containerd/log" - "golang.org/x/sys/unix" ) // HandleConsoleResize resizes the console. diff --git a/pkg/containerdutil/content.go b/pkg/containerdutil/content.go index 6c7742a3d29..46587fcae41 100644 --- a/pkg/containerdutil/content.go +++ b/pkg/containerdutil/content.go @@ -23,8 +23,8 @@ package containerdutil import ( "context" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/containerdutil/helpers.go b/pkg/containerdutil/helpers.go index 1d410035ffd..e341b38e06b 100644 --- a/pkg/containerdutil/helpers.go +++ b/pkg/containerdutil/helpers.go @@ -19,7 +19,7 @@ package containerdutil import ( "context" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/containerdutil/snapshotter.go b/pkg/containerdutil/snapshotter.go index 738e98f7a69..bf35171b5cb 100644 --- a/pkg/containerdutil/snapshotter.go +++ b/pkg/containerdutil/snapshotter.go @@ -19,8 +19,8 @@ package containerdutil import ( "context" - "github.com/containerd/containerd" - "github.com/containerd/containerd/snapshots" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/snapshots" ) // SnapshotService should be called to get a new caching snapshotter diff --git a/pkg/containerinspector/containerinspector.go b/pkg/containerinspector/containerinspector.go index 3ac41551e75..2e3fe0c86d1 100644 --- a/pkg/containerinspector/containerinspector.go +++ b/pkg/containerinspector/containerinspector.go @@ -19,7 +19,7 @@ package containerinspector import ( "context" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" diff --git a/pkg/containerutil/config.go b/pkg/containerutil/config.go index 3031921222b..0a4a57892a6 100644 --- a/pkg/containerutil/config.go +++ b/pkg/containerutil/config.go @@ -24,8 +24,8 @@ import ( "runtime" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/oci" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index f6db2e78d55..fb246c748e0 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -27,9 +27,9 @@ import ( "runtime" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" diff --git a/pkg/containerutil/container_network_manager_linux.go b/pkg/containerutil/container_network_manager_linux.go index 534040f362d..7411525c11b 100644 --- a/pkg/containerutil/container_network_manager_linux.go +++ b/pkg/containerutil/container_network_manager_linux.go @@ -22,8 +22,8 @@ import ( "io/fs" "path/filepath" - "github.com/containerd/containerd" - "github.com/containerd/containerd/oci" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" diff --git a/pkg/containerutil/container_network_manager_other.go b/pkg/containerutil/container_network_manager_other.go index 1dabe5e6428..7f9b83b225f 100644 --- a/pkg/containerutil/container_network_manager_other.go +++ b/pkg/containerutil/container_network_manager_other.go @@ -23,8 +23,8 @@ import ( "fmt" "runtime" - "github.com/containerd/containerd" - "github.com/containerd/containerd/oci" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/containerutil/container_network_manager_windows.go b/pkg/containerutil/container_network_manager_windows.go index 399ac70bacb..e81ea4560a9 100644 --- a/pkg/containerutil/container_network_manager_windows.go +++ b/pkg/containerutil/container_network_manager_windows.go @@ -20,9 +20,9 @@ import ( "context" "fmt" - "github.com/containerd/containerd" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/netns" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/netns" + "github.com/containerd/containerd/v2/pkg/oci" gocni "github.com/containerd/go-cni" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 91424c42ff5..8a033ce9a31 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -29,11 +29,11 @@ import ( "time" "github.com/containerd/console" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/runtime/restart" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/runtime/restart" + "github.com/containerd/containerd/v2/pkg/cio" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/consoleutil" "github.com/containerd/nerdctl/v2/pkg/errutil" diff --git a/pkg/containerutil/cp_linux.go b/pkg/containerutil/cp_linux.go index 0d918e526e2..fd7f6e82b98 100644 --- a/pkg/containerutil/cp_linux.go +++ b/pkg/containerutil/cp_linux.go @@ -28,8 +28,8 @@ import ( "strconv" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/mount" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" diff --git a/pkg/defaults/defaults_linux.go b/pkg/defaults/defaults_linux.go index 6b30aca67a3..41e18118e5c 100644 --- a/pkg/defaults/defaults_linux.go +++ b/pkg/defaults/defaults_linux.go @@ -22,7 +22,7 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd/plugin" + "github.com/containerd/containerd/v2/plugins" gocni "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" @@ -31,7 +31,7 @@ import ( const ( AppArmorProfileName = "nerdctl-default" SeccompProfileName = "builtin" - Runtime = plugin.RuntimeRuncV2 + Runtime = plugins.RuntimeRuncV2 ) func DataRoot() string { diff --git a/pkg/eventutil/eventutil.go b/pkg/eventutil/eventutil.go index fa4c7d8afe2..a624332e80d 100644 --- a/pkg/eventutil/eventutil.go +++ b/pkg/eventutil/eventutil.go @@ -19,7 +19,7 @@ package eventutil import ( "sync" - "github.com/containerd/containerd/events" + "github.com/containerd/containerd/v2/core/events" ) type eventHandler struct { diff --git a/pkg/formatter/formatter.go b/pkg/formatter/formatter.go index 7b3199d6be3..de313688792 100644 --- a/pkg/formatter/formatter.go +++ b/pkg/formatter/formatter.go @@ -25,16 +25,16 @@ import ( "strings" "time" + "github.com/docker/go-units" "golang.org/x/text/cases" "golang.org/x/text/language" - "github.com/containerd/containerd" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/runtime/restart" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/runtime/restart" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/portutil" - "github.com/docker/go-units" ) func ContainerStatus(ctx context.Context, c containerd.Container) string { diff --git a/pkg/idutil/containerwalker/containerwalker.go b/pkg/idutil/containerwalker/containerwalker.go index 94c497e9f10..b889682569a 100644 --- a/pkg/idutil/containerwalker/containerwalker.go +++ b/pkg/idutil/containerwalker/containerwalker.go @@ -22,7 +22,7 @@ import ( "regexp" "strings" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/idutil/imagewalker/imagewalker.go b/pkg/idutil/imagewalker/imagewalker.go index 68f8c9fe269..a500c66de57 100644 --- a/pkg/idutil/imagewalker/imagewalker.go +++ b/pkg/idutil/imagewalker/imagewalker.go @@ -22,8 +22,8 @@ import ( "regexp" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/opencontainers/go-digest" ) diff --git a/pkg/imageinspector/imageinspector.go b/pkg/imageinspector/imageinspector.go index c5f34a8995f..b3bec918692 100644 --- a/pkg/imageinspector/imageinspector.go +++ b/pkg/imageinspector/imageinspector.go @@ -19,9 +19,9 @@ package imageinspector import ( "context" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/snapshots" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index 9d43cb31a3e..e844a601bd7 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -27,14 +27,14 @@ import ( "strings" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/rootfs" - "github.com/containerd/containerd/snapshots" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/cio" + "github.com/containerd/containerd/v2/pkg/rootfs" "github.com/containerd/errdefs" "github.com/containerd/log" imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" diff --git a/pkg/imgutil/converter/zstd.go b/pkg/imgutil/converter/zstd.go index 1de2355cdd7..417175253d5 100644 --- a/pkg/imgutil/converter/zstd.go +++ b/pkg/imgutil/converter/zstd.go @@ -21,11 +21,11 @@ import ( "fmt" "io" - "github.com/containerd/containerd/archive/compression" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/images/converter" - "github.com/containerd/containerd/images/converter/uncompress" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/images/converter" + "github.com/containerd/containerd/v2/core/images/converter/uncompress" + "github.com/containerd/containerd/v2/pkg/archive/compression" "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/klauspost/compress/zstd" diff --git a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go index bad0a33c444..af59898e93f 100644 --- a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go +++ b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go @@ -23,9 +23,9 @@ import ( "fmt" "os" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" - dockerconfig "github.com/containerd/containerd/remotes/docker/config" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + dockerconfig "github.com/containerd/containerd/v2/core/remotes/docker/config" "github.com/containerd/errdefs" "github.com/containerd/log" dockercliconfig "github.com/docker/cli/cli/config" diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index ea01e781211..f34cbf48234 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -23,8 +23,8 @@ import ( "strings" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/referenceutil" distributionref "github.com/distribution/reference" diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 0fb33eded2c..baa54dd60a6 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -22,11 +22,11 @@ import ( "fmt" "reflect" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/snapshots" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/imgcrypt" "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/log" diff --git a/pkg/imgutil/jobs/jobs.go b/pkg/imgutil/jobs/jobs.go index 57329468065..b56db6bfa03 100644 --- a/pkg/imgutil/jobs/jobs.go +++ b/pkg/imgutil/jobs/jobs.go @@ -24,9 +24,9 @@ import ( "text/tabwriter" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/pkg/progress" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/pkg/progress" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/opencontainers/go-digest" diff --git a/pkg/imgutil/pull/pull.go b/pkg/imgutil/pull/pull.go index dae303eaa1c..01e5b9db250 100644 --- a/pkg/imgutil/pull/pull.go +++ b/pkg/imgutil/pull/pull.go @@ -21,9 +21,9 @@ import ( "context" "io" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/imgutil/jobs" "github.com/containerd/nerdctl/v2/pkg/platformutil" diff --git a/pkg/imgutil/push/push.go b/pkg/imgutil/push/push.go index 7307a66b3b3..5fd2447dcd5 100644 --- a/pkg/imgutil/push/push.go +++ b/pkg/imgutil/push/push.go @@ -25,17 +25,17 @@ import ( "text/tabwriter" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/pkg/progress" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "golang.org/x/sync/errgroup" + + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/pkg/progress" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/imgutil/jobs" "github.com/containerd/platforms" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - "golang.org/x/sync/errgroup" ) // Push pushes an image to a remote registry. diff --git a/pkg/imgutil/snapshotter.go b/pkg/imgutil/snapshotter.go index 0c787767eea..c56864413f0 100644 --- a/pkg/imgutil/snapshotter.go +++ b/pkg/imgutil/snapshotter.go @@ -19,9 +19,9 @@ package imgutil import ( "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" - ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" + ctdsnapshotters "github.com/containerd/containerd/v2/pkg/snapshotters" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" diff --git a/pkg/imgutil/snapshotter_test.go b/pkg/imgutil/snapshotter_test.go index e719b8086b0..375b1ccfb86 100644 --- a/pkg/imgutil/snapshotter_test.go +++ b/pkg/imgutil/snapshotter_test.go @@ -21,8 +21,8 @@ import ( "reflect" "testing" - "github.com/containerd/containerd" - ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" + containerd "github.com/containerd/containerd/v2/client" + ctdsnapshotters "github.com/containerd/containerd/v2/pkg/snapshotters" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" digest "github.com/opencontainers/go-digest" diff --git a/pkg/infoutil/infoutil.go b/pkg/infoutil/infoutil.go index 3b4c57e6968..1f02fa4b311 100644 --- a/pkg/infoutil/infoutil.go +++ b/pkg/infoutil/infoutil.go @@ -26,9 +26,9 @@ import ( "time" "github.com/Masterminds/semver/v3" - "github.com/containerd/containerd" - ptypes "github.com/containerd/containerd/protobuf/types" - "github.com/containerd/containerd/services/introspection" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/introspection" + ptypes "github.com/containerd/containerd/v2/pkg/protobuf/types" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" @@ -39,11 +39,11 @@ import ( func NativeDaemonInfo(ctx context.Context, client *containerd.Client) (*native.DaemonInfo, error) { introService := client.IntrospectionService() - plugins, err := introService.Plugins(ctx, nil) + plugins, err := introService.Plugins(ctx) if err != nil { return nil, err } - server, err := introService.Server(ctx, &ptypes.Empty{}) + server, err := introService.Server(ctx) if err != nil { return nil, err } @@ -67,7 +67,7 @@ func Info(ctx context.Context, client *containerd.Client, snapshotter, cgroupMan return nil, err } introService := client.IntrospectionService() - daemonIntro, err := introService.Server(ctx, &ptypes.Empty{}) + daemonIntro, err := introService.Server(ctx) if err != nil { return nil, err } @@ -101,7 +101,7 @@ func Info(ctx context.Context, client *containerd.Client, snapshotter, cgroupMan func GetSnapshotterNames(ctx context.Context, introService introspection.Service) ([]string, error) { var names []string - plugins, err := introService.Plugins(ctx, nil) + plugins, err := introService.Plugins(ctx) if err != nil { return nil, err } diff --git a/pkg/infoutil/infoutil_freebsd.go b/pkg/infoutil/infoutil_freebsd.go index 4cf753ad9e4..b47c63df524 100644 --- a/pkg/infoutil/infoutil_freebsd.go +++ b/pkg/infoutil/infoutil_freebsd.go @@ -18,7 +18,7 @@ package infoutil import ( "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" - "github.com/docker/docker/pkg/sysinfo" + "github.com/containerd/nerdctl/v2/pkg/sysinfo" ) const UnameO = "FreeBSD" diff --git a/pkg/infoutil/infoutil_linux.go b/pkg/infoutil/infoutil_linux.go index 8dbe95274b5..c9a90c5b162 100644 --- a/pkg/infoutil/infoutil_linux.go +++ b/pkg/infoutil/infoutil_linux.go @@ -25,8 +25,8 @@ import ( "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/sysinfo" "github.com/docker/docker/pkg/meminfo" - "github.com/docker/docker/pkg/sysinfo" ) const UnameO = "GNU/Linux" diff --git a/pkg/infoutil/infoutil_windows.go b/pkg/infoutil/infoutil_windows.go index 6f01255a7b6..11a013bfd04 100644 --- a/pkg/infoutil/infoutil_windows.go +++ b/pkg/infoutil/infoutil_windows.go @@ -21,13 +21,13 @@ import ( "runtime" "strings" - "github.com/containerd/log" "github.com/docker/docker/pkg/meminfo" - "github.com/docker/docker/pkg/sysinfo" "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/sysinfo" ) const UnameO = "Microsoft Windows" diff --git a/pkg/infoutil/infoutil_windows_test.go b/pkg/infoutil/infoutil_windows_test.go index d59c157513c..173cf1927e4 100644 --- a/pkg/infoutil/infoutil_windows_test.go +++ b/pkg/infoutil/infoutil_windows_test.go @@ -19,11 +19,12 @@ package infoutil import ( "testing" - mocks "github.com/containerd/nerdctl/v2/pkg/infoutil/infoutilmock" "go.uber.org/mock/gomock" "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" "gotest.tools/v3/assert" + + mocks "github.com/containerd/nerdctl/v2/pkg/infoutil/infoutilmock" ) func setUpMocks(t *testing.T) *mocks.MockWindowsInfoUtil { diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index 88538906a3b..b701e0f1d51 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -35,8 +35,8 @@ import ( "strings" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/runtime/restart" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/runtime/restart" "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/imgutil" diff --git a/pkg/inspecttypes/dockercompat/dockercompat_test.go b/pkg/inspecttypes/dockercompat/dockercompat_test.go index 38dbb6835b3..4608e2b7813 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat_test.go +++ b/pkg/inspecttypes/dockercompat/dockercompat_test.go @@ -22,8 +22,8 @@ import ( "runtime" "testing" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/pkg/inspecttypes/native/container.go b/pkg/inspecttypes/native/container.go index a47b7de174d..de015dd5f94 100644 --- a/pkg/inspecttypes/native/container.go +++ b/pkg/inspecttypes/native/container.go @@ -19,8 +19,8 @@ package native import ( "net" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" ) // Container corresponds to a containerd-native container object. diff --git a/pkg/inspecttypes/native/image.go b/pkg/inspecttypes/native/image.go index 5eb5499b60d..742eb496f79 100644 --- a/pkg/inspecttypes/native/image.go +++ b/pkg/inspecttypes/native/image.go @@ -17,7 +17,7 @@ package native import ( - "github.com/containerd/containerd/images" + "github.com/containerd/containerd/v2/core/images" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/ipcutil/ipcutil.go b/pkg/ipcutil/ipcutil.go index 9a1ac8e9015..08dd67e7658 100644 --- a/pkg/ipcutil/ipcutil.go +++ b/pkg/ipcutil/ipcutil.go @@ -26,9 +26,9 @@ import ( "runtime" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/docker/go-units" diff --git a/pkg/ipfs/image.go b/pkg/ipfs/image.go index f0a8f36c219..ce6be9b500c 100644 --- a/pkg/ipfs/image.go +++ b/pkg/ipfs/image.go @@ -22,10 +22,10 @@ import ( "io" "os" - "github.com/containerd/containerd" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/images/converter" - "github.com/containerd/containerd/remotes" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/images/converter" + "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" diff --git a/pkg/ipfs/registry.go b/pkg/ipfs/registry.go index 76539826b12..c8917219789 100644 --- a/pkg/ipfs/registry.go +++ b/pkg/ipfs/registry.go @@ -29,8 +29,8 @@ import ( "strings" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" ipfsclient "github.com/containerd/stargz-snapshotter/ipfs/client" "github.com/opencontainers/go-digest" diff --git a/pkg/lockutil/lockutil_unix.go b/pkg/lockutil/lockutil_unix.go index 9b3d9d98932..7be6844aaf3 100644 --- a/pkg/lockutil/lockutil_unix.go +++ b/pkg/lockutil/lockutil_unix.go @@ -22,8 +22,9 @@ import ( "fmt" "os" - "github.com/containerd/log" "golang.org/x/sys/unix" + + "github.com/containerd/log" ) func WithDirLock(dir string, fn func() error) error { diff --git a/pkg/lockutil/lockutil_windows.go b/pkg/lockutil/lockutil_windows.go index a269fc65716..72dbce35357 100644 --- a/pkg/lockutil/lockutil_windows.go +++ b/pkg/lockutil/lockutil_windows.go @@ -20,8 +20,9 @@ import ( "fmt" "os" - "github.com/containerd/log" "golang.org/x/sys/windows" + + "github.com/containerd/log" ) func WithDirLock(dir string, fn func() error) error { diff --git a/pkg/logging/fluentd_logger.go b/pkg/logging/fluentd_logger.go index 5cc12e76c73..6267b058910 100644 --- a/pkg/logging/fluentd_logger.go +++ b/pkg/logging/fluentd_logger.go @@ -26,7 +26,7 @@ import ( "sync" "time" - "github.com/containerd/containerd/runtime/v2/logging" + "github.com/containerd/containerd/v2/core/runtime/v2/logging" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/fluent/fluent-logger-golang/fluent" diff --git a/pkg/logging/journald_logger.go b/pkg/logging/journald_logger.go index 02d49b0c411..83fa7c6aa64 100644 --- a/pkg/logging/journald_logger.go +++ b/pkg/logging/journald_logger.go @@ -28,7 +28,7 @@ import ( "text/template" "time" - "github.com/containerd/containerd/runtime/v2/logging" + "github.com/containerd/containerd/v2/core/runtime/v2/logging" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/coreos/go-systemd/v22/journal" diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index f76c053bca4..8f3141657d0 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -26,7 +26,7 @@ import ( "strconv" "time" - "github.com/containerd/containerd/runtime/v2/logging" + "github.com/containerd/containerd/v2/core/runtime/v2/logging" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/logging/jsonfile" diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index 3644d8b79a6..b704c874a8f 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -29,7 +29,7 @@ import ( "sync" "time" - "github.com/containerd/containerd/runtime/v2/logging" + "github.com/containerd/containerd/v2/core/runtime/v2/logging" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/fsnotify/fsnotify" diff --git a/pkg/logging/syslog_logger.go b/pkg/logging/syslog_logger.go index 398d3a8ea67..63805693279 100644 --- a/pkg/logging/syslog_logger.go +++ b/pkg/logging/syslog_logger.go @@ -31,7 +31,7 @@ import ( "github.com/docker/go-connections/tlsconfig" syslog "github.com/yuchanns/srslog" - "github.com/containerd/containerd/runtime/v2/logging" + "github.com/containerd/containerd/v2/core/runtime/v2/logging" "github.com/containerd/nerdctl/v2/pkg/strutil" ) diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index fccff47bbe6..ae41098b301 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -23,9 +23,9 @@ import ( "runtime" "strings" - "github.com/containerd/containerd/identifiers" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/userns" + "github.com/containerd/containerd/v2/pkg/identifiers" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/containerd/v2/pkg/userns" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" diff --git a/pkg/mountutil/mountutil_freebsd.go b/pkg/mountutil/mountutil_freebsd.go index 396b772bb2f..5d32299a2ca 100644 --- a/pkg/mountutil/mountutil_freebsd.go +++ b/pkg/mountutil/mountutil_freebsd.go @@ -20,7 +20,7 @@ import ( "fmt" "strings" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" diff --git a/pkg/mountutil/mountutil_linux.go b/pkg/mountutil/mountutil_linux.go index d42112a2073..dbc605aade4 100644 --- a/pkg/mountutil/mountutil_linux.go +++ b/pkg/mountutil/mountutil_linux.go @@ -25,15 +25,16 @@ import ( "strconv" "strings" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/oci" - "github.com/containerd/log" - "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" "github.com/docker/go-units" mobymount "github.com/moby/sys/mount" "github.com/opencontainers/runtime-spec/specs-go" "golang.org/x/sys/unix" + + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) /* diff --git a/pkg/mountutil/mountutil_linux_test.go b/pkg/mountutil/mountutil_linux_test.go index 956dcd40447..00f5d2ba42b 100644 --- a/pkg/mountutil/mountutil_linux_test.go +++ b/pkg/mountutil/mountutil_linux_test.go @@ -21,8 +21,8 @@ import ( "strings" "testing" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" mocks "github.com/containerd/nerdctl/v2/pkg/mountutil/mountutilmock" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/pkg/mountutil/mountutil_windows.go b/pkg/mountutil/mountutil_windows.go index 447aaca5cb1..e6782cb3405 100644 --- a/pkg/mountutil/mountutil_windows.go +++ b/pkg/mountutil/mountutil_windows.go @@ -29,7 +29,7 @@ import ( "regexp" "strings" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index 627e78abafe..c7bfc1ccbed 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -23,7 +23,7 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd/identifiers" + "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" diff --git a/pkg/namestore/namestore.go b/pkg/namestore/namestore.go index 73e073b911a..0527b0efb68 100644 --- a/pkg/namestore/namestore.go +++ b/pkg/namestore/namestore.go @@ -22,7 +22,7 @@ import ( "path/filepath" "strings" - "github.com/containerd/containerd/identifiers" + "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/lockutil" ) diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 637c8fd96d5..49341644441 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -30,8 +30,8 @@ import ( "strconv" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/namespaces" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" diff --git a/pkg/ocihook/ocihook_linux.go b/pkg/ocihook/ocihook_linux.go index 43cd714046d..831c7dba695 100644 --- a/pkg/ocihook/ocihook_linux.go +++ b/pkg/ocihook/ocihook_linux.go @@ -17,7 +17,7 @@ package ocihook import ( - "github.com/containerd/containerd/contrib/apparmor" + "github.com/containerd/containerd/v2/contrib/apparmor" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/apparmorutil" "github.com/containerd/nerdctl/v2/pkg/defaults" diff --git a/pkg/platformutil/layers.go b/pkg/platformutil/layers.go index 8f8aee20dee..1cc9f4e5467 100644 --- a/pkg/platformutil/layers.go +++ b/pkg/platformutil/layers.go @@ -19,8 +19,8 @@ package platformutil import ( "context" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" "github.com/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/rootlessutil/child_linux.go b/pkg/rootlessutil/child_linux.go index 1f6d82bc049..e422bff8b19 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/containerd/containerd/v2/pkg/userns" ) func IsRootlessChild() bool { diff --git a/pkg/signalutil/signals.go b/pkg/signalutil/signals.go index ac4baa9662b..b35eacbb121 100644 --- a/pkg/signalutil/signals.go +++ b/pkg/signalutil/signals.go @@ -22,7 +22,7 @@ import ( "os/signal" "syscall" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/log" ) diff --git a/pkg/snapshotterutil/socisource.go b/pkg/snapshotterutil/socisource.go index 85088388d90..fb91fc991e6 100644 --- a/pkg/snapshotterutil/socisource.go +++ b/pkg/snapshotterutil/socisource.go @@ -40,9 +40,9 @@ import ( "fmt" "strings" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" - ctdsnapshotters "github.com/containerd/containerd/pkg/snapshotters" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/labels" + ctdsnapshotters "github.com/containerd/containerd/v2/pkg/snapshotters" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/pkg/sysinfo/cgroup2_linux.go b/pkg/sysinfo/cgroup2_linux.go new file mode 100644 index 00000000000..24a19cefe55 --- /dev/null +++ b/pkg/sysinfo/cgroup2_linux.go @@ -0,0 +1,168 @@ +/* + 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. +*/ + +/* + Portions from https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/pkg/sysinfo/cgroup2_linux.go + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/NOTICE +*/ + +package sysinfo // import "github.com/docker/docker/pkg/sysinfo" + +import ( + "context" + "os" + "path" + "strings" + + "github.com/containerd/cgroups/v3" + cgroupsV2 "github.com/containerd/cgroups/v3/cgroup2" + "github.com/containerd/containerd/v2/pkg/userns" + "github.com/containerd/log" +) + +func newV2(options ...Opt) *SysInfo { + sysInfo := &SysInfo{ + CgroupUnified: true, + cg2GroupPath: "/", + } + for _, o := range options { + o(sysInfo) + } + + ops := []infoCollector{ + applyNetworkingInfo, + applyAppArmorInfo, + applySeccompInfo, + applyCgroupNsInfo, + } + + m, err := cgroupsV2.Load(sysInfo.cg2GroupPath) + if err != nil { + log.G(context.TODO()).Warn(err) + } else { + sysInfo.cg2Controllers = make(map[string]struct{}) + controllers, err := m.Controllers() + if err != nil { + log.G(context.TODO()).Warn(err) + } + for _, c := range controllers { + sysInfo.cg2Controllers[c] = struct{}{} + } + ops = append(ops, + applyMemoryCgroupInfoV2, + applyCPUCgroupInfoV2, + applyIOCgroupInfoV2, + applyCPUSetCgroupInfoV2, + applyPIDSCgroupInfoV2, + applyDevicesCgroupInfoV2, + ) + } + + for _, o := range ops { + o(sysInfo) + } + return sysInfo +} + +func getSwapLimitV2() bool { + _, g, err := cgroups.ParseCgroupFileUnified("/proc/self/cgroup") + if err != nil { + return false + } + + if g == "" { + return false + } + + cGroupPath := path.Join("/sys/fs/cgroup", g, "memory.swap.max") + if _, err = os.Stat(cGroupPath); os.IsNotExist(err) { + return false + } + return true +} + +func applyMemoryCgroupInfoV2(info *SysInfo) { + if _, ok := info.cg2Controllers["memory"]; !ok { + info.Warnings = append(info.Warnings, "Unable to find memory controller") + return + } + + info.MemoryLimit = true + info.SwapLimit = getSwapLimitV2() + info.MemoryReservation = true + info.OomKillDisable = false + info.MemorySwappiness = false + info.KernelMemory = false + info.KernelMemoryTCP = false +} + +func applyCPUCgroupInfoV2(info *SysInfo) { + if _, ok := info.cg2Controllers["cpu"]; !ok { + info.Warnings = append(info.Warnings, "Unable to find cpu controller") + return + } + info.CPUShares = true + info.CPUCfs = true + info.CPURealtime = false +} + +func applyIOCgroupInfoV2(info *SysInfo) { + if _, ok := info.cg2Controllers["io"]; !ok { + info.Warnings = append(info.Warnings, "Unable to find io controller") + return + } + + info.BlkioWeight = true + info.BlkioWeightDevice = true + info.BlkioReadBpsDevice = true + info.BlkioWriteBpsDevice = true + info.BlkioReadIOpsDevice = true + info.BlkioWriteIOpsDevice = true +} + +func applyCPUSetCgroupInfoV2(info *SysInfo) { + if _, ok := info.cg2Controllers["cpuset"]; !ok { + info.Warnings = append(info.Warnings, "Unable to find cpuset controller") + return + } + info.Cpuset = true + + cpus, err := os.ReadFile(path.Join("/sys/fs/cgroup", info.cg2GroupPath, "cpuset.cpus.effective")) + if err != nil { + return + } + info.Cpus = strings.TrimSpace(string(cpus)) + + mems, err := os.ReadFile(path.Join("/sys/fs/cgroup", info.cg2GroupPath, "cpuset.mems.effective")) + if err != nil { + return + } + info.Mems = strings.TrimSpace(string(mems)) +} + +func applyPIDSCgroupInfoV2(info *SysInfo) { + if _, ok := info.cg2Controllers["pids"]; !ok { + info.Warnings = append(info.Warnings, "Unable to find pids controller") + return + } + info.PidsLimit = true +} + +func applyDevicesCgroupInfoV2(info *SysInfo) { + info.CgroupDevicesEnabled = !userns.RunningInUserNS() +} diff --git a/pkg/sysinfo/doc.go b/pkg/sysinfo/doc.go new file mode 100644 index 00000000000..03781ed355e --- /dev/null +++ b/pkg/sysinfo/doc.go @@ -0,0 +1,21 @@ +/* + 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. +*/ + +// This here is a copy of https://github.com/moby/moby/tree/master/pkg/sysinfo +// as of cff4f20c44a3a7c882ed73934dec6a77246c6323 +// This may be removed (and replaced by a dependency to moby again) once they +// have migrated to containerd v2. +package sysinfo diff --git a/pkg/sysinfo/numcpu.go b/pkg/sysinfo/numcpu.go new file mode 100644 index 00000000000..9b585a11d88 --- /dev/null +++ b/pkg/sysinfo/numcpu.go @@ -0,0 +1,38 @@ +/* + 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. +*/ + +/* + Portions from https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/pkg/sysinfo/numcpu.go + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/NOTICE +*/ + +package sysinfo // import "github.com/docker/docker/pkg/sysinfo" + +import ( + "runtime" +) + +// NumCPU returns the number of CPUs. On Linux and Windows, it returns +// the number of CPUs which are currently online. On other platforms, +// it's the equivalent of [runtime.NumCPU]. +func NumCPU() int { + if ncpu := numCPU(); ncpu > 0 { + return ncpu + } + return runtime.NumCPU() +} diff --git a/pkg/sysinfo/numcpu_linux.go b/pkg/sysinfo/numcpu_linux.go new file mode 100644 index 00000000000..de590919ae4 --- /dev/null +++ b/pkg/sysinfo/numcpu_linux.go @@ -0,0 +1,40 @@ +/* + 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. +*/ + +/* + Portions from https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/pkg/sysinfo/numcpu_linux.go + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/NOTICE +*/ + +package sysinfo // import "github.com/docker/docker/pkg/sysinfo" + +import "golang.org/x/sys/unix" + +// numCPU queries the system for the count of threads available +// for use to this process. +// +// Returns 0 on errors. Use |runtime.NumCPU| in that case. +func numCPU() int { + // Gets the affinity mask for a process: The very one invoking this function. + var mask unix.CPUSet + err := unix.SchedGetaffinity(0, &mask) + if err != nil { + return 0 + } + return mask.Count() +} diff --git a/pkg/sysinfo/numcpu_other.go b/pkg/sysinfo/numcpu_other.go new file mode 100644 index 00000000000..cd0c676b440 --- /dev/null +++ b/pkg/sysinfo/numcpu_other.go @@ -0,0 +1,31 @@ +//go:build !linux && !windows + +/* + 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. +*/ + +/* + Portions from https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/pkg/sysinfo/numcpu_other.go + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/NOTICE +*/ + +package sysinfo + +func numCPU() int { + // not implemented + return 0 +} diff --git a/pkg/sysinfo/numcpu_windows.go b/pkg/sysinfo/numcpu_windows.go new file mode 100644 index 00000000000..dfa6496896d --- /dev/null +++ b/pkg/sysinfo/numcpu_windows.go @@ -0,0 +1,59 @@ +/* + 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. +*/ + +/* + Portions from https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/pkg/sysinfo/numcpu_windows.go + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/NOTICE +*/ + +package sysinfo // import "github.com/docker/docker/pkg/sysinfo" + +import ( + "unsafe" + + "golang.org/x/sys/windows" +) + +var ( + kernel32 = windows.NewLazySystemDLL("kernel32.dll") + getCurrentProcess = kernel32.NewProc("GetCurrentProcess") + getProcessAffinityMask = kernel32.NewProc("GetProcessAffinityMask") +) + +// Returns bit count of 1, used by NumCPU +func popcnt(x uint64) (n byte) { + x -= (x >> 1) & 0x5555555555555555 + x = (x>>2)&0x3333333333333333 + x&0x3333333333333333 + x += x >> 4 + x &= 0x0f0f0f0f0f0f0f0f + x *= 0x0101010101010101 + return byte(x >> 56) +} + +func numCPU() int { + // Gets the affinity mask for a process + var mask, sysmask uintptr + currentProcess, _, _ := getCurrentProcess.Call() + ret, _, _ := getProcessAffinityMask.Call(currentProcess, uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask))) + if ret == 0 { + return 0 + } + // For every available thread a bit is set in the mask. + ncpu := int(popcnt(uint64(mask))) + return ncpu +} diff --git a/pkg/sysinfo/sysinfo.go b/pkg/sysinfo/sysinfo.go new file mode 100644 index 00000000000..4e0452423ac --- /dev/null +++ b/pkg/sysinfo/sysinfo.go @@ -0,0 +1,193 @@ +/* + 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. +*/ + +/* + Portions from https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/pkg/sysinfo/sysinfo.go + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/NOTICE +*/ + +// Package sysinfo stores information about which features a kernel supports. +package sysinfo // import "github.com/docker/docker/" + +import "github.com/docker/docker/pkg/parsers" + +// Opt for New(). +type Opt func(info *SysInfo) + +// SysInfo stores information about which features a kernel supports. +// TODO Windows: Factor out platform specific capabilities. +type SysInfo struct { + // Whether the kernel supports AppArmor or not + AppArmor bool + // Whether the kernel supports Seccomp or not + Seccomp bool + + cgroupMemInfo + cgroupCPUInfo + cgroupBlkioInfo + cgroupCpusetInfo + cgroupPids + + // Whether the kernel supports cgroup namespaces or not + CgroupNamespaces bool + + // Whether IPv4 forwarding is supported or not, if this was disabled, networking will not work + IPv4ForwardingDisabled bool + + // Whether bridge-nf-call-iptables is supported or not + BridgeNFCallIPTablesDisabled bool + + // Whether bridge-nf-call-ip6tables is supported or not + BridgeNFCallIP6TablesDisabled bool + + // Whether the cgroup has the mountpoint of "devices" or not + CgroupDevicesEnabled bool + + // Whether the cgroup is in unified mode (v2). + CgroupUnified bool + + // Warnings contains a slice of warnings that occurred while collecting + // system information. These warnings are intended to be informational + // messages for the user, and can either be logged or returned to the + // client; they are not intended to be parsed / used for other purposes, + // and do not have a fixed format. + Warnings []string + + // cgMounts is the list of cgroup v1 mount paths, indexed by subsystem, to + // inspect availability of subsystems. + cgMounts map[string]string + + // cg2GroupPath is the cgroup v2 group path to inspect availability of the controllers. + cg2GroupPath string + + // cg2Controllers is an index of available cgroup v2 controllers. + cg2Controllers map[string]struct{} +} + +type cgroupMemInfo struct { + // Whether memory limit is supported or not + MemoryLimit bool + + // Whether swap limit is supported or not + SwapLimit bool + + // Whether soft limit is supported or not + MemoryReservation bool + + // Whether OOM killer disable is supported or not + OomKillDisable bool + + // Whether memory swappiness is supported or not + MemorySwappiness bool + + // Whether kernel memory limit is supported or not. This option is used to + // detect support for kernel-memory limits on API < v1.42. Kernel memory + // limit (`kmem.limit_in_bytes`) is not supported on cgroups v2, and has been + // removed in kernel 5.4. + KernelMemory bool + + // Whether kernel memory TCP limit is supported or not. Kernel memory TCP + // limit (`memory.kmem.tcp.limit_in_bytes`) is not supported on cgroups v2. + KernelMemoryTCP bool +} + +type cgroupCPUInfo struct { + // Whether CPU shares is supported or not + CPUShares bool + + // Whether CPU CFS (Completely Fair Scheduler) is supported + CPUCfs bool + + // Whether CPU real-time scheduler is supported + CPURealtime bool +} + +type cgroupBlkioInfo struct { + // Whether Block IO weight is supported or not + BlkioWeight bool + + // Whether Block IO weight_device is supported or not + BlkioWeightDevice bool + + // Whether Block IO read limit in bytes per second is supported or not + BlkioReadBpsDevice bool + + // Whether Block IO write limit in bytes per second is supported or not + BlkioWriteBpsDevice bool + + // Whether Block IO read limit in IO per second is supported or not + BlkioReadIOpsDevice bool + + // Whether Block IO write limit in IO per second is supported or not + BlkioWriteIOpsDevice bool +} + +type cgroupCpusetInfo struct { + // Whether Cpuset is supported or not + Cpuset bool + + // Available Cpuset's cpus + Cpus string + + // Available Cpuset's memory nodes + Mems string +} + +type cgroupPids struct { + // Whether Pids Limit is supported or not + PidsLimit bool +} + +// IsCpusetCpusAvailable returns `true` if the provided string set is contained +// in cgroup's cpuset.cpus set, `false` otherwise. +// If error is not nil a parsing error occurred. +func (c cgroupCpusetInfo) IsCpusetCpusAvailable(provided string) (bool, error) { + return isCpusetListAvailable(provided, c.Cpus) +} + +// IsCpusetMemsAvailable returns `true` if the provided string set is contained +// in cgroup's cpuset.mems set, `false` otherwise. +// If error is not nil a parsing error occurred. +func (c cgroupCpusetInfo) IsCpusetMemsAvailable(provided string) (bool, error) { + return isCpusetListAvailable(provided, c.Mems) +} + +func isCpusetListAvailable(provided, available string) (bool, error) { + parsedAvailable, err := parsers.ParseUintList(available) + if err != nil { + return false, err + } + // 8192 is the normal maximum number of CPUs in Linux, so accept numbers up to this + // or more if we actually have more CPUs. + maxCPUs := 8192 + for m := range parsedAvailable { + if m > maxCPUs { + maxCPUs = m + } + } + parsedProvided, err := parsers.ParseUintListMaximum(provided, maxCPUs) + if err != nil { + return false, err + } + for k := range parsedProvided { + if !parsedAvailable[k] { + return false, nil + } + } + return true, nil +} diff --git a/pkg/sysinfo/sysinfo_linux.go b/pkg/sysinfo/sysinfo_linux.go new file mode 100644 index 00000000000..1851d3a6225 --- /dev/null +++ b/pkg/sysinfo/sysinfo_linux.go @@ -0,0 +1,329 @@ +/* + 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. +*/ + +/* + Portions from https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/pkg/sysinfo/sysinfo_linux.go + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/NOTICE +*/ + +package sysinfo // import "github.com/docker/docker/pkg/sysinfo" + +import ( + "context" + "fmt" + "os" + "path" + "strings" + "sync" + + "github.com/containerd/cgroups/v3" + "github.com/containerd/cgroups/v3/cgroup1" + "github.com/containerd/containerd/v2/pkg/seccomp" + "github.com/containerd/log" + "github.com/moby/sys/mountinfo" +) + +var ( + readMountinfoOnce sync.Once + readMountinfoErr error + cgroupMountinfo []*mountinfo.Info +) + +// readCgroupMountinfo returns a list of cgroup v1 mounts (i.e. the ones +// with fstype of "cgroup") for the current running process. +// +// The results are cached (to avoid re-reading mountinfo which is relatively +// expensive), so it is assumed that cgroup mounts are not being changed. +func readCgroupMountinfo() ([]*mountinfo.Info, error) { + readMountinfoOnce.Do(func() { + cgroupMountinfo, readMountinfoErr = mountinfo.GetMounts( + mountinfo.FSTypeFilter("cgroup"), + ) + }) + + return cgroupMountinfo, readMountinfoErr +} + +func findCgroupV1Mountpoints() (map[string]string, error) { + mounts, err := readCgroupMountinfo() + if err != nil { + return nil, err + } + + allSubsystems, err := cgroup1.ParseCgroupFile("/proc/self/cgroup") + if err != nil { + return nil, fmt.Errorf("failed to parse cgroup information: %v", err) + } + + allMap := make(map[string]bool) + for s := range allSubsystems { + allMap[s] = false + } + + mps := make(map[string]string) + for _, mi := range mounts { + for _, opt := range strings.Split(mi.VFSOptions, ",") { + seen, known := allMap[opt] + if known && !seen { + allMap[opt] = true + mps[strings.TrimPrefix(opt, "name=")] = mi.Mountpoint + } + } + if len(mps) >= len(allMap) { + break + } + } + return mps, nil +} + +type infoCollector func(info *SysInfo) + +// WithCgroup2GroupPath specifies the cgroup v2 group path to inspect availability +// of the controllers. +// +// WithCgroup2GroupPath is expected to be used for rootless mode with systemd driver. +// +// e.g. g = "/user.slice/user-1000.slice/user@1000.service" +func WithCgroup2GroupPath(g string) Opt { + return func(o *SysInfo) { + if p := path.Clean(g); p != "" { + o.cg2GroupPath = p + } + } +} + +// New returns a new SysInfo, using the filesystem to detect which features +// the kernel supports. +func New(options ...Opt) *SysInfo { + if cgroups.Mode() == cgroups.Unified { + return newV2(options...) + } + return newV1() +} + +func newV1() *SysInfo { + var ( + err error + sysInfo = &SysInfo{} + ) + + ops := []infoCollector{ + applyNetworkingInfo, + applyAppArmorInfo, + applySeccompInfo, + applyCgroupNsInfo, + } + + sysInfo.cgMounts, err = findCgroupV1Mountpoints() + if err != nil { + log.G(context.TODO()).Warn(err) + } else { + ops = append(ops, + applyMemoryCgroupInfo, + applyCPUCgroupInfo, + applyBlkioCgroupInfo, + applyCPUSetCgroupInfo, + applyPIDSCgroupInfo, + applyDevicesCgroupInfo, + ) + } + + for _, o := range ops { + o(sysInfo) + } + return sysInfo +} + +// applyMemoryCgroupInfo adds the memory cgroup controller information to the info. +func applyMemoryCgroupInfo(info *SysInfo) { + mountPoint, ok := info.cgMounts["memory"] + if !ok { + info.Warnings = append(info.Warnings, "Your kernel does not support cgroup memory limit") + return + } + info.MemoryLimit = ok + + info.SwapLimit = cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes") + if !info.SwapLimit { + info.Warnings = append(info.Warnings, "Your kernel does not support swap memory limit") + } + info.MemoryReservation = cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes") + if !info.MemoryReservation { + info.Warnings = append(info.Warnings, "Your kernel does not support memory reservation") + } + info.OomKillDisable = cgroupEnabled(mountPoint, "memory.oom_control") + if !info.OomKillDisable { + info.Warnings = append(info.Warnings, "Your kernel does not support oom control") + } + info.MemorySwappiness = cgroupEnabled(mountPoint, "memory.swappiness") + if !info.MemorySwappiness { + info.Warnings = append(info.Warnings, "Your kernel does not support memory swappiness") + } + + // Option is deprecated, but still accepted on API < v1.42 with cgroups v1, + // so setting the field to allow feature detection. + info.KernelMemory = cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes") + + // Option is deprecated in runc, but still accepted in our API, so setting + // the field to allow feature detection, but don't warn if it's missing, to + // make the daemon logs a bit less noisy. + info.KernelMemoryTCP = cgroupEnabled(mountPoint, "memory.kmem.tcp.limit_in_bytes") +} + +// applyCPUCgroupInfo adds the cpu cgroup controller information to the info. +func applyCPUCgroupInfo(info *SysInfo) { + mountPoint, ok := info.cgMounts["cpu"] + if !ok { + info.Warnings = append(info.Warnings, "Unable to find cpu cgroup in mounts") + return + } + + info.CPUShares = cgroupEnabled(mountPoint, "cpu.shares") + if !info.CPUShares { + info.Warnings = append(info.Warnings, "Your kernel does not support CPU shares") + } + + info.CPUCfs = cgroupEnabled(mountPoint, "cpu.cfs_quota_us") + if !info.CPUCfs { + info.Warnings = append(info.Warnings, "Your kernel does not support CPU CFS scheduler") + } + + info.CPURealtime = cgroupEnabled(mountPoint, "cpu.rt_period_us") + if !info.CPURealtime { + info.Warnings = append(info.Warnings, "Your kernel does not support CPU realtime scheduler") + } +} + +// applyBlkioCgroupInfo adds the blkio cgroup controller information to the info. +func applyBlkioCgroupInfo(info *SysInfo) { + mountPoint, ok := info.cgMounts["blkio"] + if !ok { + info.Warnings = append(info.Warnings, "Unable to find blkio cgroup in mounts") + return + } + + info.BlkioWeight = cgroupEnabled(mountPoint, "blkio.weight") + if !info.BlkioWeight { + info.Warnings = append(info.Warnings, "Your kernel does not support cgroup blkio weight") + } + + info.BlkioWeightDevice = cgroupEnabled(mountPoint, "blkio.weight_device") + if !info.BlkioWeightDevice { + info.Warnings = append(info.Warnings, "Your kernel does not support cgroup blkio weight_device") + } + + info.BlkioReadBpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.read_bps_device") + if !info.BlkioReadBpsDevice { + info.Warnings = append(info.Warnings, "Your kernel does not support cgroup blkio throttle.read_bps_device") + } + + info.BlkioWriteBpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.write_bps_device") + if !info.BlkioWriteBpsDevice { + info.Warnings = append(info.Warnings, "Your kernel does not support cgroup blkio throttle.write_bps_device") + } + info.BlkioReadIOpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.read_iops_device") + if !info.BlkioReadIOpsDevice { + info.Warnings = append(info.Warnings, "Your kernel does not support cgroup blkio throttle.read_iops_device") + } + + info.BlkioWriteIOpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.write_iops_device") + if !info.BlkioWriteIOpsDevice { + info.Warnings = append(info.Warnings, "Your kernel does not support cgroup blkio throttle.write_iops_device") + } +} + +// applyCPUSetCgroupInfo adds the cpuset cgroup controller information to the info. +func applyCPUSetCgroupInfo(info *SysInfo) { + mountPoint, ok := info.cgMounts["cpuset"] + if !ok { + info.Warnings = append(info.Warnings, "Unable to find cpuset cgroup in mounts") + return + } + info.Cpuset = ok + + var err error + + cpus, err := os.ReadFile(path.Join(mountPoint, "cpuset.cpus")) + if err != nil { + return + } + info.Cpus = strings.TrimSpace(string(cpus)) + + mems, err := os.ReadFile(path.Join(mountPoint, "cpuset.mems")) + if err != nil { + return + } + info.Mems = strings.TrimSpace(string(mems)) +} + +// applyPIDSCgroupInfo adds whether the pids cgroup controller is available to the info. +func applyPIDSCgroupInfo(info *SysInfo) { + _, ok := info.cgMounts["pids"] + if !ok { + info.Warnings = append(info.Warnings, "Unable to find pids cgroup in mounts") + return + } + info.PidsLimit = true +} + +// applyDevicesCgroupInfo adds whether the devices cgroup controller is available to the info. +func applyDevicesCgroupInfo(info *SysInfo) { + _, ok := info.cgMounts["devices"] + info.CgroupDevicesEnabled = ok +} + +// applyNetworkingInfo adds networking information to the info. +func applyNetworkingInfo(info *SysInfo) { + info.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward") + info.BridgeNFCallIPTablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables") + info.BridgeNFCallIP6TablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables") +} + +// applyAppArmorInfo adds whether AppArmor is enabled to the info. +func applyAppArmorInfo(info *SysInfo) { + if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) { + if _, err := os.ReadFile("/sys/kernel/security/apparmor/profiles"); err == nil { + info.AppArmor = true + } + } +} + +// applyCgroupNsInfo adds whether cgroupns is enabled to the info. +func applyCgroupNsInfo(info *SysInfo) { + if _, err := os.Stat("/proc/self/ns/cgroup"); !os.IsNotExist(err) { + info.CgroupNamespaces = true + } +} + +// applySeccompInfo checks if Seccomp is supported, via CONFIG_SECCOMP. +func applySeccompInfo(info *SysInfo) { + info.Seccomp = seccomp.IsEnabled() +} + +func cgroupEnabled(mountPoint, name string) bool { + _, err := os.Stat(path.Join(mountPoint, name)) + return err == nil +} + +func readProcBool(path string) bool { + val, err := os.ReadFile(path) + if err != nil { + return false + } + return strings.TrimSpace(string(val)) == "1" +} diff --git a/pkg/sysinfo/sysinfo_linux_test.go b/pkg/sysinfo/sysinfo_linux_test.go new file mode 100644 index 00000000000..7bfc3b6995d --- /dev/null +++ b/pkg/sysinfo/sysinfo_linux_test.go @@ -0,0 +1,147 @@ +/* + 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. +*/ + +/* + Portions from https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/pkg/sysinfo/sysinfo_linux_test.go + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/NOTICE +*/ + +package sysinfo // import "github.com/docker/docker/pkg/sysinfo" + +import ( + "os" + "path" + "path/filepath" + "testing" + + "golang.org/x/sys/unix" + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" +) + +func TestReadProcBool(t *testing.T) { + tmpDir, err := os.MkdirTemp("", "test-sysinfo-proc") + assert.NilError(t, err) + defer os.RemoveAll(tmpDir) + + procFile := filepath.Join(tmpDir, "read-proc-bool") + err = os.WriteFile(procFile, []byte("1"), 0o644) + assert.NilError(t, err) + + if !readProcBool(procFile) { + t.Fatal("expected proc bool to be true, got false") + } + + if err := os.WriteFile(procFile, []byte("0"), 0o644); err != nil { + t.Fatal(err) + } + if readProcBool(procFile) { + t.Fatal("expected proc bool to be false, got true") + } + + if readProcBool(path.Join(tmpDir, "no-exist")) { + t.Fatal("should be false for non-existent entry") + } +} + +func TestCgroupEnabled(t *testing.T) { + cgroupDir, err := os.MkdirTemp("", "cgroup-test") + assert.NilError(t, err) + defer os.RemoveAll(cgroupDir) + + if cgroupEnabled(cgroupDir, "test") { + t.Fatal("cgroupEnabled should be false") + } + + err = os.WriteFile(path.Join(cgroupDir, "test"), []byte{}, 0o644) + assert.NilError(t, err) + + if !cgroupEnabled(cgroupDir, "test") { + t.Fatal("cgroupEnabled should be true") + } +} + +func TestNew(t *testing.T) { + sysInfo := New() + assert.Assert(t, sysInfo != nil) + checkSysInfo(t, sysInfo) +} + +func checkSysInfo(t *testing.T, sysInfo *SysInfo) { + // Check if Seccomp is supported, via CONFIG_SECCOMP.then sysInfo.Seccomp must be TRUE , else FALSE + if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL { + // Make sure the kernel has CONFIG_SECCOMP_FILTER. + if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL { + assert.Assert(t, sysInfo.Seccomp) + } + } else { + assert.Assert(t, !sysInfo.Seccomp) + } +} + +func TestNewAppArmorEnabled(t *testing.T) { + // Check if AppArmor is supported. then it must be TRUE , else FALSE + if _, err := os.Stat("/sys/kernel/security/apparmor"); err != nil { + t.Skip("AppArmor Must be Enabled") + } + + // FIXME: rootless is not allowed to read the profile + if rootlessutil.IsRootless() { + t.Skip("containerd v2 aftermath: test skipped for rootless") + } + sysInfo := New() + assert.Assert(t, sysInfo.AppArmor) +} + +func TestNewAppArmorDisabled(t *testing.T) { + // Check if AppArmor is supported. then it must be TRUE , else FALSE + if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) { + t.Skip("AppArmor Must be Disabled") + } + + sysInfo := New() + assert.Assert(t, !sysInfo.AppArmor) +} + +func TestNewCgroupNamespacesEnabled(t *testing.T) { + // If cgroup namespaces are supported in the kernel, then sysInfo.CgroupNamespaces should be TRUE + if _, err := os.Stat("/proc/self/ns/cgroup"); err != nil { + t.Skip("cgroup namespaces must be enabled") + } + + sysInfo := New() + assert.Assert(t, sysInfo.CgroupNamespaces) +} + +func TestNewCgroupNamespacesDisabled(t *testing.T) { + // If cgroup namespaces are *not* supported in the kernel, then sysInfo.CgroupNamespaces should be FALSE + if _, err := os.Stat("/proc/self/ns/cgroup"); !os.IsNotExist(err) { + t.Skip("cgroup namespaces must be disabled") + } + + sysInfo := New() + assert.Assert(t, !sysInfo.CgroupNamespaces) +} + +func TestNumCPU(t *testing.T) { + cpuNumbers := NumCPU() + if cpuNumbers <= 0 { + t.Fatal("CPU returned must be greater than zero") + } +} diff --git a/pkg/sysinfo/sysinfo_other.go b/pkg/sysinfo/sysinfo_other.go new file mode 100644 index 00000000000..c48608a1909 --- /dev/null +++ b/pkg/sysinfo/sysinfo_other.go @@ -0,0 +1,31 @@ +//go:build !linux + +/* + 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. +*/ + +/* + Portions from https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/pkg/sysinfo/sysinfo_other.go + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/NOTICE +*/ + +package sysinfo // import "github.com/docker/docker/pkg/sysinfo" + +// New returns an empty SysInfo for non linux for now. +func New(options ...Opt) *SysInfo { + return &SysInfo{} +} diff --git a/pkg/sysinfo/sysinfo_test.go b/pkg/sysinfo/sysinfo_test.go new file mode 100644 index 00000000000..045036a602d --- /dev/null +++ b/pkg/sysinfo/sysinfo_test.go @@ -0,0 +1,49 @@ +/* + 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. +*/ + +/* + Portions from https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/pkg/sysinfo/sysinfo_test.go + Copyright (C) Docker/Moby authors. + Licensed under the Apache License, Version 2.0 + NOTICE: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/NOTICE +*/ + +package sysinfo // import "github.com/docker/docker/pkg/sysinfo" + +import "testing" + +func TestIsCpusetListAvailable(t *testing.T) { + cases := []struct { + provided string + available string + res bool + err bool + }{ + {"1", "0-4", true, false}, + {"01,3", "0-4", true, false}, + {"", "0-7", true, false}, + {"1--42", "0-7", false, true}, + {"1-42", "00-1,8,,9", false, true}, + {"1,41-42", "43,45", false, false}, + {"0-3", "", false, false}, + } + for _, c := range cases { + r, err := isCpusetListAvailable(c.provided, c.available) + if (c.err && err == nil) && r != c.res { + t.Fatalf("Expected pair: %v, %v for %s, %s. Got %v, %v instead", c.res, c.err, c.provided, c.available, (c.err && err == nil), r) + } + } +} diff --git a/pkg/taskutil/taskutil.go b/pkg/taskutil/taskutil.go index b966a137d76..1777e292238 100644 --- a/pkg/taskutil/taskutil.go +++ b/pkg/taskutil/taskutil.go @@ -29,14 +29,15 @@ import ( "syscall" "github.com/Masterminds/semver/v3" + "golang.org/x/term" + "github.com/containerd/console" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/cioutil" "github.com/containerd/nerdctl/v2/pkg/consoleutil" "github.com/containerd/nerdctl/v2/pkg/infoutil" - "golang.org/x/term" ) // NewTask is from https://github.com/containerd/containerd/blob/v1.4.3/cmd/ctr/commands/tasks/tasks_unix.go#L70-L108 diff --git a/pkg/testutil/testregistry/testregistry_linux.go b/pkg/testutil/testregistry/testregistry_linux.go index 24c29058908..811176c4c3c 100644 --- a/pkg/testutil/testregistry/testregistry_linux.go +++ b/pkg/testutil/testregistry/testregistry_linux.go @@ -23,12 +23,13 @@ import ( "path/filepath" "strconv" + "golang.org/x/crypto/bcrypt" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/v2/pkg/testutil/portlock" "github.com/containerd/nerdctl/v2/pkg/testutil/testca" - "golang.org/x/crypto/bcrypt" - "gotest.tools/v3/assert" ) type RegistryServer struct { diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index de80334f09e..058b4417b40 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -31,7 +31,7 @@ import ( "time" "github.com/Masterminds/semver/v3" - "github.com/containerd/containerd/defaults" + "github.com/containerd/containerd/v2/defaults" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/infoutil" diff --git a/pkg/testutil/testutil_windows.go b/pkg/testutil/testutil_windows.go index 76740064de5..54bf1e05b25 100644 --- a/pkg/testutil/testutil_windows.go +++ b/pkg/testutil/testutil_windows.go @@ -23,8 +23,9 @@ import ( "sync" "github.com/Microsoft/hcsshim" - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "golang.org/x/sys/windows/svc/mgr" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" ) const ( From 732656adb7ac561e2c3f46ea60870f6e9a1cd09c Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 8 Aug 2024 17:36:35 -0700 Subject: [PATCH 0626/1066] Make windows filelocking exclusive Signed-off-by: apostasie --- pkg/lockutil/lockutil_windows.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/lockutil/lockutil_windows.go b/pkg/lockutil/lockutil_windows.go index a269fc65716..7763c92597a 100644 --- a/pkg/lockutil/lockutil_windows.go +++ b/pkg/lockutil/lockutil_windows.go @@ -31,13 +31,12 @@ func WithDirLock(dir string, fn func() error) error { } defer dirFile.Close() // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx - // 1 lock immediately - if err = windows.LockFileEx(windows.Handle(dirFile.Fd()), 1, 0, 1, 0, &windows.Overlapped{}); err != nil { + if err = windows.LockFileEx(windows.Handle(dirFile.Fd()), windows.LOCKFILE_EXCLUSIVE_LOCK, 0, ^uint32(0), ^uint32(0), new(windows.Overlapped)); err != nil { return fmt.Errorf("failed to lock %q: %w", dir, err) } defer func() { - if err := windows.UnlockFileEx(windows.Handle(dirFile.Fd()), 0, 1, 0, &windows.Overlapped{}); err != nil { + if err := windows.UnlockFileEx(windows.Handle(dirFile.Fd()), 0, ^uint32(0), ^uint32(0), new(windows.Overlapped)); err != nil { log.L.WithError(err).Errorf("failed to unlock %q", dir) } }() @@ -50,8 +49,7 @@ func Lock(dir string) (*os.File, error) { return nil, err } // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx - // 1 lock immediately - if err = windows.LockFileEx(windows.Handle(dirFile.Fd()), 1, 0, 1, 0, &windows.Overlapped{}); err != nil { + if err = windows.LockFileEx(windows.Handle(dirFile.Fd()), windows.LOCKFILE_EXCLUSIVE_LOCK, 0, ^uint32(0), ^uint32(0), new(windows.Overlapped)); err != nil { return nil, fmt.Errorf("failed to lock %q: %w", dir, err) } return dirFile, nil @@ -62,5 +60,5 @@ func Unlock(locked *os.File) error { _ = locked.Close() }() - return windows.UnlockFileEx(windows.Handle(locked.Fd()), 0, 1, 0, &windows.Overlapped{}) + return windows.UnlockFileEx(windows.Handle(locked.Fd()), 0, ^uint32(0), ^uint32(0), new(windows.Overlapped)) } From 6f84540c343247c8ffda874cf132da0cc4df9f1b Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 9 Aug 2024 19:06:15 +0200 Subject: [PATCH 0627/1066] migrate to github.com/moby/sys/userns The userns package in containerd is deprecated and migrated to a separate module. Signed-off-by: Sebastiaan van Stijn --- cmd/nerdctl/container_run_cgroup_linux_test.go | 2 +- go.mod | 3 ++- go.sum | 6 ++++-- pkg/apparmorutil/apparmorutil_linux.go | 2 +- pkg/cmd/container/run_linux.go | 2 +- pkg/cmd/container/run_mount.go | 2 +- pkg/mountutil/mountutil.go | 2 +- pkg/rootlessutil/child_linux.go | 2 +- pkg/sysinfo/cgroup2_linux.go | 2 +- 9 files changed, 13 insertions(+), 10 deletions(-) diff --git a/cmd/nerdctl/container_run_cgroup_linux_test.go b/cmd/nerdctl/container_run_cgroup_linux_test.go index 7f7e6c0d2f9..a5abcdc8744 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/v2/pkg/userns" "github.com/containerd/continuity/testutil/loopback" "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/moby/sys/userns" "gotest.tools/v3/assert" ) diff --git a/go.mod b/go.mod index cf21bd06d17..e2f1e906742 100644 --- a/go.mod +++ b/go.mod @@ -50,6 +50,7 @@ require ( github.com/moby/sys/mount v0.3.4 github.com/moby/sys/mountinfo v0.7.2 github.com/moby/sys/signal v0.7.1 + github.com/moby/sys/userns v0.1.0 github.com/moby/term v0.5.0 github.com/muesli/cancelreader v0.2.2 github.com/opencontainers/go-digest v1.0.0 @@ -107,7 +108,7 @@ require ( github.com/moby/locker v1.0.1 // indirect github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/symlink v0.3.0 // indirect - github.com/moby/sys/user v0.2.0 // indirect + github.com/moby/sys/user v0.3.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect diff --git a/go.sum b/go.sum index fb349f4d297..cf5ab2ab833 100644 --- a/go.sum +++ b/go.sum @@ -216,8 +216,10 @@ github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0 github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8= github.com/moby/sys/symlink v0.3.0 h1:GZX89mEZ9u53f97npBy4Rc3vJKj7JBDj/PN2I22GrNU= github.com/moby/sys/symlink v0.3.0/go.mod h1:3eNdhduHmYPcgsJtZXW1W4XUJdZGBIkttZ8xKqPUJq0= -github.com/moby/sys/user v0.2.0 h1:OnpapJsRp25vkhw8TFG6OLJODNh/3rEwRWtJ3kakwRM= -github.com/moby/sys/user v0.2.0/go.mod h1:RYstrcWOJpVh+6qzUqp2bU3eaRpdiQeKGlKitaH0PM8= +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= diff --git a/pkg/apparmorutil/apparmorutil_linux.go b/pkg/apparmorutil/apparmorutil_linux.go index aea0d321b47..c8bb17a31bb 100644 --- a/pkg/apparmorutil/apparmorutil_linux.go +++ b/pkg/apparmorutil/apparmorutil_linux.go @@ -24,8 +24,8 @@ import ( "sync" "github.com/containerd/containerd/v2/pkg/apparmor" - "github.com/containerd/containerd/v2/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/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index f1ac8099451..86200e1eb5e 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -24,7 +24,6 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" - "github.com/containerd/containerd/v2/pkg/userns" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/bypass4netnsutil" @@ -33,6 +32,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" + "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 c533692b279..fb4ce299502 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -33,7 +33,6 @@ import ( "github.com/containerd/containerd/v2/core/leases" "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/containerd/v2/pkg/oci" - "github.com/containerd/containerd/v2/pkg/userns" "github.com/containerd/continuity/fs" "github.com/containerd/errdefs" "github.com/containerd/log" @@ -46,6 +45,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" "github.com/containerd/nerdctl/v2/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/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index ae41098b301..657842f34a7 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -25,11 +25,11 @@ import ( "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/containerd/v2/pkg/oci" - "github.com/containerd/containerd/v2/pkg/userns" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" "github.com/containerd/nerdctl/v2/pkg/strutil" + "github.com/moby/sys/userns" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/rootlessutil/child_linux.go b/pkg/rootlessutil/child_linux.go index e422bff8b19..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/v2/pkg/userns" + "github.com/moby/sys/userns" ) func IsRootlessChild() bool { diff --git a/pkg/sysinfo/cgroup2_linux.go b/pkg/sysinfo/cgroup2_linux.go index 24a19cefe55..1984685e139 100644 --- a/pkg/sysinfo/cgroup2_linux.go +++ b/pkg/sysinfo/cgroup2_linux.go @@ -31,8 +31,8 @@ import ( "github.com/containerd/cgroups/v3" cgroupsV2 "github.com/containerd/cgroups/v3/cgroup2" - "github.com/containerd/containerd/v2/pkg/userns" "github.com/containerd/log" + "github.com/moby/sys/userns" ) func newV2(options ...Opt) *SysInfo { From bc7e059fc7faaa83e78a985e17ac5b66d113f10c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 22:24:37 +0000 Subject: [PATCH 0628/1066] build(deps): bump github.com/containerd/accelerated-container-image Bumps [github.com/containerd/accelerated-container-image](https://github.com/containerd/accelerated-container-image) from 1.1.5-0.20240712041225-3c4dd559fed4 to 1.2.0. - [Release notes](https://github.com/containerd/accelerated-container-image/releases) - [Commits](https://github.com/containerd/accelerated-container-image/commits/v1.2.0) --- updated-dependencies: - dependency-name: github.com/containerd/accelerated-container-image dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e2f1e906742..145de63401f 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.5 github.com/compose-spec/compose-go/v2 v2.1.6 - github.com/containerd/accelerated-container-image v1.1.5-0.20240712041225-3c4dd559fed4 + github.com/containerd/accelerated-container-image v1.2.0 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0-rc.2 diff --git a/go.sum b/go.sum index cf5ab2ab833..ee8bebdc011 100644 --- a/go.sum +++ b/go.sum @@ -25,8 +25,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/v2 v2.1.6 h1:d0Cs0DffmOwmSzs0YPHwKCskknGq2jfGg4uGowlEpps= github.com/compose-spec/compose-go/v2 v2.1.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= -github.com/containerd/accelerated-container-image v1.1.5-0.20240712041225-3c4dd559fed4 h1:9anPRQFoKFkeWr++u+fMOLR2srAjIRms7dqbrouLAXo= -github.com/containerd/accelerated-container-image v1.1.5-0.20240712041225-3c4dd559fed4/go.mod h1:BbY0iTEYD6XZV84E99yjUbs46EGI0CVQrjqb/Wgx9nE= +github.com/containerd/accelerated-container-image v1.2.0 h1:txvvjckuXjIqsKpaPfDwGcGmjwH+TJDrvUuOswEBCTg= +github.com/containerd/accelerated-container-image v1.2.0/go.mod h1:BbY0iTEYD6XZV84E99yjUbs46EGI0CVQrjqb/Wgx9nE= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= From bd59961bf2e2ed3469ee05c80497aee5bdc829d2 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 9 Aug 2024 09:58:29 -0700 Subject: [PATCH 0629/1066] Fix godoc to align with style Signed-off-by: apostasie --- pkg/sysinfo/doc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/sysinfo/doc.go b/pkg/sysinfo/doc.go index 03781ed355e..17515398fbd 100644 --- a/pkg/sysinfo/doc.go +++ b/pkg/sysinfo/doc.go @@ -14,7 +14,7 @@ limitations under the License. */ -// This here is a copy of https://github.com/moby/moby/tree/master/pkg/sysinfo +// Package sysinfo is a copy of https://github.com/moby/moby/tree/master/pkg/sysinfo // as of cff4f20c44a3a7c882ed73934dec6a77246c6323 // This may be removed (and replaced by a dependency to moby again) once they // have migrated to containerd v2. From 83914c5b2db3b3441ac4a4bd7d1a1c40c0ef8fbc Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 9 Aug 2024 10:06:46 -0700 Subject: [PATCH 0630/1066] Fix docker/errdefs -> containerd/errdefs Signed-off-by: apostasie --- pkg/cmd/login/login.go | 2 +- pkg/imgutil/imgutil.go | 7 ++++--- pkg/ipfs/image.go | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 744a7b5a256..0c8fc802d4a 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -27,10 +27,10 @@ import ( "os" "strings" + "github.com/containerd/errdefs" dockercliconfig "github.com/docker/cli/cli/config" dockercliconfigtypes "github.com/docker/cli/cli/config/types" "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/errdefs" "golang.org/x/net/context/ctxhttp" "golang.org/x/term" diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index baa54dd60a6..7d29db6e4d6 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -19,6 +19,7 @@ package imgutil import ( "context" "encoding/json" + "errors" "fmt" "reflect" @@ -27,6 +28,7 @@ import ( "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/errdefs" "github.com/containerd/imgcrypt" "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/log" @@ -37,7 +39,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" "github.com/containerd/platforms" distributionref "github.com/distribution/reference" - "github.com/docker/docker/errdefs" "github.com/opencontainers/image-spec/identity" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -90,10 +91,10 @@ func GetExistingImage(ctx context.Context, client *containerd.Client, snapshotte return nil, err } if count == 0 { - return nil, errdefs.NotFound(fmt.Errorf("got count 0 after walking")) + return nil, errors.Join(errdefs.ErrNotFound, errors.New("got count 0 after walking")) } if res == nil { - return nil, errdefs.NotFound(fmt.Errorf("got nil res after walking")) + return nil, errors.Join(errdefs.ErrNotFound, errors.New("got nil res after walking")) } return res, nil } diff --git a/pkg/ipfs/image.go b/pkg/ipfs/image.go index ce6be9b500c..00e5f77faf7 100644 --- a/pkg/ipfs/image.go +++ b/pkg/ipfs/image.go @@ -26,6 +26,7 @@ import ( "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/images/converter" "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" @@ -34,7 +35,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/stargz-snapshotter/ipfs" ipfsclient "github.com/containerd/stargz-snapshotter/ipfs/client" - "github.com/docker/docker/errdefs" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) From cbe7cfe7232fc867bd75dea7788f6ae1ad2c60f1 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 9 Aug 2024 10:22:27 -0700 Subject: [PATCH 0631/1066] Uniformize import style Signed-off-by: apostasie --- pkg/bypass4netnsutil/bypass4netnsutil.go | 5 +++-- pkg/clientutil/client.go | 3 ++- pkg/cmd/compose/compose.go | 3 ++- pkg/cmd/container/create.go | 7 ++++--- pkg/cmd/container/exec.go | 3 ++- pkg/cmd/container/exec_linux.go | 3 ++- pkg/cmd/container/run_cgroup_linux.go | 5 +++-- pkg/cmd/container/run_linux.go | 5 +++-- pkg/cmd/container/run_mount.go | 9 +++++---- pkg/cmd/container/run_runtime.go | 3 ++- pkg/cmd/container/run_ulimit.go | 5 +++-- pkg/cmd/container/run_windows.go | 5 +++-- pkg/cmd/image/convert.go | 5 +++-- pkg/cmd/image/crypt.go | 3 ++- pkg/cmd/image/list.go | 7 ++++--- pkg/cmd/image/prune.go | 3 ++- pkg/cmd/image/push.go | 7 ++++--- pkg/cmd/login/login.go | 2 +- pkg/containerdutil/content.go | 3 ++- pkg/containerdutil/helpers.go | 3 ++- pkg/containerutil/config.go | 3 ++- pkg/containerutil/container_network_manager.go | 3 ++- pkg/containerutil/containerutil.go | 5 +++-- pkg/idutil/imagewalker/imagewalker.go | 3 ++- pkg/imgutil/commit/commit.go | 9 +++++---- pkg/imgutil/converter/zstd.go | 5 +++-- pkg/imgutil/imgutil.go | 7 ++++--- pkg/imgutil/jobs/jobs.go | 5 +++-- pkg/imgutil/pull/pull.go | 3 ++- pkg/imgutil/snapshotter_test.go | 7 ++++--- pkg/inspecttypes/dockercompat/dockercompat.go | 5 +++-- pkg/inspecttypes/dockercompat/dockercompat_test.go | 6 +++--- pkg/inspecttypes/native/image.go | 3 ++- pkg/ipcutil/ipcutil.go | 5 +++-- pkg/ipfs/image.go | 3 ++- pkg/ipfs/registry.go | 5 +++-- pkg/mountutil/mountutil.go | 5 +++-- pkg/mountutil/mountutil_linux_test.go | 9 +++++---- pkg/mountutil/mountutil_windows_test.go | 5 +++-- pkg/ocihook/ocihook.go | 10 +++++----- pkg/platformutil/layers.go | 3 ++- pkg/platformutil/platformutil.go | 3 ++- pkg/snapshotterutil/socisource.go | 3 ++- pkg/testutil/testutil.go | 7 ++++--- 44 files changed, 126 insertions(+), 85 deletions(-) diff --git a/pkg/bypass4netnsutil/bypass4netnsutil.go b/pkg/bypass4netnsutil/bypass4netnsutil.go index 0d67e2c0546..81db6e6d50b 100644 --- a/pkg/bypass4netnsutil/bypass4netnsutil.go +++ b/pkg/bypass4netnsutil/bypass4netnsutil.go @@ -23,11 +23,12 @@ import ( "path/filepath" "strconv" + "github.com/opencontainers/runtime-spec/specs-go" + b4nnoci "github.com/rootless-containers/bypass4netns/pkg/oci" + "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/annotations" - "github.com/opencontainers/runtime-spec/specs-go" - b4nnoci "github.com/rootless-containers/bypass4netns/pkg/oci" ) func generateSecurityOpt(listenerPath string) (oci.SpecOpts, error) { diff --git a/pkg/clientutil/client.go b/pkg/clientutil/client.go index 2e4043eb6f0..b4118bc49c3 100644 --- a/pkg/clientutil/client.go +++ b/pkg/clientutil/client.go @@ -24,13 +24,14 @@ import ( "runtime" "strings" + "github.com/opencontainers/go-digest" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/systemutil" "github.com/containerd/platforms" - "github.com/opencontainers/go-digest" ) func NewClient(ctx context.Context, namespace, address string, opts ...containerd.Opt) (*containerd.Client, context.Context, context.CancelFunc, error) { diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 0c57aaf869c..090292b3d59 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -23,6 +23,8 @@ import ( "os" "path/filepath" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/api/types" @@ -36,7 +38,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/signutil" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/platforms" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // New returns a new *composer.Composer. diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 1b8c3538293..cc84cd1648c 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -29,6 +29,10 @@ import ( "strconv" "strings" + dockercliopts "github.com/docker/cli/opts" + dockeropts "github.com/docker/docker/opts" + "github.com/opencontainers/runtime-spec/specs-go" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/cio" @@ -55,9 +59,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" - dockercliopts "github.com/docker/cli/opts" - dockeropts "github.com/docker/docker/opts" - "github.com/opencontainers/runtime-spec/specs-go" ) // Create will create a container. diff --git a/pkg/cmd/container/exec.go b/pkg/cmd/container/exec.go index 6fce2849d04..7a0a715a840 100644 --- a/pkg/cmd/container/exec.go +++ b/pkg/cmd/container/exec.go @@ -22,6 +22,8 @@ import ( "io" "os" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/containerd/console" containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/cio" @@ -33,7 +35,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/signalutil" "github.com/containerd/nerdctl/v2/pkg/taskutil" - "github.com/opencontainers/runtime-spec/specs-go" ) // Exec will find the right running container to run a new command. diff --git a/pkg/cmd/container/exec_linux.go b/pkg/cmd/container/exec_linux.go index cd3997020b0..33159b77dc9 100644 --- a/pkg/cmd/container/exec_linux.go +++ b/pkg/cmd/container/exec_linux.go @@ -17,8 +17,9 @@ package container import ( - "github.com/containerd/containerd/v2/pkg/cap" "github.com/opencontainers/runtime-spec/specs-go" + + "github.com/containerd/containerd/v2/pkg/cap" ) func setExecCapabilities(pspec *specs.Process) error { diff --git a/pkg/cmd/container/run_cgroup_linux.go b/pkg/cmd/container/run_cgroup_linux.go index c979dd18bc8..be63938ec57 100644 --- a/pkg/cmd/container/run_cgroup_linux.go +++ b/pkg/cmd/container/run_cgroup_linux.go @@ -23,14 +23,15 @@ import ( "path/filepath" "strings" + "github.com/docker/go-units" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/docker/go-units" - "github.com/opencontainers/runtime-spec/specs-go" ) type customMemoryOptions struct { diff --git a/pkg/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index 86200e1eb5e..9d5c2301524 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -21,6 +21,9 @@ import ( "fmt" "strings" + "github.com/moby/sys/userns" + "github.com/opencontainers/runtime-spec/specs-go" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" @@ -32,8 +35,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/moby/sys/userns" - "github.com/opencontainers/runtime-spec/specs-go" ) // WithoutRunMount returns a SpecOpts that unmounts the default tmpfs on "/run" diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index fb4ce299502..cbcf42e9f87 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -28,6 +28,11 @@ import ( "strings" "time" + securejoin "github.com/cyphar/filepath-securejoin" + "github.com/moby/sys/userns" + "github.com/opencontainers/image-spec/identity" + "github.com/opencontainers/runtime-spec/specs-go" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/core/leases" @@ -44,10 +49,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/mountutil" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" "github.com/containerd/nerdctl/v2/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" ) // copy from https://github.com/containerd/containerd/blob/v1.6.0-rc.1/pkg/cri/opts/spec_linux.go#L129-L151 diff --git a/pkg/cmd/container/run_runtime.go b/pkg/cmd/container/run_runtime.go index 94bb9acc165..b6d0ac4965e 100644 --- a/pkg/cmd/container/run_runtime.go +++ b/pkg/cmd/container/run_runtime.go @@ -20,13 +20,14 @@ import ( "context" "strings" + "github.com/opencontainers/runtime-spec/specs-go" + runcoptions "github.com/containerd/containerd/api/types/runc/options" containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/containerd/v2/plugins" "github.com/containerd/log" - "github.com/opencontainers/runtime-spec/specs-go" ) func generateRuntimeCOpts(cgroupManager, runtimeStr string) ([]containerd.NewContainerOpts, error) { diff --git a/pkg/cmd/container/run_ulimit.go b/pkg/cmd/container/run_ulimit.go index 6a83ea9f72d..2398c713dc5 100644 --- a/pkg/cmd/container/run_ulimit.go +++ b/pkg/cmd/container/run_ulimit.go @@ -20,11 +20,12 @@ import ( "context" "strings" + "github.com/docker/go-units" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/docker/go-units" - "github.com/opencontainers/runtime-spec/specs-go" ) func generateUlimitsOpts(ulimits []string) ([]oci.SpecOpts, error) { diff --git a/pkg/cmd/container/run_windows.go b/pkg/cmd/container/run_windows.go index 7c550cc2a8b..904bc6b71b0 100644 --- a/pkg/cmd/container/run_windows.go +++ b/pkg/cmd/container/run_windows.go @@ -22,12 +22,13 @@ import ( "fmt" "strings" + "github.com/docker/go-units" + "github.com/opencontainers/runtime-spec/specs-go" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/api/types" - "github.com/docker/go-units" - "github.com/opencontainers/runtime-spec/specs-go" ) const ( diff --git a/pkg/cmd/image/convert.go b/pkg/cmd/image/convert.go index cbbbe60d8eb..5747b39a240 100644 --- a/pkg/cmd/image/convert.go +++ b/pkg/cmd/image/convert.go @@ -25,6 +25,9 @@ import ( "os" "strings" + "github.com/klauspost/compress/zstd" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + overlaybdconvert "github.com/containerd/accelerated-container-image/pkg/convertor" containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/content" @@ -43,8 +46,6 @@ import ( estargzexternaltocconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz/externaltoc" zstdchunkedconvert "github.com/containerd/stargz-snapshotter/nativeconverter/zstdchunked" "github.com/containerd/stargz-snapshotter/recorder" - "github.com/klauspost/compress/zstd" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRawRef string, options types.ImageConvertOptions) error { diff --git a/pkg/cmd/image/crypt.go b/pkg/cmd/image/crypt.go index a4f967b5726..a4915c25bf2 100644 --- a/pkg/cmd/image/crypt.go +++ b/pkg/cmd/image/crypt.go @@ -21,6 +21,8 @@ import ( "errors" "fmt" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/images/converter" @@ -29,7 +31,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/referenceutil" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) func Crypt(ctx context.Context, client *containerd.Client, srcRawRef, targetRawRef string, encrypt bool, options types.ImageCryptOptions) error { diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index aaae4d62adb..bdf84ed6efe 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -29,6 +29,10 @@ import ( "text/template" "time" + "github.com/docker/go-units" + "github.com/opencontainers/image-spec/identity" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/images" @@ -39,9 +43,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/platforms" - "github.com/docker/go-units" - "github.com/opencontainers/image-spec/identity" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // ListCommandHandler `List` and print images matching filters in `options`. diff --git a/pkg/cmd/image/prune.go b/pkg/cmd/image/prune.go index d31e8aea005..13ec96ca8cd 100644 --- a/pkg/cmd/image/prune.go +++ b/pkg/cmd/image/prune.go @@ -20,13 +20,14 @@ import ( "context" "fmt" + "github.com/opencontainers/go-digest" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/platforms" - "github.com/opencontainers/go-digest" ) // Prune will remove all dangling images. If all is specified, will also remove all images not referenced by any container. diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index 3c28cd91d40..96d35389669 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -23,6 +23,10 @@ import ( "os" "path/filepath" + distributionref "github.com/distribution/reference" + "github.com/opencontainers/go-digest" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/images" @@ -44,9 +48,6 @@ import ( "github.com/containerd/stargz-snapshotter/estargz" "github.com/containerd/stargz-snapshotter/estargz/zstdchunked" estargzconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz" - distributionref "github.com/distribution/reference" - "github.com/opencontainers/go-digest" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // Push pushes an image specified by `rawRef`. diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 0c8fc802d4a..5ee1d1993f3 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -27,7 +27,6 @@ import ( "os" "strings" - "github.com/containerd/errdefs" dockercliconfig "github.com/docker/cli/cli/config" dockercliconfigtypes "github.com/docker/cli/cli/config/types" "github.com/docker/docker/api/types/registry" @@ -36,6 +35,7 @@ import ( "github.com/containerd/containerd/v2/core/remotes/docker" "github.com/containerd/containerd/v2/core/remotes/docker/config" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/errutil" diff --git a/pkg/containerdutil/content.go b/pkg/containerdutil/content.go index 46587fcae41..929e60951c9 100644 --- a/pkg/containerdutil/content.go +++ b/pkg/containerdutil/content.go @@ -23,9 +23,10 @@ package containerdutil import ( "context" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/content" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // ContentStore should be called to get a Provider with caching diff --git a/pkg/containerdutil/helpers.go b/pkg/containerdutil/helpers.go index e341b38e06b..6f4e7a8a451 100644 --- a/pkg/containerdutil/helpers.go +++ b/pkg/containerdutil/helpers.go @@ -19,8 +19,9 @@ package containerdutil import ( "context" - "github.com/containerd/containerd/v2/core/content" ocispec "github.com/opencontainers/image-spec/specs-go/v1" + + "github.com/containerd/containerd/v2/core/content" ) var ReadBlob = readBlobWithCache() diff --git a/pkg/containerutil/config.go b/pkg/containerutil/config.go index 0a4a57892a6..dc0e28f51aa 100644 --- a/pkg/containerutil/config.go +++ b/pkg/containerutil/config.go @@ -24,12 +24,13 @@ import ( "runtime" "strings" + "github.com/opencontainers/runtime-spec/specs-go" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" - "github.com/opencontainers/runtime-spec/specs-go" ) // ReconfigNetContainer reconfigures the container's network namespace path. diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index fb246c748e0..ada48d2b0d4 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -27,6 +27,8 @@ import ( "runtime" "strings" + "github.com/opencontainers/runtime-spec/specs-go" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" @@ -40,7 +42,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/opencontainers/runtime-spec/specs-go" ) const ( diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 8a033ce9a31..7f661e36196 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -28,6 +28,9 @@ import ( "strings" "time" + "github.com/moby/sys/signal" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/containerd/console" containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" @@ -46,8 +49,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/signalutil" "github.com/containerd/nerdctl/v2/pkg/taskutil" - "github.com/moby/sys/signal" - "github.com/opencontainers/runtime-spec/specs-go" ) // PrintHostPort writes to `writer` the public (HostIP:HostPort) of a given `containerPort/protocol` in a container. diff --git a/pkg/idutil/imagewalker/imagewalker.go b/pkg/idutil/imagewalker/imagewalker.go index a500c66de57..0ab540fec5a 100644 --- a/pkg/idutil/imagewalker/imagewalker.go +++ b/pkg/idutil/imagewalker/imagewalker.go @@ -22,10 +22,11 @@ import ( "regexp" "strings" + "github.com/opencontainers/go-digest" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/nerdctl/v2/pkg/referenceutil" - "github.com/opencontainers/go-digest" ) type Found struct { diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index a5bcd7ede3c..29d80c1b2ac 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -27,6 +27,11 @@ import ( "strings" "time" + "github.com/opencontainers/go-digest" + "github.com/opencontainers/image-spec/identity" + "github.com/opencontainers/image-spec/specs-go" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/diff" @@ -40,10 +45,6 @@ import ( imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/platforms" - "github.com/opencontainers/go-digest" - "github.com/opencontainers/image-spec/identity" - "github.com/opencontainers/image-spec/specs-go" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) type Changes struct { diff --git a/pkg/imgutil/converter/zstd.go b/pkg/imgutil/converter/zstd.go index 417175253d5..e6fdb043366 100644 --- a/pkg/imgutil/converter/zstd.go +++ b/pkg/imgutil/converter/zstd.go @@ -21,6 +21,9 @@ import ( "fmt" "io" + "github.com/klauspost/compress/zstd" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/images/converter" @@ -28,8 +31,6 @@ import ( "github.com/containerd/containerd/v2/pkg/archive/compression" "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/api/types" - "github.com/klauspost/compress/zstd" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // ZstdLayerConvertFunc converts legacy tar.gz layers into zstd layers with diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 7d29db6e4d6..8ebf22772b3 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -23,6 +23,10 @@ import ( "fmt" "reflect" + distributionref "github.com/distribution/reference" + "github.com/opencontainers/image-spec/identity" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/images" @@ -38,9 +42,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" "github.com/containerd/platforms" - distributionref "github.com/distribution/reference" - "github.com/opencontainers/image-spec/identity" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // EnsuredImage contains the image existed in containerd and its metadata. diff --git a/pkg/imgutil/jobs/jobs.go b/pkg/imgutil/jobs/jobs.go index b56db6bfa03..7dc0d985828 100644 --- a/pkg/imgutil/jobs/jobs.go +++ b/pkg/imgutil/jobs/jobs.go @@ -24,13 +24,14 @@ import ( "text/tabwriter" "time" + "github.com/opencontainers/go-digest" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/containerd/v2/pkg/progress" "github.com/containerd/errdefs" "github.com/containerd/log" - "github.com/opencontainers/go-digest" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // ShowProgress continuously updates the output with job progress diff --git a/pkg/imgutil/pull/pull.go b/pkg/imgutil/pull/pull.go index 01e5b9db250..21429cb1acf 100644 --- a/pkg/imgutil/pull/pull.go +++ b/pkg/imgutil/pull/pull.go @@ -21,13 +21,14 @@ import ( "context" "io" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/imgutil/jobs" "github.com/containerd/nerdctl/v2/pkg/platformutil" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // Config for content fetch diff --git a/pkg/imgutil/snapshotter_test.go b/pkg/imgutil/snapshotter_test.go index 375b1ccfb86..42d3f68433c 100644 --- a/pkg/imgutil/snapshotter_test.go +++ b/pkg/imgutil/snapshotter_test.go @@ -21,13 +21,14 @@ import ( "reflect" "testing" + digest "github.com/opencontainers/go-digest" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "gotest.tools/v3/assert" + containerd "github.com/containerd/containerd/v2/client" ctdsnapshotters "github.com/containerd/containerd/v2/pkg/snapshotters" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" - digest "github.com/opencontainers/go-digest" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "gotest.tools/v3/assert" ) const ( diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index b701e0f1d51..56c9f1e071b 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -35,6 +35,9 @@ import ( "strings" "time" + "github.com/docker/go-connections/nat" + "github.com/opencontainers/runtime-spec/specs-go" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/runtime/restart" "github.com/containerd/go-cni" @@ -43,8 +46,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/ocihook/state" - "github.com/docker/go-connections/nat" - "github.com/opencontainers/runtime-spec/specs-go" ) // From https://github.com/moby/moby/blob/v26.1.2/api/types/types.go#L34-L140 diff --git a/pkg/inspecttypes/dockercompat/dockercompat_test.go b/pkg/inspecttypes/dockercompat/dockercompat_test.go index 4608e2b7813..bacbc013db8 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat_test.go +++ b/pkg/inspecttypes/dockercompat/dockercompat_test.go @@ -22,12 +22,12 @@ import ( "runtime" "testing" + "github.com/opencontainers/runtime-spec/specs-go" + "gotest.tools/v3/assert" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - - "github.com/opencontainers/runtime-spec/specs-go" - "gotest.tools/v3/assert" ) func TestContainerFromNative(t *testing.T) { diff --git a/pkg/inspecttypes/native/image.go b/pkg/inspecttypes/native/image.go index 742eb496f79..d7e1ac388d9 100644 --- a/pkg/inspecttypes/native/image.go +++ b/pkg/inspecttypes/native/image.go @@ -17,8 +17,9 @@ package native import ( - "github.com/containerd/containerd/v2/core/images" ocispec "github.com/opencontainers/image-spec/specs-go/v1" + + "github.com/containerd/containerd/v2/core/images" ) // Image corresponds to a containerd-native image object. diff --git a/pkg/ipcutil/ipcutil.go b/pkg/ipcutil/ipcutil.go index 08dd67e7658..94df89cd255 100644 --- a/pkg/ipcutil/ipcutil.go +++ b/pkg/ipcutil/ipcutil.go @@ -26,13 +26,14 @@ import ( "runtime" "strings" + "github.com/docker/go-units" + "github.com/opencontainers/runtime-spec/specs-go" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/labels" - "github.com/docker/go-units" - "github.com/opencontainers/runtime-spec/specs-go" ) type IPCMode string diff --git a/pkg/ipfs/image.go b/pkg/ipfs/image.go index 00e5f77faf7..ace90f21820 100644 --- a/pkg/ipfs/image.go +++ b/pkg/ipfs/image.go @@ -22,6 +22,8 @@ import ( "io" "os" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/images/converter" @@ -35,7 +37,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/stargz-snapshotter/ipfs" ipfsclient "github.com/containerd/stargz-snapshotter/ipfs/client" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) const ipfsPathEnv = "IPFS_PATH" diff --git a/pkg/ipfs/registry.go b/pkg/ipfs/registry.go index c8917219789..038b44f70ce 100644 --- a/pkg/ipfs/registry.go +++ b/pkg/ipfs/registry.go @@ -29,12 +29,13 @@ import ( "strings" "time" + "github.com/opencontainers/go-digest" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" ipfsclient "github.com/containerd/stargz-snapshotter/ipfs/client" - "github.com/opencontainers/go-digest" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // RegistryOptions represents options to configure the registry. diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index 657842f34a7..fa0f80bedd5 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -23,14 +23,15 @@ import ( "runtime" "strings" + "github.com/moby/sys/userns" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/moby/sys/userns" - "github.com/opencontainers/runtime-spec/specs-go" ) const ( diff --git a/pkg/mountutil/mountutil_linux_test.go b/pkg/mountutil/mountutil_linux_test.go index 00f5d2ba42b..983108019b9 100644 --- a/pkg/mountutil/mountutil_linux_test.go +++ b/pkg/mountutil/mountutil_linux_test.go @@ -21,14 +21,15 @@ import ( "strings" "testing" - "github.com/containerd/containerd/v2/core/mount" - "github.com/containerd/containerd/v2/pkg/oci" - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - mocks "github.com/containerd/nerdctl/v2/pkg/mountutil/mountutilmock" "github.com/opencontainers/runtime-spec/specs-go" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" + + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + mocks "github.com/containerd/nerdctl/v2/pkg/mountutil/mountutilmock" ) // TestParseVolumeOptions tests volume options are parsed as expected. diff --git a/pkg/mountutil/mountutil_windows_test.go b/pkg/mountutil/mountutil_windows_test.go index 81322f9b8c6..8ee4725a2cb 100644 --- a/pkg/mountutil/mountutil_windows_test.go +++ b/pkg/mountutil/mountutil_windows_test.go @@ -21,12 +21,13 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - mocks "github.com/containerd/nerdctl/v2/pkg/mountutil/mountutilmock" "github.com/opencontainers/runtime-spec/specs-go" "go.uber.org/mock/gomock" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + mocks "github.com/containerd/nerdctl/v2/pkg/mountutil/mountutilmock" ) func TestParseVolumeOptions(t *testing.T) { diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index d023de39b40..6df9fbc42d9 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -28,6 +28,11 @@ import ( "strings" "time" + types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/opencontainers/runtime-spec/specs-go" + b4nndclient "github.com/rootless-containers/bypass4netns/pkg/api/daemon/client" + rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" + gocni "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/bypass4netnsutil" @@ -38,11 +43,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" "github.com/containerd/nerdctl/v2/pkg/ocihook/state" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - types100 "github.com/containernetworking/cni/pkg/types/100" - "github.com/opencontainers/runtime-spec/specs-go" - - b4nndclient "github.com/rootless-containers/bypass4netns/pkg/api/daemon/client" - rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" ) const ( diff --git a/pkg/platformutil/layers.go b/pkg/platformutil/layers.go index 1cc9f4e5467..7bb6956bc10 100644 --- a/pkg/platformutil/layers.go +++ b/pkg/platformutil/layers.go @@ -19,10 +19,11 @@ package platformutil import ( "context" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/platforms" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) func LayerDescs(ctx context.Context, provider content.Provider, imageTarget ocispec.Descriptor, platform platforms.MatchComparer) ([]ocispec.Descriptor, error) { diff --git a/pkg/platformutil/platformutil.go b/pkg/platformutil/platformutil.go index e47bee7e550..b8594964804 100644 --- a/pkg/platformutil/platformutil.go +++ b/pkg/platformutil/platformutil.go @@ -19,9 +19,10 @@ package platformutil import ( "fmt" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/platforms" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // NewMatchComparerFromOCISpecPlatformSlice returns MatchComparer. diff --git a/pkg/snapshotterutil/socisource.go b/pkg/snapshotterutil/socisource.go index fb91fc991e6..7bd0184085c 100644 --- a/pkg/snapshotterutil/socisource.go +++ b/pkg/snapshotterutil/socisource.go @@ -40,10 +40,11 @@ import ( "fmt" "strings" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/pkg/labels" ctdsnapshotters "github.com/containerd/containerd/v2/pkg/snapshotters" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) const ( diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 058b4417b40..f42b4861e8e 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -31,6 +31,10 @@ import ( "time" "github.com/Masterminds/semver/v3" + "github.com/opencontainers/go-digest" + "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" + "github.com/containerd/containerd/v2/defaults" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/imgutil" @@ -39,9 +43,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/opencontainers/go-digest" - "gotest.tools/v3/assert" - "gotest.tools/v3/icmd" ) type Base struct { From af50cb59c78b89cb155a2c908387ec17e8dfd703 Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Sat, 3 Aug 2024 12:24:05 +0200 Subject: [PATCH 0632/1066] enforce registry default host for login Signed-off-by: fahed dorgaa --- pkg/cmd/login/login.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 64573c7e0e5..fc6e7f4c796 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -53,7 +53,7 @@ type isFileStore interface { func Login(ctx context.Context, options types.LoginCommandOptions, stdout io.Writer) error { var serverAddress string - if options.ServerAddress == "" { + if options.ServerAddress == "" || options.ServerAddress == "docker.io" || options.ServerAddress == "index.docker.io" || options.ServerAddress == "registry-1.docker.io" { serverAddress = dockerconfigresolver.IndexServer } else { serverAddress = options.ServerAddress From 9cc9a5bd6f43dab76ae2c994eb8d6ef3f2d28df7 Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Sat, 10 Aug 2024 23:07:52 +0200 Subject: [PATCH 0633/1066] gofumpt lint Signed-off-by: fahed dorgaa --- pkg/cmd/login/login.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index fc6e7f4c796..8c4572e5fe0 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -67,7 +67,7 @@ func Login(ctx context.Context, options types.LoginCommandOptions, stdout io.Wri authConfig = ®istry.AuthConfig{ServerAddress: serverAddress} } if err == nil && authConfig.Username != "" && authConfig.Password != "" { - //login With StoreCreds + // login With StoreCreds responseIdentityToken, err = loginClientSide(ctx, options.GOptions, *authConfig) } @@ -124,7 +124,7 @@ func GetDefaultAuthConfig(checkCredStore bool, serverAddress string, isDefaultRe return nil, err } } - var authconfig = dockercliconfigtypes.AuthConfig{} + authconfig := dockercliconfigtypes.AuthConfig{} if checkCredStore { dockerConfigFile, err := dockercliconfig.Load("") if err != nil { From d4152ca3d37efc2f6ddabd28a570f0d5853143fe Mon Sep 17 00:00:00 2001 From: Frits <4488681+frits-v@users.noreply.github.com> Date: Sat, 10 Aug 2024 11:04:42 -0700 Subject: [PATCH 0634/1066] feat(compose): add mac-address parsing fixes #3290 Signed-off-by: Frits <4488681+frits-v@users.noreply.github.com> --- pkg/composer/serviceparser/serviceparser.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index 8faed02ac07..7b8ec441be8 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -594,6 +594,9 @@ func newContainer(project *types.Project, parsed *Service, i int) (*Container, e if value != nil && value.Ipv4Address != "" { c.RunArgs = append(c.RunArgs, "--ip="+value.Ipv4Address) } + if value != nil && value.MacAddress != "" { + c.RunArgs = append(c.RunArgs, "--mac-address="+value.MacAddress) + } } } From 41448de95ac901073a08ee66732f84e41910586e Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 10 Aug 2024 22:07:50 -0700 Subject: [PATCH 0635/1066] Use http.ErrSchemeMismatch Signed-off-by: apostasie --- pkg/cmd/image/push.go | 4 +++- pkg/cmd/login/login.go | 2 +- pkg/errutil/errors_check.go | 9 --------- pkg/imgutil/imgutil.go | 3 ++- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index 96d35389669..965c6fa509e 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -18,8 +18,10 @@ package image import ( "context" + "errors" "fmt" "io" + "net/http" "os" "path/filepath" @@ -152,7 +154,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options resolver := docker.NewResolver(resolverOpts) if err = pushFunc(resolver); err != nil { // In some circumstance (e.g. people just use 80 port to support pure http), the error will contain message like "dial tcp : connection refused" - if !errutil.IsErrHTTPResponseToHTTPSClient(err) && !errutil.IsErrConnectionRefused(err) { + if !errors.Is(err, http.ErrSchemeMismatch) && !errutil.IsErrConnectionRefused(err) { return err } if options.GOptions.InsecureRegistry { diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 5ee1d1993f3..0feac734cdf 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -187,7 +187,7 @@ func loginClientSide(ctx context.Context, globalOptions types.GlobalCommandOptio } for i, rh := range regHosts { err = tryLoginWithRegHost(ctx, rh) - if err != nil && globalOptions.InsecureRegistry && (errutil.IsErrHTTPResponseToHTTPSClient(err) || errutil.IsErrConnectionRefused(err)) { + if err != nil && globalOptions.InsecureRegistry && (errors.Is(err, http.ErrSchemeMismatch) || errutil.IsErrConnectionRefused(err)) { rh.Scheme = "http" err = tryLoginWithRegHost(ctx, rh) } diff --git a/pkg/errutil/errors_check.go b/pkg/errutil/errors_check.go index 755fbf2582e..202c4fe8518 100644 --- a/pkg/errutil/errors_check.go +++ b/pkg/errutil/errors_check.go @@ -18,15 +18,6 @@ package errutil import "strings" -// IsErrHTTPResponseToHTTPSClient returns whether err is -// "http: server gave HTTP response to HTTPS client" -func IsErrHTTPResponseToHTTPSClient(err error) bool { - // The error string is unexposed as of Go 1.16, so we can't use `errors.Is`. - // https://github.com/golang/go/issues/44855 - const unexposed = "server gave HTTP response to HTTPS client" - return strings.Contains(err.Error(), unexposed) -} - // IsErrConnectionRefused return whether err is // "connect: connection refused" func IsErrConnectionRefused(err error) bool { diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 8ebf22772b3..05eae9c8f9e 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -21,6 +21,7 @@ import ( "encoding/json" "errors" "fmt" + "net/http" "reflect" distributionref "github.com/distribution/reference" @@ -145,7 +146,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, img, err := PullImage(ctx, client, resolver, ref, options) if err != nil { // In some circumstance (e.g. people just use 80 port to support pure http), the error will contain message like "dial tcp : connection refused". - if !errutil.IsErrHTTPResponseToHTTPSClient(err) && !errutil.IsErrConnectionRefused(err) { + if !errors.Is(err, http.ErrSchemeMismatch) && !errutil.IsErrConnectionRefused(err) { return nil, err } if options.GOptions.InsecureRegistry { From 5d6d02b91252be6ff54221d69f28f6c7d81cfe48 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 10 Aug 2024 22:23:04 -0700 Subject: [PATCH 0636/1066] archived mitchellh/mapstructure -> go-viper/mapstructure Signed-off-by: apostasie --- go.mod | 3 +-- go.sum | 2 -- pkg/netutil/netutil_unix.go | 2 +- pkg/netutil/netutil_windows.go | 2 +- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 145de63401f..16b09b02bbf 100644 --- a/go.mod +++ b/go.mod @@ -43,10 +43,10 @@ require ( github.com/fatih/color v1.17.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/fsnotify/fsnotify v1.7.0 + github.com/go-viper/mapstructure/v2 v2.0.0 github.com/ipfs/go-cid v0.4.1 github.com/klauspost/compress v1.17.9 github.com/mattn/go-isatty v0.0.20 - github.com/mitchellh/mapstructure v1.5.0 github.com/moby/sys/mount v0.3.4 github.com/moby/sys/mountinfo v0.7.2 github.com/moby/sys/signal v0.7.1 @@ -91,7 +91,6 @@ require ( github.com/go-jose/go-jose/v4 v4.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-viper/mapstructure/v2 v2.0.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect diff --git a/go.sum b/go.sum index ee8bebdc011..1bc619aabdd 100644 --- a/go.sum +++ b/go.sum @@ -199,8 +199,6 @@ github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dz github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index 5c846b703b6..7e803981843 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -34,7 +34,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/systemutil" - "github.com/mitchellh/mapstructure" + "github.com/go-viper/mapstructure/v2" "github.com/vishvananda/netlink" ) diff --git a/pkg/netutil/netutil_windows.go b/pkg/netutil/netutil_windows.go index e0956bf7306..8ae9bdb3486 100644 --- a/pkg/netutil/netutil_windows.go +++ b/pkg/netutil/netutil_windows.go @@ -21,7 +21,7 @@ import ( "fmt" "net" - "github.com/mitchellh/mapstructure" + "github.com/go-viper/mapstructure/v2" ) const ( From dc204e922dda15e6ceb62adb720f44d56e330a1f Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 10 Aug 2024 22:34:53 -0700 Subject: [PATCH 0637/1066] Get rid of naked returns Signed-off-by: apostasie --- .golangci.yml | 2 +- cmd/nerdctl/container_create.go | 142 ++++++++++++++++---------------- cmd/nerdctl/container_run.go | 16 ++-- pkg/cmd/container/create.go | 12 +-- 4 files changed, 88 insertions(+), 84 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 5d57ceae6ea..21e02d8c0df 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,7 +10,7 @@ linters: - govet - ineffassign - misspell - # - nakedret + - nakedret - prealloc - typecheck # - asciicheck diff --git a/cmd/nerdctl/container_create.go b/cmd/nerdctl/container_create.go index 9d94f068d9e..1354050b880 100644 --- a/cmd/nerdctl/container_create.go +++ b/cmd/nerdctl/container_create.go @@ -53,12 +53,16 @@ func newCreateCommand() *cobra.Command { return createCommand } -func processContainerCreateOptions(cmd *cobra.Command) (opt types.ContainerCreateOptions, err error) { - opt.Stdout = cmd.OutOrStdout() - opt.Stderr = cmd.ErrOrStderr() +func processContainerCreateOptions(cmd *cobra.Command) (types.ContainerCreateOptions, error) { + var err error + opt := types.ContainerCreateOptions{ + Stdout: cmd.OutOrStdout(), + Stderr: cmd.ErrOrStderr(), + } + opt.GOptions, err = processRootCmdFlags(cmd) if err != nil { - return + return opt, err } opt.NerdctlCmd, opt.NerdctlArgs = globalFlags(cmd) @@ -68,54 +72,54 @@ func processContainerCreateOptions(cmd *cobra.Command) (opt types.ContainerCreat opt.Interactive = false opt.TTY, err = cmd.Flags().GetBool("tty") if err != nil { - return + return opt, err } // The nerdctl create command similar to nerdctl run -d except the container is never started. // So we keep the default value of `opt.Detach` true. opt.Detach = true opt.Restart, err = cmd.Flags().GetString("restart") if err != nil { - return + return opt, err } opt.Rm, err = cmd.Flags().GetBool("rm") if err != nil { - return + return opt, err } opt.Pull, err = cmd.Flags().GetString("pull") if err != nil { - return + return opt, err } opt.Pid, err = cmd.Flags().GetString("pid") if err != nil { - return + return opt, err } opt.StopSignal, err = cmd.Flags().GetString("stop-signal") if err != nil { - return + return opt, err } opt.StopTimeout, err = cmd.Flags().GetInt("stop-timeout") if err != nil { - return + return opt, err } // #endregion // #region for platform flags opt.Platform, err = cmd.Flags().GetString("platform") if err != nil { - return + return opt, err } // #endregion // #region for init process flags opt.InitProcessFlag, err = cmd.Flags().GetBool("init") if err != nil { - return + return opt, err } if opt.InitProcessFlag || cmd.Flags().Changed("init-binary") { var initBinary string initBinary, err = cmd.Flags().GetString("init-binary") if err != nil { - return + return opt, err } opt.InitBinary = &initBinary } @@ -124,97 +128,97 @@ func processContainerCreateOptions(cmd *cobra.Command) (opt types.ContainerCreat // #region for isolation flags opt.Isolation, err = cmd.Flags().GetString("isolation") if err != nil { - return + return opt, err } // #endregion // #region for resource flags opt.CPUs, err = cmd.Flags().GetFloat64("cpus") if err != nil { - return + return opt, err } opt.CPUQuota, err = cmd.Flags().GetInt64("cpu-quota") if err != nil { - return + return opt, err } opt.CPUPeriod, err = cmd.Flags().GetUint64("cpu-period") if err != nil { - return + return opt, err } opt.CPUShares, err = cmd.Flags().GetUint64("cpu-shares") if err != nil { - return + return opt, err } opt.CPUSetCPUs, err = cmd.Flags().GetString("cpuset-cpus") if err != nil { - return + return opt, err } opt.CPUSetMems, err = cmd.Flags().GetString("cpuset-mems") if err != nil { - return + return opt, err } opt.Memory, err = cmd.Flags().GetString("memory") if err != nil { - return + return opt, err } opt.MemoryReservationChanged = cmd.Flags().Changed("memory-reservation") opt.MemoryReservation, err = cmd.Flags().GetString("memory-reservation") if err != nil { - return + return opt, err } opt.MemorySwap, err = cmd.Flags().GetString("memory-swap") if err != nil { - return + return opt, err } opt.MemorySwappiness64Changed = cmd.Flags().Changed("memory-swappiness") opt.MemorySwappiness64, err = cmd.Flags().GetInt64("memory-swappiness") if err != nil { - return + return opt, err } opt.KernelMemoryChanged = cmd.Flag("kernel-memory").Changed opt.KernelMemory, err = cmd.Flags().GetString("kernel-memory") if err != nil { - return + return opt, err } opt.OomKillDisable, err = cmd.Flags().GetBool("oom-kill-disable") if err != nil { - return + return opt, err } opt.OomScoreAdjChanged = cmd.Flags().Changed("oom-score-adj") opt.OomScoreAdj, err = cmd.Flags().GetInt("oom-score-adj") if err != nil { - return + return opt, err } opt.PidsLimit, err = cmd.Flags().GetInt64("pids-limit") if err != nil { - return + return opt, err } opt.CgroupConf, err = cmd.Flags().GetStringSlice("cgroup-conf") if err != nil { - return + return opt, err } opt.BlkioWeight, err = cmd.Flags().GetUint16("blkio-weight") if err != nil { - return + return opt, err } opt.Cgroupns, err = cmd.Flags().GetString("cgroupns") if err != nil { - return + return opt, err } opt.CgroupParent, err = cmd.Flags().GetString("cgroup-parent") if err != nil { - return + return opt, err } opt.Device, err = cmd.Flags().GetStringSlice("device") if err != nil { - return + return opt, err } // #endregion // #region for intel RDT flags opt.RDTClass, err = cmd.Flags().GetString("rdt-class") if err != nil { - return + return opt, err } // #endregion @@ -223,83 +227,83 @@ func processContainerCreateOptions(cmd *cobra.Command) (opt types.ContainerCreat // Otherwise we will inherit permissions from the user that the containerd process is running as opt.User, err = cmd.Flags().GetString("user") if err != nil { - return + return opt, err } opt.Umask = "" if cmd.Flags().Changed("umask") { opt.Umask, err = cmd.Flags().GetString("umask") if err != nil { - return + return opt, err } } opt.GroupAdd, err = cmd.Flags().GetStringSlice("group-add") if err != nil { - return + return opt, err } // #endregion // #region for security flags opt.SecurityOpt, err = cmd.Flags().GetStringArray("security-opt") if err != nil { - return + return opt, err } opt.CapAdd, err = cmd.Flags().GetStringSlice("cap-add") if err != nil { - return + return opt, err } opt.CapDrop, err = cmd.Flags().GetStringSlice("cap-drop") if err != nil { - return + return opt, err } opt.Privileged, err = cmd.Flags().GetBool("privileged") if err != nil { - return + return opt, err } opt.Systemd, err = cmd.Flags().GetString("systemd") if err != nil { - return + return opt, err } // #endregion // #region for runtime flags opt.Runtime, err = cmd.Flags().GetString("runtime") if err != nil { - return + return opt, err } opt.Sysctl, err = cmd.Flags().GetStringArray("sysctl") if err != nil { - return + return opt, err } // #endregion // #region for volume flags opt.Volume, err = cmd.Flags().GetStringArray("volume") if err != nil { - return + return opt, err } // tmpfs needs to be StringArray, not StringSlice, to prevent "/foo:size=64m,exec" from being split to {"/foo:size=64m", "exec"} opt.Tmpfs, err = cmd.Flags().GetStringArray("tmpfs") if err != nil { - return + return opt, err } opt.Mount, err = cmd.Flags().GetStringArray("mount") if err != nil { - return + return opt, err } opt.VolumesFrom, err = cmd.Flags().GetStringArray("volumes-from") if err != nil { - return + return opt, err } // #endregion // #region for rootfs flags opt.ReadOnly, err = cmd.Flags().GetBool("read-only") if err != nil { - return + return opt, err } opt.Rootfs, err = cmd.Flags().GetBool("rootfs") if err != nil { - return + return opt, err } // #endregion @@ -307,19 +311,19 @@ func processContainerCreateOptions(cmd *cobra.Command) (opt types.ContainerCreat opt.EntrypointChanged = cmd.Flags().Changed("entrypoint") opt.Entrypoint, err = cmd.Flags().GetStringArray("entrypoint") if err != nil { - return + return opt, err } opt.Workdir, err = cmd.Flags().GetString("workdir") if err != nil { - return + return opt, err } opt.Env, err = cmd.Flags().GetStringArray("env") if err != nil { - return + return opt, err } opt.EnvFile, err = cmd.Flags().GetStringSlice("env-file") if err != nil { - return + return opt, err } // #endregion @@ -327,29 +331,29 @@ func processContainerCreateOptions(cmd *cobra.Command) (opt types.ContainerCreat opt.NameChanged = cmd.Flags().Changed("name") opt.Name, err = cmd.Flags().GetString("name") if err != nil { - return + return opt, err } opt.Label, err = cmd.Flags().GetStringArray("label") if err != nil { - return + return opt, err } opt.LabelFile, err = cmd.Flags().GetStringSlice("label-file") if err != nil { - return + return opt, err } opt.Annotations, err = cmd.Flags().GetStringArray("annotation") if err != nil { - return + return opt, err } opt.CidFile, err = cmd.Flags().GetString("cidfile") if err != nil { - return + return opt, err } opt.PidFile = "" if cmd.Flags().Changed("pidfile") { opt.PidFile, err = cmd.Flags().GetString("pidfile") if err != nil { - return + return opt, err } } // #endregion @@ -358,50 +362,50 @@ func processContainerCreateOptions(cmd *cobra.Command) (opt types.ContainerCreat // json-file is the built-in and default log driver for nerdctl opt.LogDriver, err = cmd.Flags().GetString("log-driver") if err != nil { - return + return opt, err } opt.LogOpt, err = cmd.Flags().GetStringArray("log-opt") if err != nil { - return + return opt, err } // #endregion // #region for shared memory flags opt.IPC, err = cmd.Flags().GetString("ipc") if err != nil { - return + return opt, err } opt.ShmSize, err = cmd.Flags().GetString("shm-size") if err != nil { - return + return opt, err } // #endregion // #region for gpu flags opt.GPUs, err = cmd.Flags().GetStringArray("gpus") if err != nil { - return + return opt, err } // #endregion // #region for ulimit flags opt.Ulimit, err = cmd.Flags().GetStringSlice("ulimit") if err != nil { - return + return opt, err } // #endregion // #region for ipfs flags opt.IPFSAddress, err = cmd.Flags().GetString("ipfs-address") if err != nil { - return + return opt, err } // #endregion // #region for image pull and verify options imageVerifyOpt, err := processImageVerifyOptions(cmd) if err != nil { - return + return opt, err } opt.ImagePullOpt = types.ImagePullOptions{ GOptions: opt.GOptions, diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index eab36b8f917..86af3073260 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -282,33 +282,33 @@ func setCreateFlags(cmd *cobra.Command) { } -func processCreateCommandFlagsInRun(cmd *cobra.Command) (opt types.ContainerCreateOptions, err error) { - opt, err = processContainerCreateOptions(cmd) +func processCreateCommandFlagsInRun(cmd *cobra.Command) (types.ContainerCreateOptions, error) { + opt, err := processContainerCreateOptions(cmd) if err != nil { - return + return opt, err } opt.InRun = true opt.SigProxy, err = cmd.Flags().GetBool("sig-proxy") if err != nil { - return + return opt, err } opt.Interactive, err = cmd.Flags().GetBool("interactive") if err != nil { - return + return opt, err } opt.Detach, err = cmd.Flags().GetBool("detach") if err != nil { - return + return opt, err } opt.DetachKeys, err = cmd.Flags().GetString("detach-keys") if err != nil { - return + return opt, err } opt.Attach, err = cmd.Flags().GetStringSlice("attach") if err != nil { - return + return opt, err } validAttachFlag := true diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index cc84cd1648c..6a9eeeba33a 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -786,7 +786,7 @@ func generateLogConfig(dataStore string, id string, logDriver string, logOpt []s logConfig.Driver = logDriver logConfig.Opts, err = parseKVStringsMapFromLogOpt(logOpt, logDriver) if err != nil { - return + return logConfig, err } var ( logDriverInst logging.Driver @@ -795,25 +795,25 @@ func generateLogConfig(dataStore string, id string, logDriver string, logOpt []s ) logDriverInst, err = logging.GetDriver(logDriver, logConfig.Opts) if err != nil { - return + return logConfig, err } if err = logDriverInst.Init(dataStore, ns, id); err != nil { - return + return logConfig, err } logConfigB, err = json.Marshal(logConfig) if err != nil { - return + return logConfig, err } logConfigFilePath := logging.LogConfigFilePath(dataStore, ns, id) if err = os.WriteFile(logConfigFilePath, logConfigB, 0600); err != nil { - return + return logConfig, err } lu, err = GenerateLogURI(dataStore) if err != nil { - return + return logConfig, err } if lu != nil { log.L.Debugf("generated log driver: %s", lu.String()) From 02cb8a9207a475ecc523005cf8fc39b049aaca21 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 10 Aug 2024 22:54:04 -0700 Subject: [PATCH 0638/1066] use slice.Contains Signed-off-by: apostasie --- pkg/buildkitutil/buildkitutil.go | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/pkg/buildkitutil/buildkitutil.go b/pkg/buildkitutil/buildkitutil.go index 9004892ae85..87bc066a054 100644 --- a/pkg/buildkitutil/buildkitutil.go +++ b/pkg/buildkitutil/buildkitutil.go @@ -34,6 +34,7 @@ import ( "os/exec" "path/filepath" "runtime" + "slices" "strings" "github.com/containerd/log" @@ -130,20 +131,9 @@ func PingBKDaemon(buildkitHost string) error { return nil } -// contains open-codes slices.Contains (without generics) from Go 1.21. -// TODO: Replace once Go 1.21 is the minimum supported compiler. -func contains(haystack []string, needle string) bool { - for i := range haystack { - if needle == haystack[i] { - return true - } - } - return false -} - func pingBKDaemon(buildkitHost string) (output string, _ error) { supportedOses := []string{"linux", "freebsd", "windows"} - if !contains(supportedOses, runtime.GOOS) { + if !slices.Contains(supportedOses, runtime.GOOS) { return "", fmt.Errorf("only %s are supported", strings.Join(supportedOses, ", ")) } buildctlBinary, err := BuildctlBinary() From 6277d8f6b9edd3a382da68b06be378c82cecac18 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 10 Aug 2024 23:08:06 -0700 Subject: [PATCH 0639/1066] Move projectloader to testutil Signed-off-by: apostasie --- pkg/composer/projectloader/projectloader.go | 56 ------------------- pkg/composer/serviceparser/build_test.go | 3 +- .../serviceparser/serviceparser_test.go | 15 +++-- pkg/testutil/compose.go | 33 +++++++++++ 4 files changed, 41 insertions(+), 66 deletions(-) delete mode 100644 pkg/composer/projectloader/projectloader.go diff --git a/pkg/composer/projectloader/projectloader.go b/pkg/composer/projectloader/projectloader.go deleted file mode 100644 index 680eb2842d6..00000000000 --- a/pkg/composer/projectloader/projectloader.go +++ /dev/null @@ -1,56 +0,0 @@ -/* - 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 projectloader - -import ( - "context" - "os" - "path/filepath" - - "github.com/compose-spec/compose-go/v2/loader" - compose "github.com/compose-spec/compose-go/v2/types" -) - -// Load is used only for unit testing. -// TODO: Remove -func Load(fileName, projectName string, envMap map[string]string) (*compose.Project, error) { - if envMap == nil { - envMap = make(map[string]string) - } - b, err := os.ReadFile(fileName) - if err != nil { - return nil, err - } - - wd, err := filepath.Abs(filepath.Dir(fileName)) - if err != nil { - return nil, err - } - var files []compose.ConfigFile - files = append(files, compose.ConfigFile{Filename: fileName, Content: b}) - return loader.LoadWithContext(context.TODO(), compose.ConfigDetails{ - WorkingDir: wd, - ConfigFiles: files, - Environment: envMap, - }, withProjectName(projectName)) -} - -func withProjectName(name string) func(*loader.Options) { - return func(lOpts *loader.Options) { - lOpts.SetProjectName(name, true) - } -} diff --git a/pkg/composer/serviceparser/build_test.go b/pkg/composer/serviceparser/build_test.go index 55d2ecc2e87..0c63343bc2b 100644 --- a/pkg/composer/serviceparser/build_test.go +++ b/pkg/composer/serviceparser/build_test.go @@ -19,7 +19,6 @@ package serviceparser import ( "testing" - "github.com/containerd/nerdctl/v2/pkg/composer/projectloader" "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" ) @@ -59,7 +58,7 @@ secrets: comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() - project, err := projectloader.Load(comp.YAMLFullPath(), comp.ProjectName(), nil) + project, err := testutil.LoadProject(comp.YAMLFullPath(), comp.ProjectName(), nil) assert.NilError(t, err) fooSvc, err := project.GetService("foo") diff --git a/pkg/composer/serviceparser/serviceparser_test.go b/pkg/composer/serviceparser/serviceparser_test.go index b3aa2008f99..0e178b791d1 100644 --- a/pkg/composer/serviceparser/serviceparser_test.go +++ b/pkg/composer/serviceparser/serviceparser_test.go @@ -24,7 +24,6 @@ import ( "testing" "github.com/compose-spec/compose-go/v2/types" - "github.com/containerd/nerdctl/v2/pkg/composer/projectloader" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" @@ -141,7 +140,7 @@ volumes: comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() - project, err := projectloader.Load(comp.YAMLFullPath(), comp.ProjectName(), nil) + project, err := testutil.LoadProject(comp.YAMLFullPath(), comp.ProjectName(), nil) assert.NilError(t, err) wpSvc, err := project.GetService("wordpress") @@ -212,7 +211,7 @@ services: comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() - project, err := projectloader.Load(comp.YAMLFullPath(), comp.ProjectName(), nil) + project, err := testutil.LoadProject(comp.YAMLFullPath(), comp.ProjectName(), nil) assert.NilError(t, err) fooSvc, err := project.GetService("foo") @@ -273,7 +272,7 @@ services: comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() - project, err := projectloader.Load(comp.YAMLFullPath(), comp.ProjectName(), nil) + project, err := testutil.LoadProject(comp.YAMLFullPath(), comp.ProjectName(), nil) assert.NilError(t, err) fooSvc, err := project.GetService("foo") @@ -346,7 +345,7 @@ services: comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() - project, err := projectloader.Load(comp.YAMLFullPath(), comp.ProjectName(), nil) + project, err := testutil.LoadProject(comp.YAMLFullPath(), comp.ProjectName(), nil) assert.NilError(t, err) fooSvc, err := project.GetService("foo") @@ -378,7 +377,7 @@ services: comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() - project, err := projectloader.Load(comp.YAMLFullPath(), comp.ProjectName(), nil) + project, err := testutil.LoadProject(comp.YAMLFullPath(), comp.ProjectName(), nil) assert.NilError(t, err) fooSvc, err := project.GetService("foo") @@ -438,7 +437,7 @@ configs: comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() - project, err := projectloader.Load(comp.YAMLFullPath(), comp.ProjectName(), nil) + project, err := testutil.LoadProject(comp.YAMLFullPath(), comp.ProjectName(), nil) assert.NilError(t, err) for _, f := range []string{"secret1", "secret2", "secret3", "config1", "config2"} { @@ -482,7 +481,7 @@ services: comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() - project, err := projectloader.Load(comp.YAMLFullPath(), comp.ProjectName(), nil) + project, err := testutil.LoadProject(comp.YAMLFullPath(), comp.ProjectName(), nil) assert.NilError(t, err) getContainersFromService := func(svcName string) []Container { diff --git a/pkg/testutil/compose.go b/pkg/testutil/compose.go index 2d1a28e17f3..2e5b55b056d 100644 --- a/pkg/testutil/compose.go +++ b/pkg/testutil/compose.go @@ -17,9 +17,13 @@ package testutil import ( + "context" "os" "path/filepath" "testing" + + "github.com/compose-spec/compose-go/v2/loader" + compose "github.com/compose-spec/compose-go/v2/types" ) type ComposeDir struct { @@ -63,3 +67,32 @@ func NewComposeDir(t testing.TB, dockerComposeYAML string) *ComposeDir { cd.WriteFile(cd.yamlBasePath, dockerComposeYAML) return cd } + +// Load is used only for unit testing. +func LoadProject(fileName, projectName string, envMap map[string]string) (*compose.Project, error) { + if envMap == nil { + envMap = make(map[string]string) + } + b, err := os.ReadFile(fileName) + if err != nil { + return nil, err + } + + wd, err := filepath.Abs(filepath.Dir(fileName)) + if err != nil { + return nil, err + } + var files []compose.ConfigFile + files = append(files, compose.ConfigFile{Filename: fileName, Content: b}) + return loader.LoadWithContext(context.TODO(), compose.ConfigDetails{ + WorkingDir: wd, + ConfigFiles: files, + Environment: envMap, + }, withProjectName(projectName)) +} + +func withProjectName(name string) func(*loader.Options) { + return func(lOpts *loader.Options) { + lOpts.SetProjectName(name, true) + } +} From 0b729e9e6726a9e0c5387ddc267252eb2ddaac4f Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 11 Aug 2024 17:10:23 -0700 Subject: [PATCH 0640/1066] Import ordering consistency Signed-off-by: apostasie --- cmd/nerdctl/builder.go | 1 + cmd/nerdctl/builder_build_test.go | 6 ++++-- cmd/nerdctl/builder_linux_test.go | 3 ++- cmd/nerdctl/completion.go | 1 + cmd/nerdctl/compose_config_test.go | 3 ++- cmd/nerdctl/compose_cp.go | 3 ++- cmd/nerdctl/compose_cp_linux_test.go | 3 ++- cmd/nerdctl/compose_exec_linux_test.go | 3 ++- cmd/nerdctl/compose_images.go | 1 + cmd/nerdctl/compose_ps.go | 1 + cmd/nerdctl/compose_ps_linux_test.go | 3 ++- cmd/nerdctl/compose_push.go | 3 ++- cmd/nerdctl/compose_rm.go | 3 ++- cmd/nerdctl/compose_run_linux_test.go | 4 +++- cmd/nerdctl/compose_start.go | 1 + cmd/nerdctl/compose_top.go | 1 + cmd/nerdctl/compose_up.go | 3 ++- cmd/nerdctl/compose_up_linux_test.go | 1 + cmd/nerdctl/compose_up_test.go | 3 ++- cmd/nerdctl/compose_version.go | 3 ++- cmd/nerdctl/container_attach.go | 4 +++- cmd/nerdctl/container_attach_linux_test.go | 3 ++- cmd/nerdctl/container_cp_linux_test.go | 3 ++- cmd/nerdctl/container_create.go | 3 ++- cmd/nerdctl/container_create_linux_test.go | 3 ++- cmd/nerdctl/container_diff.go | 3 ++- cmd/nerdctl/container_exec.go | 1 + cmd/nerdctl/container_inspect_windows_test.go | 3 ++- cmd/nerdctl/container_kill.go | 4 +++- cmd/nerdctl/container_kill_linux_test.go | 5 +++-- cmd/nerdctl/container_list_linux_test.go | 3 ++- cmd/nerdctl/container_list_windows_test.go | 3 ++- cmd/nerdctl/container_logs_test.go | 3 ++- cmd/nerdctl/container_pause.go | 1 + cmd/nerdctl/container_remove_windows_test.go | 3 ++- cmd/nerdctl/container_rename.go | 3 ++- cmd/nerdctl/container_restart_linux_test.go | 3 ++- cmd/nerdctl/container_run.go | 4 +++- cmd/nerdctl/container_run_cgroup_linux_test.go | 6 ++++-- cmd/nerdctl/container_run_gpus_test.go | 3 ++- cmd/nerdctl/container_run_linux.go | 3 ++- cmd/nerdctl/container_run_linux_test.go | 5 +++-- cmd/nerdctl/container_run_mount_linux_test.go | 1 + cmd/nerdctl/container_run_mount_windows_test.go | 3 ++- cmd/nerdctl/container_run_network.go | 1 + cmd/nerdctl/container_run_network_base_test.go | 3 ++- cmd/nerdctl/container_run_network_linux_test.go | 6 ++++-- cmd/nerdctl/container_run_network_windows_test.go | 3 ++- cmd/nerdctl/container_run_restart_linux_test.go | 6 +++--- cmd/nerdctl/container_run_security_linux_test.go | 4 ++-- cmd/nerdctl/container_run_test.go | 3 ++- cmd/nerdctl/container_run_windows_test.go | 3 ++- cmd/nerdctl/container_start.go | 4 +++- cmd/nerdctl/container_start_linux_test.go | 3 ++- cmd/nerdctl/container_stats.go | 1 + cmd/nerdctl/container_stop.go | 1 + cmd/nerdctl/container_stop_linux_test.go | 6 +++--- cmd/nerdctl/container_top.go | 1 + cmd/nerdctl/container_unpause.go | 1 + cmd/nerdctl/container_update.go | 3 ++- cmd/nerdctl/container_wait.go | 1 + cmd/nerdctl/flagutil.go | 3 ++- cmd/nerdctl/image_convert_linux_test.go | 3 ++- cmd/nerdctl/image_cryptutil.go | 3 ++- cmd/nerdctl/image_encrypt_linux_test.go | 4 +++- cmd/nerdctl/image_history.go | 1 + cmd/nerdctl/image_history_test.go | 3 ++- cmd/nerdctl/image_list.go | 3 ++- cmd/nerdctl/image_list_test.go | 3 ++- cmd/nerdctl/image_load_linux_test.go | 3 ++- cmd/nerdctl/image_pull_linux_test.go | 3 ++- cmd/nerdctl/image_push_linux_test.go | 3 ++- cmd/nerdctl/image_save.go | 5 +++-- cmd/nerdctl/image_save_linux_test.go | 4 ++-- cmd/nerdctl/ipfs_build_linux_test.go | 4 ++-- cmd/nerdctl/ipfs_compose_linux_test.go | 3 ++- cmd/nerdctl/ipfs_linux_test.go | 4 ++-- cmd/nerdctl/login.go | 1 + cmd/nerdctl/login_linux_test.go | 3 ++- cmd/nerdctl/logout.go | 3 ++- cmd/nerdctl/main.go | 1 + cmd/nerdctl/main_test.go | 4 +++- cmd/nerdctl/main_unix.go | 1 + cmd/nerdctl/multi_platform_linux_test.go | 3 ++- cmd/nerdctl/namespace.go | 1 + cmd/nerdctl/namespace_remove.go | 3 ++- cmd/nerdctl/network_create.go | 1 + cmd/nerdctl/network_create_linux_test.go | 3 ++- cmd/nerdctl/network_inspect_test.go | 3 ++- cmd/nerdctl/network_remove.go | 4 ++-- cmd/nerdctl/system_events_linux_test.go | 3 ++- cmd/nerdctl/system_info.go | 3 ++- cmd/nerdctl/system_prune.go | 1 + cmd/nerdctl/system_prune_linux_test.go | 1 + cmd/nerdctl/version.go | 4 +++- cmd/nerdctl/volume_create.go | 1 + cmd/nerdctl/volume_create_test.go | 4 +++- cmd/nerdctl/volume_inspect_test.go | 6 ++++-- cmd/nerdctl/volume_namespace_test.go | 4 +++- cmd/nerdctl/volume_remove_linux_test.go | 6 ++++-- pkg/apparmorutil/apparmorutil_linux.go | 3 ++- pkg/buildkitutil/buildkitutil.go | 1 + pkg/buildkitutil/buildkitutil_linux.go | 1 + pkg/bypass4netnsutil/bypass.go | 8 +++++--- pkg/bypass4netnsutil/bypass4netnsutil.go | 1 + pkg/cioutil/container_io_windows.go | 1 + pkg/clientutil/client.go | 3 ++- pkg/cmd/apparmor/inspect_linux.go | 1 + pkg/cmd/apparmor/load_linux.go | 1 + pkg/cmd/apparmor/unload_linux.go | 1 + pkg/cmd/builder/build.go | 6 ++++-- pkg/cmd/builder/prune.go | 1 + pkg/cmd/compose/compose.go | 3 ++- pkg/cmd/container/attach.go | 1 + pkg/cmd/container/commit.go | 1 + pkg/cmd/container/cp_linux.go | 1 + pkg/cmd/container/create.go | 1 + pkg/cmd/container/exec.go | 1 + pkg/cmd/container/inspect.go | 1 + pkg/cmd/container/kill.go | 4 +++- pkg/cmd/container/list.go | 1 + pkg/cmd/container/list_util.go | 1 + pkg/cmd/container/logs.go | 1 + pkg/cmd/container/pause.go | 1 + pkg/cmd/container/prune.go | 1 + pkg/cmd/container/remove.go | 1 + pkg/cmd/container/rename.go | 1 + pkg/cmd/container/restart.go | 1 + pkg/cmd/container/run_cgroup_freebsd.go | 1 + pkg/cmd/container/run_cgroup_linux.go | 1 + pkg/cmd/container/run_cgroup_windows.go | 1 + pkg/cmd/container/run_freebsd.go | 1 + pkg/cmd/container/run_gpus.go | 1 + pkg/cmd/container/run_linux.go | 1 + pkg/cmd/container/run_mount.go | 1 + pkg/cmd/container/run_restart.go | 1 + pkg/cmd/container/run_security_linux.go | 1 + pkg/cmd/container/run_ulimit.go | 1 + pkg/cmd/container/run_windows.go | 1 + pkg/cmd/container/start.go | 1 + pkg/cmd/container/stats.go | 3 ++- pkg/cmd/container/stats_linux.go | 6 ++++-- pkg/cmd/container/stop.go | 1 + pkg/cmd/container/top.go | 1 + pkg/cmd/container/top_windows.go | 3 ++- pkg/cmd/container/unpause.go | 1 + pkg/cmd/container/wait.go | 1 + pkg/cmd/image/convert.go | 11 ++++++----- pkg/cmd/image/crypt.go | 1 + pkg/cmd/image/inspect.go | 4 +++- pkg/cmd/image/list.go | 3 ++- pkg/cmd/image/load.go | 3 ++- pkg/cmd/image/prune.go | 3 ++- pkg/cmd/image/pull.go | 1 + pkg/cmd/image/push.go | 7 ++++--- pkg/cmd/image/remove.go | 3 ++- pkg/cmd/image/save.go | 1 + pkg/cmd/image/tag.go | 1 + pkg/cmd/ipfs/registry_serve.go | 1 + pkg/cmd/login/login.go | 1 + pkg/cmd/namespace/create.go | 1 + pkg/cmd/namespace/inspect.go | 1 + pkg/cmd/namespace/remove.go | 1 + pkg/cmd/namespace/update.go | 1 + pkg/cmd/network/create.go | 1 + pkg/cmd/network/inspect.go | 1 + pkg/cmd/network/prune.go | 1 + pkg/cmd/network/remove.go | 1 + pkg/cmd/system/events.go | 3 ++- pkg/cmd/system/info.go | 1 + pkg/cmd/system/prune.go | 1 + pkg/cmd/volume/create.go | 3 ++- pkg/cmd/volume/inspect.go | 1 + pkg/cmd/volume/list.go | 1 + pkg/cmd/volume/prune.go | 1 + pkg/cmd/volume/rm.go | 1 + pkg/composer/build.go | 2 ++ pkg/composer/composer.go | 2 ++ pkg/composer/container.go | 1 + pkg/composer/copy.go | 4 +++- pkg/composer/create.go | 3 ++- pkg/composer/down.go | 1 + pkg/composer/exec.go | 1 + pkg/composer/logs.go | 2 ++ pkg/composer/orphans.go | 1 + pkg/composer/pause.go | 1 + pkg/composer/pull.go | 2 ++ pkg/composer/push.go | 2 ++ pkg/composer/restart.go | 2 ++ pkg/composer/rm.go | 1 + pkg/composer/run.go | 5 +++-- pkg/composer/serviceparser/build.go | 5 +++-- pkg/composer/serviceparser/build_test.go | 3 ++- pkg/composer/serviceparser/serviceparser.go | 2 ++ pkg/composer/serviceparser/serviceparser_test.go | 3 ++- pkg/composer/stop.go | 1 + pkg/composer/up.go | 2 ++ pkg/composer/up_network.go | 1 + pkg/composer/up_service.go | 1 + pkg/composer/up_volume.go | 1 + pkg/config/config.go | 1 + pkg/consoleutil/detach.go | 3 ++- pkg/containerinspector/containerinspector.go | 3 ++- pkg/containerinspector/containerinspector_linux.go | 4 ++-- pkg/containerutil/config.go | 1 + pkg/containerutil/container_network_manager.go | 1 + pkg/containerutil/container_network_manager_linux.go | 1 + pkg/containerutil/container_network_manager_other.go | 1 + pkg/containerutil/containerutil.go | 1 + pkg/containerutil/cp_linux.go | 4 +++- pkg/defaults/cgroup_linux.go | 1 + pkg/defaults/defaults_linux.go | 1 + pkg/dnsutil/hostsstore/hostsstore.go | 4 +++- pkg/dnsutil/hostsstore/updater.go | 1 + pkg/formatter/formatter.go | 1 + pkg/idutil/containerwalker/containerwalker.go | 1 + pkg/idutil/imagewalker/imagewalker.go | 1 + pkg/imageinspector/imageinspector.go | 1 + pkg/imgutil/commit/commit.go | 3 ++- pkg/imgutil/converter/zstd.go | 1 + .../dockerconfigresolver/dockerconfigresolver.go | 7 ++++--- pkg/imgutil/filtering.go | 4 +++- pkg/imgutil/imgutil.go | 3 ++- pkg/imgutil/pull/pull.go | 1 + pkg/imgutil/push/push.go | 3 ++- pkg/imgutil/snapshotter.go | 3 ++- pkg/imgutil/snapshotter_test.go | 1 + pkg/infoutil/infoutil.go | 2 ++ pkg/infoutil/infoutil_linux.go | 4 +++- pkg/infoutil/infoutil_test.go | 3 ++- pkg/infoutil/infoutil_windows.go | 1 + pkg/inspecttypes/dockercompat/dockercompat.go | 1 + pkg/inspecttypes/dockercompat/dockercompat_test.go | 1 + pkg/ipcutil/ipcutil.go | 1 + pkg/ipfs/image.go | 5 +++-- pkg/logging/cri_logger.go | 4 +++- pkg/logging/fluentd_logger.go | 4 +++- pkg/logging/journald_logger.go | 8 +++++--- pkg/logging/json_logger.go | 8 +++++--- pkg/logging/jsonfile/jsonfile.go | 3 ++- pkg/logging/log_viewer.go | 1 + pkg/logging/logging.go | 5 +++-- pkg/logging/syslog_logger.go | 3 ++- pkg/mountutil/mountutil.go | 1 + pkg/mountutil/mountutil_freebsd.go | 1 + pkg/mountutil/mountutil_linux.go | 1 + pkg/mountutil/mountutil_linux_test.go | 1 + pkg/mountutil/mountutil_windows.go | 1 + pkg/mountutil/mountutilmock/volumestore.mock.go | 3 ++- pkg/mountutil/volumestore/volumestore.go | 1 + pkg/namestore/namestore.go | 1 + pkg/netutil/netutil.go | 4 +++- pkg/netutil/netutil_test.go | 4 ++-- pkg/netutil/netutil_unix.go | 6 ++++-- pkg/nsutil/nsutil_test.go | 3 ++- pkg/ocihook/ocihook.go | 1 + pkg/ocihook/ocihook_linux.go | 1 + pkg/ocihook/rootless_linux.go | 4 +++- pkg/ocihook/rootless_other.go | 3 ++- pkg/platformutil/platformutil.go | 3 ++- pkg/portutil/portutil.go | 4 +++- pkg/portutil/portutil_test.go | 1 + pkg/rootlessutil/port_linux.go | 5 +++-- pkg/signutil/cosignutil.go | 1 + pkg/signutil/notationutil.go | 1 + pkg/signutil/signutil.go | 1 + pkg/snapshotterutil/sociutil.go | 1 + pkg/statsutil/stats_linux.go | 3 ++- pkg/sysinfo/cgroup2_linux.go | 3 ++- pkg/sysinfo/sysinfo_linux.go | 3 ++- pkg/taskutil/taskutil.go | 1 + pkg/testutil/testutil.go | 1 + 272 files changed, 479 insertions(+), 174 deletions(-) diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index 1ae4d230c3b..cec6ddb8597 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -25,6 +25,7 @@ import ( "github.com/spf13/cobra" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" ) diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index d4134dde94f..9da239c786b 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -23,9 +23,11 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" - "github.com/containerd/platforms" "gotest.tools/v3/assert" + + "github.com/containerd/platforms" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestBuild(t *testing.T) { diff --git a/cmd/nerdctl/builder_linux_test.go b/cmd/nerdctl/builder_linux_test.go index 42ae8376945..bca3a4649ba 100644 --- a/cmd/nerdctl/builder_linux_test.go +++ b/cmd/nerdctl/builder_linux_test.go @@ -24,9 +24,10 @@ import ( "path/filepath" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) func TestBuilderDebug(t *testing.T) { diff --git a/cmd/nerdctl/completion.go b/cmd/nerdctl/completion.go index f36bc7b1ba7..398723b3ee1 100644 --- a/cmd/nerdctl/completion.go +++ b/cmd/nerdctl/completion.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/netutil" diff --git a/cmd/nerdctl/compose_config_test.go b/cmd/nerdctl/compose_config_test.go index 67e99580cdd..415a4c1e7b4 100644 --- a/cmd/nerdctl/compose_config_test.go +++ b/cmd/nerdctl/compose_config_test.go @@ -22,8 +22,9 @@ import ( "path/filepath" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeConfig(t *testing.T) { diff --git a/cmd/nerdctl/compose_cp.go b/cmd/nerdctl/compose_cp.go index 859ebb4f85e..976a5617ed9 100644 --- a/cmd/nerdctl/compose_cp.go +++ b/cmd/nerdctl/compose_cp.go @@ -19,11 +19,12 @@ package main import ( "errors" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/spf13/cobra" ) func newComposeCopyCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_cp_linux_test.go b/cmd/nerdctl/compose_cp_linux_test.go index 46174e685e5..1ea44db4c23 100644 --- a/cmd/nerdctl/compose_cp_linux_test.go +++ b/cmd/nerdctl/compose_cp_linux_test.go @@ -22,8 +22,9 @@ import ( "path/filepath" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeCopy(t *testing.T) { diff --git a/cmd/nerdctl/compose_exec_linux_test.go b/cmd/nerdctl/compose_exec_linux_test.go index 2cb758f77dc..7805cb22dca 100644 --- a/cmd/nerdctl/compose_exec_linux_test.go +++ b/cmd/nerdctl/compose_exec_linux_test.go @@ -24,8 +24,9 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestComposeExec(t *testing.T) { diff --git a/cmd/nerdctl/compose_images.go b/cmd/nerdctl/compose_images.go index 45d66a15b8e..852cae4e437 100644 --- a/cmd/nerdctl/compose_images.go +++ b/cmd/nerdctl/compose_images.go @@ -28,6 +28,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/containerd/v2/pkg/progress" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/formatter" diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose_ps.go index ad43b5c0768..08b2040dce7 100644 --- a/cmd/nerdctl/compose_ps.go +++ b/cmd/nerdctl/compose_ps.go @@ -31,6 +31,7 @@ import ( "github.com/containerd/errdefs" gocni "github.com/containerd/go-cni" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/containerutil" diff --git a/cmd/nerdctl/compose_ps_linux_test.go b/cmd/nerdctl/compose_ps_linux_test.go index 55e0b5a756e..5bf8e7a0358 100644 --- a/cmd/nerdctl/compose_ps_linux_test.go +++ b/cmd/nerdctl/compose_ps_linux_test.go @@ -23,9 +23,10 @@ import ( "testing" "time" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/tabutil" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) func TestComposePs(t *testing.T) { diff --git a/cmd/nerdctl/compose_push.go b/cmd/nerdctl/compose_push.go index bfdf02a9d4e..cfa310a3e98 100644 --- a/cmd/nerdctl/compose_push.go +++ b/cmd/nerdctl/compose_push.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposePushCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_rm.go b/cmd/nerdctl/compose_rm.go index 536b919890b..778345e993a 100644 --- a/cmd/nerdctl/compose_rm.go +++ b/cmd/nerdctl/compose_rm.go @@ -20,10 +20,11 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeRemoveCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_run_linux_test.go b/cmd/nerdctl/compose_run_linux_test.go index f2e06fcea35..bdbe95a9760 100644 --- a/cmd/nerdctl/compose_run_linux_test.go +++ b/cmd/nerdctl/compose_run_linux_test.go @@ -23,11 +23,13 @@ import ( "testing" "time" + "gotest.tools/v3/assert" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" - "gotest.tools/v3/assert" ) func TestComposeRun(t *testing.T) { diff --git a/cmd/nerdctl/compose_start.go b/cmd/nerdctl/compose_start.go index 509ae1a1e05..f0ce42cfe29 100644 --- a/cmd/nerdctl/compose_start.go +++ b/cmd/nerdctl/compose_start.go @@ -26,6 +26,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/containerutil" diff --git a/cmd/nerdctl/compose_top.go b/cmd/nerdctl/compose_top.go index 70cd9ac1f54..a3356b8face 100644 --- a/cmd/nerdctl/compose_top.go +++ b/cmd/nerdctl/compose_top.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" diff --git a/cmd/nerdctl/compose_up.go b/cmd/nerdctl/compose_up.go index 5d871dff3bf..a38c4f9dab7 100644 --- a/cmd/nerdctl/compose_up.go +++ b/cmd/nerdctl/compose_up.go @@ -22,10 +22,11 @@ import ( "strconv" "strings" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" - "github.com/spf13/cobra" ) func newComposeUpCommand() *cobra.Command { diff --git a/cmd/nerdctl/compose_up_linux_test.go b/cmd/nerdctl/compose_up_linux_test.go index 94fccd05a02..f6a0f0a35ba 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/cmd/nerdctl/compose_up_linux_test.go @@ -28,6 +28,7 @@ import ( "gotest.tools/v3/icmd" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" diff --git a/cmd/nerdctl/compose_up_test.go b/cmd/nerdctl/compose_up_test.go index 8431ab4ece6..1941fef8c1d 100644 --- a/cmd/nerdctl/compose_up_test.go +++ b/cmd/nerdctl/compose_up_test.go @@ -23,9 +23,10 @@ import ( "runtime" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) // https://github.com/containerd/nerdctl/issues/1942 diff --git a/cmd/nerdctl/compose_version.go b/cmd/nerdctl/compose_version.go index 0382300ea02..e847bc1343e 100644 --- a/cmd/nerdctl/compose_version.go +++ b/cmd/nerdctl/compose_version.go @@ -20,8 +20,9 @@ import ( "fmt" "strings" - "github.com/containerd/nerdctl/v2/pkg/version" "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/pkg/version" ) func newComposeVersionCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_attach.go b/cmd/nerdctl/container_attach.go index cc6fe7d58c9..abb4d90db33 100644 --- a/cmd/nerdctl/container_attach.go +++ b/cmd/nerdctl/container_attach.go @@ -17,12 +17,14 @@ package main import ( + "github.com/spf13/cobra" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/consoleutil" - "github.com/spf13/cobra" ) func newAttachCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_attach_linux_test.go b/cmd/nerdctl/container_attach_linux_test.go index 84a774c7e4a..e0b04b87d5d 100644 --- a/cmd/nerdctl/container_attach_linux_test.go +++ b/cmd/nerdctl/container_attach_linux_test.go @@ -21,8 +21,9 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) // skipAttachForDocker should be called by attach-related tests that assert 'read detach keys' in stdout. diff --git a/cmd/nerdctl/container_cp_linux_test.go b/cmd/nerdctl/container_cp_linux_test.go index 807ea0f0619..33f59ba45d3 100644 --- a/cmd/nerdctl/container_cp_linux_test.go +++ b/cmd/nerdctl/container_cp_linux_test.go @@ -24,9 +24,10 @@ import ( "syscall" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) func TestCopyToContainer(t *testing.T) { diff --git a/cmd/nerdctl/container_create.go b/cmd/nerdctl/container_create.go index 1354050b880..49ed0af26bb 100644 --- a/cmd/nerdctl/container_create.go +++ b/cmd/nerdctl/container_create.go @@ -20,11 +20,12 @@ import ( "fmt" "runtime" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/containerutil" - "github.com/spf13/cobra" ) func newCreateCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_create_linux_test.go b/cmd/nerdctl/container_create_linux_test.go index e080cc72980..fa4e65525ab 100644 --- a/cmd/nerdctl/container_create_linux_test.go +++ b/cmd/nerdctl/container_create_linux_test.go @@ -22,9 +22,10 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" - "gotest.tools/v3/assert" ) func TestCreate(t *testing.T) { diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index 00f228f9fc9..08cd376d43c 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -31,13 +31,14 @@ import ( "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/continuity/fs" "github.com/containerd/log" + "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" - "github.com/containerd/platforms" ) func newDiffCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_exec.go b/cmd/nerdctl/container_exec.go index 7c879e288a8..267bc61a646 100644 --- a/cmd/nerdctl/container_exec.go +++ b/cmd/nerdctl/container_exec.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/cmd/nerdctl/container_inspect_windows_test.go b/cmd/nerdctl/container_inspect_windows_test.go index bc5cf33278b..16c8ec4de36 100644 --- a/cmd/nerdctl/container_inspect_windows_test.go +++ b/cmd/nerdctl/container_inspect_windows_test.go @@ -19,8 +19,9 @@ package main import ( "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestInspectProcessContainerContainsLabel(t *testing.T) { diff --git a/cmd/nerdctl/container_kill.go b/cmd/nerdctl/container_kill.go index 4c859ab6775..75154e63c3b 100644 --- a/cmd/nerdctl/container_kill.go +++ b/cmd/nerdctl/container_kill.go @@ -17,11 +17,13 @@ package main import ( + "github.com/spf13/cobra" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newKillCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_kill_linux_test.go b/cmd/nerdctl/container_kill_linux_test.go index 3651c06c6a9..076d8820498 100644 --- a/cmd/nerdctl/container_kill_linux_test.go +++ b/cmd/nerdctl/container_kill_linux_test.go @@ -21,11 +21,12 @@ import ( "strings" "testing" + "github.com/coreos/go-iptables/iptables" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" iptablesutil "github.com/containerd/nerdctl/v2/pkg/testutil/iptables" - "github.com/coreos/go-iptables/iptables" - "gotest.tools/v3/assert" ) // TestKillCleanupForwards runs a container that exposes a port and then kill it. diff --git a/cmd/nerdctl/container_list_linux_test.go b/cmd/nerdctl/container_list_linux_test.go index 48d442d303a..ab6c3173e42 100644 --- a/cmd/nerdctl/container_list_linux_test.go +++ b/cmd/nerdctl/container_list_linux_test.go @@ -24,11 +24,12 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/tabutil" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) type psTestContainer struct { diff --git a/cmd/nerdctl/container_list_windows_test.go b/cmd/nerdctl/container_list_windows_test.go index 5efbac82da3..8ad0c7ea5ef 100644 --- a/cmd/nerdctl/container_list_windows_test.go +++ b/cmd/nerdctl/container_list_windows_test.go @@ -21,11 +21,12 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/tabutil" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) type psTestContainer struct { diff --git a/cmd/nerdctl/container_logs_test.go b/cmd/nerdctl/container_logs_test.go index 8409c1d6cae..7f6db3831ab 100644 --- a/cmd/nerdctl/container_logs_test.go +++ b/cmd/nerdctl/container_logs_test.go @@ -23,8 +23,9 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestLogs(t *testing.T) { diff --git a/cmd/nerdctl/container_pause.go b/cmd/nerdctl/container_pause.go index f66f2a9753b..8176e8c2f16 100644 --- a/cmd/nerdctl/container_pause.go +++ b/cmd/nerdctl/container_pause.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/cmd/nerdctl/container_remove_windows_test.go b/cmd/nerdctl/container_remove_windows_test.go index a93573c5ca5..7f113729000 100644 --- a/cmd/nerdctl/container_remove_windows_test.go +++ b/cmd/nerdctl/container_remove_windows_test.go @@ -19,8 +19,9 @@ package main import ( "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRemoveProcessContainer(t *testing.T) { diff --git a/cmd/nerdctl/container_rename.go b/cmd/nerdctl/container_rename.go index 6e5857117e6..915e1d2eb00 100644 --- a/cmd/nerdctl/container_rename.go +++ b/cmd/nerdctl/container_rename.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" - "github.com/spf13/cobra" ) func newRenameCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_restart_linux_test.go b/cmd/nerdctl/container_restart_linux_test.go index cd1160a540e..dddaef2f40b 100644 --- a/cmd/nerdctl/container_restart_linux_test.go +++ b/cmd/nerdctl/container_restart_linux_test.go @@ -22,8 +22,9 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRestart(t *testing.T) { diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 86af3073260..08401a0366e 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -22,8 +22,11 @@ import ( "runtime" "strings" + "github.com/spf13/cobra" + "github.com/containerd/console" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/annotations" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -37,7 +40,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/containerd/nerdctl/v2/pkg/signalutil" "github.com/containerd/nerdctl/v2/pkg/taskutil" - "github.com/spf13/cobra" ) const ( diff --git a/cmd/nerdctl/container_run_cgroup_linux_test.go b/cmd/nerdctl/container_run_cgroup_linux_test.go index a5abcdc8744..43c491dce55 100644 --- a/cmd/nerdctl/container_run_cgroup_linux_test.go +++ b/cmd/nerdctl/container_run_cgroup_linux_test.go @@ -23,12 +23,14 @@ import ( "path/filepath" "testing" + "github.com/moby/sys/userns" + "gotest.tools/v3/assert" + "github.com/containerd/cgroups/v3" "github.com/containerd/continuity/testutil/loopback" + "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/testutil" - "github.com/moby/sys/userns" - "gotest.tools/v3/assert" ) func TestRunCgroupV2(t *testing.T) { diff --git a/cmd/nerdctl/container_run_gpus_test.go b/cmd/nerdctl/container_run_gpus_test.go index 392a978d618..fea180b732b 100644 --- a/cmd/nerdctl/container_run_gpus_test.go +++ b/cmd/nerdctl/container_run_gpus_test.go @@ -19,9 +19,10 @@ package main import ( "testing" - "github.com/containerd/nerdctl/v2/pkg/cmd/container" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" + + "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) func TestParseGpusOptAll(t *testing.T) { diff --git a/cmd/nerdctl/container_run_linux.go b/cmd/nerdctl/container_run_linux.go index cdbfa19f8d9..28d3f543160 100644 --- a/cmd/nerdctl/container_run_linux.go +++ b/cmd/nerdctl/container_run_linux.go @@ -19,8 +19,9 @@ package main import ( "strings" - "github.com/containerd/containerd/v2/pkg/cap" "github.com/spf13/cobra" + + "github.com/containerd/containerd/v2/pkg/cap" ) func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { diff --git a/cmd/nerdctl/container_run_linux_test.go b/cmd/nerdctl/container_run_linux_test.go index f73fd8ebfda..87194131181 100644 --- a/cmd/nerdctl/container_run_linux_test.go +++ b/cmd/nerdctl/container_run_linux_test.go @@ -33,11 +33,12 @@ import ( "testing" "time" + "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" - "gotest.tools/v3/icmd" ) func TestRunCustomRootfs(t *testing.T) { diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container_run_mount_linux_test.go index ea97047ec9c..d91d37971af 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container_run_mount_linux_test.go @@ -27,6 +27,7 @@ import ( "gotest.tools/v3/assert" "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" ) diff --git a/cmd/nerdctl/container_run_mount_windows_test.go b/cmd/nerdctl/container_run_mount_windows_test.go index 7c84bd17f15..3ad3f9506f9 100644 --- a/cmd/nerdctl/container_run_mount_windows_test.go +++ b/cmd/nerdctl/container_run_mount_windows_test.go @@ -21,9 +21,10 @@ import ( "os" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) func TestRunMountVolume(t *testing.T) { diff --git a/cmd/nerdctl/container_run_network.go b/cmd/nerdctl/container_run_network.go index 3e4444267d9..178d277232a 100644 --- a/cmd/nerdctl/container_run_network.go +++ b/cmd/nerdctl/container_run_network.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" gocni "github.com/containerd/go-cni" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/portutil" "github.com/containerd/nerdctl/v2/pkg/strutil" diff --git a/cmd/nerdctl/container_run_network_base_test.go b/cmd/nerdctl/container_run_network_base_test.go index f072ac34ecb..e6f5c112ca7 100644 --- a/cmd/nerdctl/container_run_network_base_test.go +++ b/cmd/nerdctl/container_run_network_base_test.go @@ -26,9 +26,10 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" - "gotest.tools/v3/assert" ) // Tests various port mapping argument combinations by starting an nginx container and diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index a1d86e56c40..9615529146c 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -25,12 +25,14 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" + "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" - "gotest.tools/v3/assert" - "gotest.tools/v3/icmd" ) // TestRunInternetConnectivity tests Internet connectivity with `apk update` diff --git a/cmd/nerdctl/container_run_network_windows_test.go b/cmd/nerdctl/container_run_network_windows_test.go index 5a842cde06e..e8c42559ad8 100644 --- a/cmd/nerdctl/container_run_network_windows_test.go +++ b/cmd/nerdctl/container_run_network_windows_test.go @@ -23,10 +23,11 @@ import ( "testing" "github.com/Microsoft/hcsshim" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) // TestRunInternetConnectivity tests Internet connectivity by pinging github.com. diff --git a/cmd/nerdctl/container_run_restart_linux_test.go b/cmd/nerdctl/container_run_restart_linux_test.go index 44e42b2393e..d9ba357b8fc 100644 --- a/cmd/nerdctl/container_run_restart_linux_test.go +++ b/cmd/nerdctl/container_run_restart_linux_test.go @@ -24,11 +24,11 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/v2/pkg/testutil" - "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" - "gotest.tools/v3/assert" "gotest.tools/v3/poll" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" ) func TestRunRestart(t *testing.T) { diff --git a/cmd/nerdctl/container_run_security_linux_test.go b/cmd/nerdctl/container_run_security_linux_test.go index e5a029d6a08..be1191f1d1e 100644 --- a/cmd/nerdctl/container_run_security_linux_test.go +++ b/cmd/nerdctl/container_run_security_linux_test.go @@ -24,11 +24,11 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" - - "gotest.tools/v3/assert" ) func getCapEff(base *testutil.Base, args ...string) uint64 { diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index 16ada61828d..940eb6e5743 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -30,10 +30,11 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" "gotest.tools/v3/poll" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRunEntrypointWithBuild(t *testing.T) { diff --git a/cmd/nerdctl/container_run_windows_test.go b/cmd/nerdctl/container_run_windows_test.go index 38faa432ec9..d3af8a6534f 100644 --- a/cmd/nerdctl/container_run_windows_test.go +++ b/cmd/nerdctl/container_run_windows_test.go @@ -22,8 +22,9 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestRunHostProcessContainer(t *testing.T) { diff --git a/cmd/nerdctl/container_start.go b/cmd/nerdctl/container_start.go index 09fec22cc68..793624ecc3e 100644 --- a/cmd/nerdctl/container_start.go +++ b/cmd/nerdctl/container_start.go @@ -17,12 +17,14 @@ package main import ( + "github.com/spf13/cobra" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/consoleutil" - "github.com/spf13/cobra" ) func newStartCommand() *cobra.Command { diff --git a/cmd/nerdctl/container_start_linux_test.go b/cmd/nerdctl/container_start_linux_test.go index d7b35c6271b..91df7a1b9cb 100644 --- a/cmd/nerdctl/container_start_linux_test.go +++ b/cmd/nerdctl/container_start_linux_test.go @@ -21,8 +21,9 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestStartDetachKeys(t *testing.T) { diff --git a/cmd/nerdctl/container_stats.go b/cmd/nerdctl/container_stats.go index 9f39942e6f9..eaec1307c45 100644 --- a/cmd/nerdctl/container_stats.go +++ b/cmd/nerdctl/container_stats.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/cmd/nerdctl/container_stop.go b/cmd/nerdctl/container_stop.go index 31f2751981c..571b9e29e87 100644 --- a/cmd/nerdctl/container_stop.go +++ b/cmd/nerdctl/container_stop.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/cmd/nerdctl/container_stop_linux_test.go b/cmd/nerdctl/container_stop_linux_test.go index a29e697bdb6..bdc17e00821 100644 --- a/cmd/nerdctl/container_stop_linux_test.go +++ b/cmd/nerdctl/container_stop_linux_test.go @@ -22,13 +22,13 @@ import ( "strings" "testing" + "github.com/coreos/go-iptables/iptables" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" iptablesutil "github.com/containerd/nerdctl/v2/pkg/testutil/iptables" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" - "github.com/coreos/go-iptables/iptables" - - "gotest.tools/v3/assert" ) func TestStopStart(t *testing.T) { diff --git a/cmd/nerdctl/container_top.go b/cmd/nerdctl/container_top.go index b5434dfd7c0..168a4e978b0 100644 --- a/cmd/nerdctl/container_top.go +++ b/cmd/nerdctl/container_top.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/cmd/nerdctl/container_unpause.go b/cmd/nerdctl/container_unpause.go index 190ea8e6ffe..98e3e9cb500 100644 --- a/cmd/nerdctl/container_unpause.go +++ b/cmd/nerdctl/container_unpause.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index 6de1edcaa1a..8f020071bec 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -31,13 +31,14 @@ import ( "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/typeurl/v2" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" nerdctlContainer "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/infoutil" - "github.com/containerd/typeurl/v2" ) type updateResourceOptions struct { diff --git a/cmd/nerdctl/container_wait.go b/cmd/nerdctl/container_wait.go index e9e456f9d4d..a4d962bf4ef 100644 --- a/cmd/nerdctl/container_wait.go +++ b/cmd/nerdctl/container_wait.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/cmd/nerdctl/flagutil.go b/cmd/nerdctl/flagutil.go index 795d9d2a0cd..c88e7597af9 100644 --- a/cmd/nerdctl/flagutil.go +++ b/cmd/nerdctl/flagutil.go @@ -17,8 +17,9 @@ package main import ( - "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/pkg/api/types" ) func processImageSignOptions(cmd *cobra.Command) (opt types.ImageSignOptions, err error) { diff --git a/cmd/nerdctl/image_convert_linux_test.go b/cmd/nerdctl/image_convert_linux_test.go index a8b53401d72..e3557f91fae 100644 --- a/cmd/nerdctl/image_convert_linux_test.go +++ b/cmd/nerdctl/image_convert_linux_test.go @@ -21,10 +21,11 @@ import ( "runtime" "testing" + "gotest.tools/v3/icmd" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" - "gotest.tools/v3/icmd" ) func TestImageConvertNydus(t *testing.T) { diff --git a/cmd/nerdctl/image_cryptutil.go b/cmd/nerdctl/image_cryptutil.go index 47d5fdb0c52..28b38dd1ff2 100644 --- a/cmd/nerdctl/image_cryptutil.go +++ b/cmd/nerdctl/image_cryptutil.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" - "github.com/spf13/cobra" ) // registerImgcryptFlags register flags that correspond to parseImgcryptFlags(). diff --git a/cmd/nerdctl/image_encrypt_linux_test.go b/cmd/nerdctl/image_encrypt_linux_test.go index e48e1769efb..e8998a83060 100644 --- a/cmd/nerdctl/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image_encrypt_linux_test.go @@ -24,12 +24,14 @@ import ( "path/filepath" "testing" + "gotest.tools/v3/assert" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" - "gotest.tools/v3/assert" ) type jweKeyPair struct { diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index 6bb75a8ad77..4f77e8a819b 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -34,6 +34,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" diff --git a/cmd/nerdctl/image_history_test.go b/cmd/nerdctl/image_history_test.go index 93b1d942a03..d68930cb384 100644 --- a/cmd/nerdctl/image_history_test.go +++ b/cmd/nerdctl/image_history_test.go @@ -25,8 +25,9 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) type historyObj struct { diff --git a/cmd/nerdctl/image_list.go b/cmd/nerdctl/image_list.go index a7dc5be6f23..561b0c00956 100644 --- a/cmd/nerdctl/image_list.go +++ b/cmd/nerdctl/image_list.go @@ -19,11 +19,12 @@ package main import ( "fmt" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/containerd/nerdctl/v2/pkg/referenceutil" - "github.com/spf13/cobra" ) func newImagesCommand() *cobra.Command { diff --git a/cmd/nerdctl/image_list_test.go b/cmd/nerdctl/image_list_test.go index 993a30eae52..ba855cc2303 100644 --- a/cmd/nerdctl/image_list_test.go +++ b/cmd/nerdctl/image_list_test.go @@ -22,9 +22,10 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/tabutil" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) func TestImagesWithNames(t *testing.T) { diff --git a/cmd/nerdctl/image_load_linux_test.go b/cmd/nerdctl/image_load_linux_test.go index bb48046844d..f8e3c9684f8 100644 --- a/cmd/nerdctl/image_load_linux_test.go +++ b/cmd/nerdctl/image_load_linux_test.go @@ -24,8 +24,9 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestLoadStdinFromPipe(t *testing.T) { diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image_pull_linux_test.go index 86aba9972bd..edfc5af1854 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image_pull_linux_test.go @@ -24,9 +24,10 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" - "gotest.tools/v3/assert" ) type cosignKeyPair struct { diff --git a/cmd/nerdctl/image_push_linux_test.go b/cmd/nerdctl/image_push_linux_test.go index 0bea04d169f..17ab1a89227 100644 --- a/cmd/nerdctl/image_push_linux_test.go +++ b/cmd/nerdctl/image_push_linux_test.go @@ -22,9 +22,10 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" - "gotest.tools/v3/assert" ) func TestPushPlainHTTPFails(t *testing.T) { diff --git a/cmd/nerdctl/image_save.go b/cmd/nerdctl/image_save.go index a72b7b245b2..dc4e7a86a0a 100644 --- a/cmd/nerdctl/image_save.go +++ b/cmd/nerdctl/image_save.go @@ -20,11 +20,12 @@ import ( "fmt" "os" + "github.com/mattn/go-isatty" + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" - "github.com/mattn/go-isatty" - "github.com/spf13/cobra" ) func newSaveCommand() *cobra.Command { diff --git a/cmd/nerdctl/image_save_linux_test.go b/cmd/nerdctl/image_save_linux_test.go index 82072f46623..0536d180983 100644 --- a/cmd/nerdctl/image_save_linux_test.go +++ b/cmd/nerdctl/image_save_linux_test.go @@ -26,9 +26,9 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestSave(t *testing.T) { diff --git a/cmd/nerdctl/ipfs_build_linux_test.go b/cmd/nerdctl/ipfs_build_linux_test.go index 5fc6efc307e..0623fee2b19 100644 --- a/cmd/nerdctl/ipfs_build_linux_test.go +++ b/cmd/nerdctl/ipfs_build_linux_test.go @@ -22,10 +22,10 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" "gotest.tools/v3/icmd" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestIPFSBuild(t *testing.T) { diff --git a/cmd/nerdctl/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs_compose_linux_test.go index 1872d24596e..e0646cc2632 100644 --- a/cmd/nerdctl/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs_compose_linux_test.go @@ -22,10 +22,11 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" - "gotest.tools/v3/assert" ) func TestIPFSComposeUp(t *testing.T) { diff --git a/cmd/nerdctl/ipfs_linux_test.go b/cmd/nerdctl/ipfs_linux_test.go index cb4e6e32efe..0cff7e9433e 100644 --- a/cmd/nerdctl/ipfs_linux_test.go +++ b/cmd/nerdctl/ipfs_linux_test.go @@ -20,12 +20,12 @@ import ( "fmt" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" - - "gotest.tools/v3/assert" ) func TestIPFS(t *testing.T) { diff --git a/cmd/nerdctl/login.go b/cmd/nerdctl/login.go index d8d27415167..7772692f5ee 100644 --- a/cmd/nerdctl/login.go +++ b/cmd/nerdctl/login.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/login" ) diff --git a/cmd/nerdctl/login_linux_test.go b/cmd/nerdctl/login_linux_test.go index 4429b4480ea..395792c32fb 100644 --- a/cmd/nerdctl/login_linux_test.go +++ b/cmd/nerdctl/login_linux_test.go @@ -25,10 +25,11 @@ import ( "strconv" "testing" + "gotest.tools/v3/icmd" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testca" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" - "gotest.tools/v3/icmd" ) func safeRandomString(n int) string { diff --git a/cmd/nerdctl/logout.go b/cmd/nerdctl/logout.go index a08c2bdd0a8..4c7d10c07b8 100644 --- a/cmd/nerdctl/logout.go +++ b/cmd/nerdctl/logout.go @@ -19,9 +19,10 @@ package main import ( "fmt" - "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" dockercliconfig "github.com/docker/cli/cli/config" "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" ) func newLogoutCommand() *cobra.Command { diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 4c5e00272fd..e4af1c72fbe 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -31,6 +31,7 @@ import ( "github.com/spf13/pflag" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/config" ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/errutil" diff --git a/cmd/nerdctl/main_test.go b/cmd/nerdctl/main_test.go index b8400730133..a450c963bf5 100644 --- a/cmd/nerdctl/main_test.go +++ b/cmd/nerdctl/main_test.go @@ -21,9 +21,11 @@ import ( "path/filepath" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) func TestMain(m *testing.M) { diff --git a/cmd/nerdctl/main_unix.go b/cmd/nerdctl/main_unix.go index 2a768500566..af6bb4d2434 100644 --- a/cmd/nerdctl/main_unix.go +++ b/cmd/nerdctl/main_unix.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" diff --git a/cmd/nerdctl/multi_platform_linux_test.go b/cmd/nerdctl/multi_platform_linux_test.go index cf9b130dd59..638b265eae5 100644 --- a/cmd/nerdctl/multi_platform_linux_test.go +++ b/cmd/nerdctl/multi_platform_linux_test.go @@ -22,10 +22,11 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" - "gotest.tools/v3/assert" ) func testMultiPlatformRun(base *testutil.Base, alpineImage string) { diff --git a/cmd/nerdctl/namespace.go b/cmd/nerdctl/namespace.go index ecd41989026..3faa08f09ea 100644 --- a/cmd/nerdctl/namespace.go +++ b/cmd/nerdctl/namespace.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) diff --git a/cmd/nerdctl/namespace_remove.go b/cmd/nerdctl/namespace_remove.go index c8b6c1c8c1c..aa9a887a9b0 100644 --- a/cmd/nerdctl/namespace_remove.go +++ b/cmd/nerdctl/namespace_remove.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" - "github.com/spf13/cobra" ) func newNamespaceRmCommand() *cobra.Command { diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index 9cb0191f35e..a1bfe008619 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" "github.com/containerd/containerd/v2/pkg/identifiers" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" "github.com/containerd/nerdctl/v2/pkg/strutil" diff --git a/cmd/nerdctl/network_create_linux_test.go b/cmd/nerdctl/network_create_linux_test.go index 4936edf0991..0ff4cc9b4c8 100644 --- a/cmd/nerdctl/network_create_linux_test.go +++ b/cmd/nerdctl/network_create_linux_test.go @@ -22,8 +22,9 @@ import ( "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func TestNetworkCreateWithMTU(t *testing.T) { diff --git a/cmd/nerdctl/network_inspect_test.go b/cmd/nerdctl/network_inspect_test.go index 0582bb7fc3d..aa47a33ce4f 100644 --- a/cmd/nerdctl/network_inspect_test.go +++ b/cmd/nerdctl/network_inspect_test.go @@ -20,9 +20,10 @@ import ( "runtime" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) func TestNetworkInspect(t *testing.T) { diff --git a/cmd/nerdctl/network_remove.go b/cmd/nerdctl/network_remove.go index 3b8dae7fb1d..80eb48ac98d 100644 --- a/cmd/nerdctl/network_remove.go +++ b/cmd/nerdctl/network_remove.go @@ -17,12 +17,12 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/network" "github.com/containerd/nerdctl/v2/pkg/netutil" - - "github.com/spf13/cobra" ) func newNetworkRmCommand() *cobra.Command { diff --git a/cmd/nerdctl/system_events_linux_test.go b/cmd/nerdctl/system_events_linux_test.go index 16a0a954ac0..28c442fa595 100644 --- a/cmd/nerdctl/system_events_linux_test.go +++ b/cmd/nerdctl/system_events_linux_test.go @@ -22,8 +22,9 @@ import ( "testing" "time" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func testEventFilter(t *testing.T, args ...string) string { diff --git a/cmd/nerdctl/system_info.go b/cmd/nerdctl/system_info.go index b7a69568df6..b2562319a97 100644 --- a/cmd/nerdctl/system_info.go +++ b/cmd/nerdctl/system_info.go @@ -17,10 +17,11 @@ package main import ( + "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/system" - "github.com/spf13/cobra" ) func newInfoCommand() *cobra.Command { diff --git a/cmd/nerdctl/system_prune.go b/cmd/nerdctl/system_prune.go index f521d223381..ed3e8cd370f 100644 --- a/cmd/nerdctl/system_prune.go +++ b/cmd/nerdctl/system_prune.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/cobra" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/system" diff --git a/cmd/nerdctl/system_prune_linux_test.go b/cmd/nerdctl/system_prune_linux_test.go index 8356ccd3adc..3070cdde5fb 100644 --- a/cmd/nerdctl/system_prune_linux_test.go +++ b/cmd/nerdctl/system_prune_linux_test.go @@ -26,6 +26,7 @@ import ( "testing" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/testutil" ) diff --git a/cmd/nerdctl/version.go b/cmd/nerdctl/version.go index 6d09a364321..6eb2528dce5 100644 --- a/cmd/nerdctl/version.go +++ b/cmd/nerdctl/version.go @@ -23,13 +23,15 @@ import ( "os" "text/template" + "github.com/spf13/cobra" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/spf13/cobra" ) func newVersionCommand() *cobra.Command { diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume_create.go index 55d50b7b3ec..fefc7d2c0c4 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume_create.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" ) diff --git a/cmd/nerdctl/volume_create_test.go b/cmd/nerdctl/volume_create_test.go index 5b94bbe6389..9780fc3d20e 100644 --- a/cmd/nerdctl/volume_create_test.go +++ b/cmd/nerdctl/volume_create_test.go @@ -19,9 +19,11 @@ package main import ( "testing" + "gotest.tools/v3/icmd" + "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/icmd" ) func TestVolumeCreate(t *testing.T) { diff --git a/cmd/nerdctl/volume_inspect_test.go b/cmd/nerdctl/volume_inspect_test.go index dfaca86484f..9b7dfb31e15 100644 --- a/cmd/nerdctl/volume_inspect_test.go +++ b/cmd/nerdctl/volume_inspect_test.go @@ -25,11 +25,13 @@ import ( "strings" "testing" + "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" + "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" - "gotest.tools/v3/icmd" ) func createFileWithSize(base *testutil.Base, vol string, size int64) { diff --git a/cmd/nerdctl/volume_namespace_test.go b/cmd/nerdctl/volume_namespace_test.go index 9eb1aa32551..8c775d49a08 100644 --- a/cmd/nerdctl/volume_namespace_test.go +++ b/cmd/nerdctl/volume_namespace_test.go @@ -19,9 +19,11 @@ package main import ( "testing" + "gotest.tools/v3/icmd" + "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/icmd" ) func TestVolumeNamespace(t *testing.T) { diff --git a/cmd/nerdctl/volume_remove_linux_test.go b/cmd/nerdctl/volume_remove_linux_test.go index 73e63dd1b4d..b5757946720 100644 --- a/cmd/nerdctl/volume_remove_linux_test.go +++ b/cmd/nerdctl/volume_remove_linux_test.go @@ -21,10 +21,12 @@ import ( "strings" "testing" - "github.com/containerd/errdefs" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" + + "github.com/containerd/errdefs" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) // TestVolumeRemove does test a large variety of volume remove situations, albeit none of them being diff --git a/pkg/apparmorutil/apparmorutil_linux.go b/pkg/apparmorutil/apparmorutil_linux.go index c8bb17a31bb..600047a54da 100644 --- a/pkg/apparmorutil/apparmorutil_linux.go +++ b/pkg/apparmorutil/apparmorutil_linux.go @@ -23,9 +23,10 @@ import ( "strings" "sync" + "github.com/moby/sys/userns" + "github.com/containerd/containerd/v2/pkg/apparmor" "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/buildkitutil/buildkitutil.go b/pkg/buildkitutil/buildkitutil.go index 87bc066a054..5b9570a1ddb 100644 --- a/pkg/buildkitutil/buildkitutil.go +++ b/pkg/buildkitutil/buildkitutil.go @@ -38,6 +38,7 @@ import ( "strings" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) diff --git a/pkg/buildkitutil/buildkitutil_linux.go b/pkg/buildkitutil/buildkitutil_linux.go index 55740a29af3..dad13d022f2 100644 --- a/pkg/buildkitutil/buildkitutil_linux.go +++ b/pkg/buildkitutil/buildkitutil_linux.go @@ -20,6 +20,7 @@ import ( "fmt" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) diff --git a/pkg/bypass4netnsutil/bypass.go b/pkg/bypass4netnsutil/bypass.go index 2008d457f80..a6112ea3858 100644 --- a/pkg/bypass4netnsutil/bypass.go +++ b/pkg/bypass4netnsutil/bypass.go @@ -23,12 +23,14 @@ import ( "net" "path/filepath" - "github.com/containerd/errdefs" - gocni "github.com/containerd/go-cni" - "github.com/containerd/nerdctl/v2/pkg/annotations" b4nnapi "github.com/rootless-containers/bypass4netns/pkg/api" "github.com/rootless-containers/bypass4netns/pkg/api/daemon/client" rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" + + "github.com/containerd/errdefs" + gocni "github.com/containerd/go-cni" + + "github.com/containerd/nerdctl/v2/pkg/annotations" ) func NewBypass4netnsCNIBypassManager(client client.Client, rlkClient rlkclient.Client, annotationsMap map[string]string) (*Bypass4netnsCNIBypassManager, error) { diff --git a/pkg/bypass4netnsutil/bypass4netnsutil.go b/pkg/bypass4netnsutil/bypass4netnsutil.go index 81db6e6d50b..7fa7e605a72 100644 --- a/pkg/bypass4netnsutil/bypass4netnsutil.go +++ b/pkg/bypass4netnsutil/bypass4netnsutil.go @@ -28,6 +28,7 @@ import ( "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/annotations" ) diff --git a/pkg/cioutil/container_io_windows.go b/pkg/cioutil/container_io_windows.go index 97e521b2c7f..4d9789e0763 100644 --- a/pkg/cioutil/container_io_windows.go +++ b/pkg/cioutil/container_io_windows.go @@ -22,6 +22,7 @@ import ( "os/exec" "github.com/Microsoft/go-winio" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" ) diff --git a/pkg/clientutil/client.go b/pkg/clientutil/client.go index b4118bc49c3..7304f7a44ec 100644 --- a/pkg/clientutil/client.go +++ b/pkg/clientutil/client.go @@ -29,9 +29,10 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/log" + "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/systemutil" - "github.com/containerd/platforms" ) func NewClient(ctx context.Context, namespace, address string, opts ...containerd.Opt) (*containerd.Client, context.Context, context.CancelFunc, error) { diff --git a/pkg/cmd/apparmor/inspect_linux.go b/pkg/cmd/apparmor/inspect_linux.go index 53e2652be4d..67b067b532f 100644 --- a/pkg/cmd/apparmor/inspect_linux.go +++ b/pkg/cmd/apparmor/inspect_linux.go @@ -20,6 +20,7 @@ import ( "fmt" "github.com/containerd/containerd/v2/contrib/apparmor" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/defaults" ) diff --git a/pkg/cmd/apparmor/load_linux.go b/pkg/cmd/apparmor/load_linux.go index 73bf9f93d98..f5930379a6c 100644 --- a/pkg/cmd/apparmor/load_linux.go +++ b/pkg/cmd/apparmor/load_linux.go @@ -19,6 +19,7 @@ package apparmor import ( "github.com/containerd/containerd/v2/contrib/apparmor" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/defaults" ) diff --git a/pkg/cmd/apparmor/unload_linux.go b/pkg/cmd/apparmor/unload_linux.go index 87458d87341..f9ab7779f0d 100644 --- a/pkg/cmd/apparmor/unload_linux.go +++ b/pkg/cmd/apparmor/unload_linux.go @@ -18,6 +18,7 @@ package apparmor import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" ) diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 449b5f2b998..03d87848fe1 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -28,18 +28,20 @@ import ( "strconv" "strings" + distributionref "github.com/distribution/reference" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/images/archive" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/containerd/platforms" - distributionref "github.com/distribution/reference" ) type PlatformParser interface { diff --git a/pkg/cmd/builder/prune.go b/pkg/cmd/builder/prune.go index 121b9230962..541507f6cd0 100644 --- a/pkg/cmd/builder/prune.go +++ b/pkg/cmd/builder/prune.go @@ -24,6 +24,7 @@ import ( "os/exec" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" ) diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 090292b3d59..7afbd74e0b1 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -27,6 +27,8 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" + "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -37,7 +39,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/nerdctl/v2/pkg/signutil" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/containerd/platforms" ) // New returns a new *composer.Composer. diff --git a/pkg/cmd/container/attach.go b/pkg/cmd/container/attach.go index 31b480770f9..eb74252cf1d 100644 --- a/pkg/cmd/container/attach.go +++ b/pkg/cmd/container/attach.go @@ -25,6 +25,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/consoleutil" "github.com/containerd/nerdctl/v2/pkg/errutil" diff --git a/pkg/cmd/container/commit.go b/pkg/cmd/container/commit.go index 1814b926ebe..32f78d871be 100644 --- a/pkg/cmd/container/commit.go +++ b/pkg/cmd/container/commit.go @@ -24,6 +24,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/imgutil/commit" diff --git a/pkg/cmd/container/cp_linux.go b/pkg/cmd/container/cp_linux.go index 19b8a69c8da..5d883a47565 100644 --- a/pkg/cmd/container/cp_linux.go +++ b/pkg/cmd/container/cp_linux.go @@ -21,6 +21,7 @@ import ( "fmt" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 6a9eeeba33a..71c93b50272 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -39,6 +39,7 @@ import ( "github.com/containerd/containerd/v2/pkg/oci" gocni "github.com/containerd/go-cni" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/annotations" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" diff --git a/pkg/cmd/container/exec.go b/pkg/cmd/container/exec.go index 7a0a715a840..a7ad6857c33 100644 --- a/pkg/cmd/container/exec.go +++ b/pkg/cmd/container/exec.go @@ -28,6 +28,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/consoleutil" "github.com/containerd/nerdctl/v2/pkg/flagutil" diff --git a/pkg/cmd/container/inspect.go b/pkg/cmd/container/inspect.go index 2e2c399c221..72db92d4248 100644 --- a/pkg/cmd/container/inspect.go +++ b/pkg/cmd/container/inspect.go @@ -24,6 +24,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerdutil" "github.com/containerd/nerdctl/v2/pkg/containerinspector" diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index 661e465d6c8..50c2900bfbd 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -24,11 +24,14 @@ import ( "strings" "syscall" + "github.com/moby/sys/signal" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/errdefs" gocni "github.com/containerd/go-cni" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" @@ -37,7 +40,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" "github.com/containerd/nerdctl/v2/pkg/portutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/moby/sys/signal" ) // Kill kills a list of containers diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index 206574d391c..2914e49e739 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -29,6 +29,7 @@ import ( "github.com/containerd/containerd/v2/pkg/progress" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerdutil" "github.com/containerd/nerdctl/v2/pkg/containerutil" diff --git a/pkg/cmd/container/list_util.go b/pkg/cmd/container/list_util.go index b1b1906b254..da8992c4064 100644 --- a/pkg/cmd/container/list_util.go +++ b/pkg/cmd/container/list_util.go @@ -26,6 +26,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/containerutil" ) diff --git a/pkg/cmd/container/logs.go b/pkg/cmd/container/logs.go index 1d9193e804b..2deb143e6bc 100644 --- a/pkg/cmd/container/logs.go +++ b/pkg/cmd/container/logs.go @@ -26,6 +26,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/api/types/cri" "github.com/containerd/nerdctl/v2/pkg/clientutil" diff --git a/pkg/cmd/container/pause.go b/pkg/cmd/container/pause.go index 0e3664ca7d1..99451a8e3e5 100644 --- a/pkg/cmd/container/pause.go +++ b/pkg/cmd/container/pause.go @@ -21,6 +21,7 @@ import ( "fmt" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/prune.go b/pkg/cmd/container/prune.go index 3e6d33fba44..68614e0e42d 100644 --- a/pkg/cmd/container/prune.go +++ b/pkg/cmd/container/prune.go @@ -24,6 +24,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index d62130e0f83..78caa7e41cb 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -30,6 +30,7 @@ import ( "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" diff --git a/pkg/cmd/container/rename.go b/pkg/cmd/container/rename.go index cc9cf145fe8..7211678988e 100644 --- a/pkg/cmd/container/rename.go +++ b/pkg/cmd/container/rename.go @@ -22,6 +22,7 @@ import ( "runtime" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" diff --git a/pkg/cmd/container/restart.go b/pkg/cmd/container/restart.go index a67093c7122..2be386ea323 100644 --- a/pkg/cmd/container/restart.go +++ b/pkg/cmd/container/restart.go @@ -21,6 +21,7 @@ import ( "fmt" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/run_cgroup_freebsd.go b/pkg/cmd/container/run_cgroup_freebsd.go index b250500f6cb..994d800cdae 100644 --- a/pkg/cmd/container/run_cgroup_freebsd.go +++ b/pkg/cmd/container/run_cgroup_freebsd.go @@ -18,6 +18,7 @@ package container import ( "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/container/run_cgroup_linux.go b/pkg/cmd/container/run_cgroup_linux.go index be63938ec57..af43b12c1fd 100644 --- a/pkg/cmd/container/run_cgroup_linux.go +++ b/pkg/cmd/container/run_cgroup_linux.go @@ -29,6 +29,7 @@ import ( "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" diff --git a/pkg/cmd/container/run_cgroup_windows.go b/pkg/cmd/container/run_cgroup_windows.go index b250500f6cb..994d800cdae 100644 --- a/pkg/cmd/container/run_cgroup_windows.go +++ b/pkg/cmd/container/run_cgroup_windows.go @@ -18,6 +18,7 @@ package container import ( "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/container/run_freebsd.go b/pkg/cmd/container/run_freebsd.go index 962f74ad6fc..ddf743121e7 100644 --- a/pkg/cmd/container/run_freebsd.go +++ b/pkg/cmd/container/run_freebsd.go @@ -22,6 +22,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/container/run_gpus.go b/pkg/cmd/container/run_gpus.go index da8245299d4..e2261e641eb 100644 --- a/pkg/cmd/container/run_gpus.go +++ b/pkg/cmd/container/run_gpus.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/containerd/v2/contrib/nvidia" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) diff --git a/pkg/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index 9d5c2301524..1c7522010b2 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -28,6 +28,7 @@ import ( "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/bypass4netnsutil" "github.com/containerd/nerdctl/v2/pkg/containerutil" diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index cbcf42e9f87..b6d0c989bc9 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -41,6 +41,7 @@ import ( "github.com/containerd/continuity/fs" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/imgutil" diff --git a/pkg/cmd/container/run_restart.go b/pkg/cmd/container/run_restart.go index d7b97d09389..5932f2175d5 100644 --- a/pkg/cmd/container/run_restart.go +++ b/pkg/cmd/container/run_restart.go @@ -23,6 +23,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/runtime/restart" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) diff --git a/pkg/cmd/container/run_security_linux.go b/pkg/cmd/container/run_security_linux.go index 3681c6845a1..4b26d23f766 100644 --- a/pkg/cmd/container/run_security_linux.go +++ b/pkg/cmd/container/run_security_linux.go @@ -26,6 +26,7 @@ import ( "github.com/containerd/containerd/v2/pkg/cap" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/maputil" diff --git a/pkg/cmd/container/run_ulimit.go b/pkg/cmd/container/run_ulimit.go index 2398c713dc5..b19c31a35dc 100644 --- a/pkg/cmd/container/run_ulimit.go +++ b/pkg/cmd/container/run_ulimit.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) diff --git a/pkg/cmd/container/run_windows.go b/pkg/cmd/container/run_windows.go index 904bc6b71b0..ea8409d4708 100644 --- a/pkg/cmd/container/run_windows.go +++ b/pkg/cmd/container/run_windows.go @@ -28,6 +28,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/container/start.go b/pkg/cmd/container/start.go index a29f900c831..3d9de68cb29 100644 --- a/pkg/cmd/container/start.go +++ b/pkg/cmd/container/start.go @@ -21,6 +21,7 @@ import ( "fmt" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/stats.go b/pkg/cmd/container/stats.go index b36ae484eb2..b21c08fce61 100644 --- a/pkg/cmd/container/stats.go +++ b/pkg/cmd/container/stats.go @@ -32,6 +32,8 @@ import ( "github.com/containerd/containerd/v2/core/events" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/typeurl/v2" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/containerinspector" @@ -42,7 +44,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/statsutil" - "github.com/containerd/typeurl/v2" ) type stats struct { diff --git a/pkg/cmd/container/stats_linux.go b/pkg/cmd/container/stats_linux.go index 762dec200ac..76aa1c96ab3 100644 --- a/pkg/cmd/container/stats_linux.go +++ b/pkg/cmd/container/stats_linux.go @@ -23,12 +23,14 @@ import ( "strings" "time" + "github.com/vishvananda/netlink" + "github.com/vishvananda/netns" + v1 "github.com/containerd/cgroups/v3/cgroup1/stats" v2 "github.com/containerd/cgroups/v3/cgroup2/stats" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/statsutil" - "github.com/vishvananda/netlink" - "github.com/vishvananda/netns" ) //nolint:nakedret diff --git a/pkg/cmd/container/stop.go b/pkg/cmd/container/stop.go index a385cbd4bec..3000fd611b4 100644 --- a/pkg/cmd/container/stop.go +++ b/pkg/cmd/container/stop.go @@ -22,6 +22,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/top.go b/pkg/cmd/container/top.go index d73fa02dcdb..0e2f49adadc 100644 --- a/pkg/cmd/container/top.go +++ b/pkg/cmd/container/top.go @@ -33,6 +33,7 @@ import ( "strings" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) diff --git a/pkg/cmd/container/top_windows.go b/pkg/cmd/container/top_windows.go index eee445ae4b6..fcdb165b9b3 100644 --- a/pkg/cmd/container/top_windows.go +++ b/pkg/cmd/container/top_windows.go @@ -26,9 +26,10 @@ import ( "time" "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options" + "github.com/docker/go-units" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/typeurl/v2" - "github.com/docker/go-units" ) // containerTop was inspired from https://github.com/moby/moby/blob/master/daemon/top_windows.go diff --git a/pkg/cmd/container/unpause.go b/pkg/cmd/container/unpause.go index bd6ba750d8e..cc6f8a5781d 100644 --- a/pkg/cmd/container/unpause.go +++ b/pkg/cmd/container/unpause.go @@ -21,6 +21,7 @@ import ( "fmt" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" diff --git a/pkg/cmd/container/wait.go b/pkg/cmd/container/wait.go index 31bd2daaf79..1dbc81d6e44 100644 --- a/pkg/cmd/container/wait.go +++ b/pkg/cmd/container/wait.go @@ -23,6 +23,7 @@ import ( "io" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) diff --git a/pkg/cmd/image/convert.go b/pkg/cmd/image/convert.go index 5747b39a240..d628c43158a 100644 --- a/pkg/cmd/image/convert.go +++ b/pkg/cmd/image/convert.go @@ -35,17 +35,18 @@ import ( "github.com/containerd/containerd/v2/core/images/converter" "github.com/containerd/containerd/v2/core/images/converter/uncompress" "github.com/containerd/log" - "github.com/containerd/nerdctl/v2/pkg/api/types" - "github.com/containerd/nerdctl/v2/pkg/clientutil" - converterutil "github.com/containerd/nerdctl/v2/pkg/imgutil/converter" - "github.com/containerd/nerdctl/v2/pkg/platformutil" - "github.com/containerd/nerdctl/v2/pkg/referenceutil" nydusconvert "github.com/containerd/nydus-snapshotter/pkg/converter" "github.com/containerd/stargz-snapshotter/estargz" estargzconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz" estargzexternaltocconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz/externaltoc" zstdchunkedconvert "github.com/containerd/stargz-snapshotter/nativeconverter/zstdchunked" "github.com/containerd/stargz-snapshotter/recorder" + + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + converterutil "github.com/containerd/nerdctl/v2/pkg/imgutil/converter" + "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRawRef string, options types.ImageConvertOptions) error { diff --git a/pkg/cmd/image/crypt.go b/pkg/cmd/image/crypt.go index a4915c25bf2..105821eb22f 100644 --- a/pkg/cmd/image/crypt.go +++ b/pkg/cmd/image/crypt.go @@ -28,6 +28,7 @@ import ( "github.com/containerd/containerd/v2/core/images/converter" "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/imgcrypt/images/encryption/parsehelpers" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/referenceutil" diff --git a/pkg/cmd/image/inspect.go b/pkg/cmd/image/inspect.go index cd864fd2653..be8c1515080 100644 --- a/pkg/cmd/image/inspect.go +++ b/pkg/cmd/image/inspect.go @@ -23,16 +23,18 @@ import ( "strings" "time" + "github.com/distribution/reference" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerdutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/imageinspector" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/referenceutil" - "github.com/distribution/reference" ) func inspectIdentifier(ctx context.Context, client *containerd.Client, identifier string) ([]images.Image, string, string, error) { diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index bdf84ed6efe..a7e6f46c6a1 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -38,11 +38,12 @@ import ( "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/log" + "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerdutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/imgutil" - "github.com/containerd/platforms" ) // ListCommandHandler `List` and print images matching filters in `options`. diff --git a/pkg/cmd/image/load.go b/pkg/cmd/image/load.go index 78b46b0dd8c..996feda5d04 100644 --- a/pkg/cmd/image/load.go +++ b/pkg/cmd/image/load.go @@ -27,10 +27,11 @@ import ( "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/images/archive" "github.com/containerd/containerd/v2/pkg/archive/compression" + "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" - "github.com/containerd/platforms" ) type readCounter struct { diff --git a/pkg/cmd/image/prune.go b/pkg/cmd/image/prune.go index 13ec96ca8cd..b2888c8ea71 100644 --- a/pkg/cmd/image/prune.go +++ b/pkg/cmd/image/prune.go @@ -25,9 +25,10 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" + "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil" - "github.com/containerd/platforms" ) // Prune will remove all dangling images. If all is specified, will also remove all images not referenced by any container. diff --git a/pkg/cmd/image/pull.go b/pkg/cmd/image/pull.go index 7dd3c534748..c714c47418d 100644 --- a/pkg/cmd/image/pull.go +++ b/pkg/cmd/image/pull.go @@ -23,6 +23,7 @@ import ( "path/filepath" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/ipfs" diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index 965c6fa509e..266313a9e04 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -38,6 +38,10 @@ import ( dockerconfig "github.com/containerd/containerd/v2/core/remotes/docker/config" "github.com/containerd/containerd/v2/pkg/reference" "github.com/containerd/log" + "github.com/containerd/stargz-snapshotter/estargz" + "github.com/containerd/stargz-snapshotter/estargz/zstdchunked" + estargzconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/errutil" "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" @@ -47,9 +51,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/nerdctl/v2/pkg/signutil" "github.com/containerd/nerdctl/v2/pkg/snapshotterutil" - "github.com/containerd/stargz-snapshotter/estargz" - "github.com/containerd/stargz-snapshotter/estargz/zstdchunked" - estargzconvert "github.com/containerd/stargz-snapshotter/nativeconverter/estargz" ) // Push pushes an image specified by `rawRef`. diff --git a/pkg/cmd/image/remove.go b/pkg/cmd/image/remove.go index 53bd8b02a25..09d76b90e69 100644 --- a/pkg/cmd/image/remove.go +++ b/pkg/cmd/image/remove.go @@ -25,10 +25,11 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" + "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" - "github.com/containerd/platforms" ) // Remove removes a list of `images`. diff --git a/pkg/cmd/image/save.go b/pkg/cmd/image/save.go index 8d6a2601269..fc92e0b9eb9 100644 --- a/pkg/cmd/image/save.go +++ b/pkg/cmd/image/save.go @@ -22,6 +22,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images/archive" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/platformutil" diff --git a/pkg/cmd/image/tag.go b/pkg/cmd/image/tag.go index ae450408165..48929d3694e 100644 --- a/pkg/cmd/image/tag.go +++ b/pkg/cmd/image/tag.go @@ -22,6 +22,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/referenceutil" diff --git a/pkg/cmd/ipfs/registry_serve.go b/pkg/cmd/ipfs/registry_serve.go index 9ee048a9a94..09294032c1d 100644 --- a/pkg/cmd/ipfs/registry_serve.go +++ b/pkg/cmd/ipfs/registry_serve.go @@ -22,6 +22,7 @@ import ( "path/filepath" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/ipfs" ) diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index e2906b14ed7..3ca7c9e35c1 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -37,6 +37,7 @@ import ( "github.com/containerd/containerd/v2/core/remotes/docker/config" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/errutil" "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" diff --git a/pkg/cmd/namespace/create.go b/pkg/cmd/namespace/create.go index 91fef5fd094..f07b9f007e6 100644 --- a/pkg/cmd/namespace/create.go +++ b/pkg/cmd/namespace/create.go @@ -20,6 +20,7 @@ import ( "context" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/namespace/inspect.go b/pkg/cmd/namespace/inspect.go index 761891692b9..3a7a4932815 100644 --- a/pkg/cmd/namespace/inspect.go +++ b/pkg/cmd/namespace/inspect.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" diff --git a/pkg/cmd/namespace/remove.go b/pkg/cmd/namespace/remove.go index e4b1f9c24f5..81850be854e 100644 --- a/pkg/cmd/namespace/remove.go +++ b/pkg/cmd/namespace/remove.go @@ -23,6 +23,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/namespace/update.go b/pkg/cmd/namespace/update.go index 46694342af3..63d2d8a5971 100644 --- a/pkg/cmd/namespace/update.go +++ b/pkg/cmd/namespace/update.go @@ -20,6 +20,7 @@ import ( "context" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/cmd/network/create.go b/pkg/cmd/network/create.go index dd60901ea63..dc62875863e 100644 --- a/pkg/cmd/network/create.go +++ b/pkg/cmd/network/create.go @@ -21,6 +21,7 @@ import ( "io" "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/netutil" ) diff --git a/pkg/cmd/network/inspect.go b/pkg/cmd/network/inspect.go index 1d680642856..6389be63755 100644 --- a/pkg/cmd/network/inspect.go +++ b/pkg/cmd/network/inspect.go @@ -22,6 +22,7 @@ import ( "fmt" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/idutil/netwalker" diff --git a/pkg/cmd/network/prune.go b/pkg/cmd/network/prune.go index f5063463a9f..d88442160b1 100644 --- a/pkg/cmd/network/prune.go +++ b/pkg/cmd/network/prune.go @@ -22,6 +22,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/containerd/nerdctl/v2/pkg/strutil" diff --git a/pkg/cmd/network/remove.go b/pkg/cmd/network/remove.go index c50d1649528..66ad7ca1f33 100644 --- a/pkg/cmd/network/remove.go +++ b/pkg/cmd/network/remove.go @@ -21,6 +21,7 @@ import ( "fmt" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/netwalker" "github.com/containerd/nerdctl/v2/pkg/netutil" diff --git a/pkg/cmd/system/events.go b/pkg/cmd/system/events.go index 56e3d421afc..a544f071b57 100644 --- a/pkg/cmd/system/events.go +++ b/pkg/cmd/system/events.go @@ -30,9 +30,10 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/events" "github.com/containerd/log" + "github.com/containerd/typeurl/v2" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" - "github.com/containerd/typeurl/v2" ) // EventOut contains information about an event. diff --git a/pkg/cmd/system/info.go b/pkg/cmd/system/info.go index 6d43f063a4c..50d65c63dea 100644 --- a/pkg/cmd/system/info.go +++ b/pkg/cmd/system/info.go @@ -31,6 +31,7 @@ import ( "github.com/containerd/containerd/api/services/introspection/v1" containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/infoutil" diff --git a/pkg/cmd/system/prune.go b/pkg/cmd/system/prune.go index 71c4cfa85d6..19b48ef07c6 100644 --- a/pkg/cmd/system/prune.go +++ b/pkg/cmd/system/prune.go @@ -21,6 +21,7 @@ import ( "fmt" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/builder" "github.com/containerd/nerdctl/v2/pkg/cmd/container" diff --git a/pkg/cmd/volume/create.go b/pkg/cmd/volume/create.go index f8cdbbcd345..5aac0ce0486 100644 --- a/pkg/cmd/volume/create.go +++ b/pkg/cmd/volume/create.go @@ -19,11 +19,12 @@ package volume import ( "fmt" + "github.com/docker/docker/pkg/stringid" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/docker/docker/pkg/stringid" ) func Create(name string, options types.VolumeCreateOptions) (*native.Volume, error) { diff --git a/pkg/cmd/volume/inspect.go b/pkg/cmd/volume/inspect.go index 4a7ee1cd2e5..8369a6c9ea8 100644 --- a/pkg/cmd/volume/inspect.go +++ b/pkg/cmd/volume/inspect.go @@ -21,6 +21,7 @@ import ( "errors" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" ) diff --git a/pkg/cmd/volume/list.go b/pkg/cmd/volume/list.go index e005d886a6a..b934f0a9614 100644 --- a/pkg/cmd/volume/list.go +++ b/pkg/cmd/volume/list.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/containerd/v2/pkg/progress" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" diff --git a/pkg/cmd/volume/prune.go b/pkg/cmd/volume/prune.go index aa051d1cc55..f159b99757a 100644 --- a/pkg/cmd/volume/prune.go +++ b/pkg/cmd/volume/prune.go @@ -21,6 +21,7 @@ import ( "fmt" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/cmd/volume/rm.go b/pkg/cmd/volume/rm.go index d7327845cf7..a7864a801a0 100644 --- a/pkg/cmd/volume/rm.go +++ b/pkg/cmd/volume/rm.go @@ -25,6 +25,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/labels" diff --git a/pkg/composer/build.go b/pkg/composer/build.go index ff235e6f905..17b3fd0d8cd 100644 --- a/pkg/composer/build.go +++ b/pkg/composer/build.go @@ -22,7 +22,9 @@ import ( "os" "github.com/compose-spec/compose-go/v2/types" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" ) diff --git a/pkg/composer/composer.go b/pkg/composer/composer.go index 2adf7459433..6ef597fbfa9 100644 --- a/pkg/composer/composer.go +++ b/pkg/composer/composer.go @@ -25,9 +25,11 @@ import ( composecli "github.com/compose-spec/compose-go/v2/cli" compose "github.com/compose-spec/compose-go/v2/types" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) diff --git a/pkg/composer/container.go b/pkg/composer/container.go index 53525457a87..b1e101b7238 100644 --- a/pkg/composer/container.go +++ b/pkg/composer/container.go @@ -22,6 +22,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/composer/copy.go b/pkg/composer/copy.go index 9e90e91e034..a75d56bac33 100644 --- a/pkg/composer/copy.go +++ b/pkg/composer/copy.go @@ -22,10 +22,12 @@ import ( "fmt" "strings" + "github.com/docker/docker/pkg/system" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/labels" - "github.com/docker/docker/pkg/system" ) type CopyOptions struct { diff --git a/pkg/composer/create.go b/pkg/composer/create.go index 5e261d00f07..25d6872590b 100644 --- a/pkg/composer/create.go +++ b/pkg/composer/create.go @@ -23,10 +23,11 @@ import ( "path/filepath" "strings" + "github.com/compose-spec/compose-go/v2/types" "golang.org/x/sync/errgroup" - "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/composer/down.go b/pkg/composer/down.go index b20f884b6f5..4ebd0d1d09b 100644 --- a/pkg/composer/down.go +++ b/pkg/composer/down.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) diff --git a/pkg/composer/exec.go b/pkg/composer/exec.go index df1ae533714..04c6e077614 100644 --- a/pkg/composer/exec.go +++ b/pkg/composer/exec.go @@ -26,6 +26,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/composer/logs.go b/pkg/composer/logs.go index 91889692e12..b14722270ec 100644 --- a/pkg/composer/logs.go +++ b/pkg/composer/logs.go @@ -25,8 +25,10 @@ import ( "strings" "github.com/compose-spec/compose-go/v2/types" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/pipetagger" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" diff --git a/pkg/composer/orphans.go b/pkg/composer/orphans.go index ed5028c3da0..eacac677fc3 100644 --- a/pkg/composer/orphans.go +++ b/pkg/composer/orphans.go @@ -21,6 +21,7 @@ import ( "fmt" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/composer/pause.go b/pkg/composer/pause.go index b89bfec4d67..d0e7bc5aa77 100644 --- a/pkg/composer/pause.go +++ b/pkg/composer/pause.go @@ -25,6 +25,7 @@ import ( "golang.org/x/sync/errgroup" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/composer/pull.go b/pkg/composer/pull.go index 1ada8cadddf..758d342f49e 100644 --- a/pkg/composer/pull.go +++ b/pkg/composer/pull.go @@ -22,7 +22,9 @@ import ( "os" "github.com/compose-spec/compose-go/v2/types" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" ) diff --git a/pkg/composer/push.go b/pkg/composer/push.go index b9bc9a04336..5f384601863 100644 --- a/pkg/composer/push.go +++ b/pkg/composer/push.go @@ -22,7 +22,9 @@ import ( "os" "github.com/compose-spec/compose-go/v2/types" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" ) diff --git a/pkg/composer/restart.go b/pkg/composer/restart.go index d27b981d5dd..e0ab0285b9a 100644 --- a/pkg/composer/restart.go +++ b/pkg/composer/restart.go @@ -22,8 +22,10 @@ import ( "sync" "github.com/compose-spec/compose-go/v2/types" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/composer/rm.go b/pkg/composer/rm.go index 590028c4d0e..c58cb024475 100644 --- a/pkg/composer/rm.go +++ b/pkg/composer/rm.go @@ -23,6 +23,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/labels" diff --git a/pkg/composer/run.go b/pkg/composer/run.go index b7d6e88bd15..87dbe5be9ec 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -22,11 +22,12 @@ import ( "fmt" "sync" - "golang.org/x/sync/errgroup" - "github.com/compose-spec/compose-go/v2/format" "github.com/compose-spec/compose-go/v2/types" + "golang.org/x/sync/errgroup" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/idgen" ) diff --git a/pkg/composer/serviceparser/build.go b/pkg/composer/serviceparser/build.go index ec95fc66591..eea441cb77a 100644 --- a/pkg/composer/serviceparser/build.go +++ b/pkg/composer/serviceparser/build.go @@ -23,12 +23,13 @@ import ( "strings" "github.com/compose-spec/compose-go/v2/types" + securejoin "github.com/cyphar/filepath-securejoin" + "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/errdefs" "github.com/containerd/log" - "github.com/containerd/nerdctl/v2/pkg/reflectutil" - securejoin "github.com/cyphar/filepath-securejoin" + "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) func parseBuildConfig(c *types.BuildConfig, project *types.Project, imageName string) (*Build, error) { diff --git a/pkg/composer/serviceparser/build_test.go b/pkg/composer/serviceparser/build_test.go index 0c63343bc2b..2ffa8962515 100644 --- a/pkg/composer/serviceparser/build_test.go +++ b/pkg/composer/serviceparser/build_test.go @@ -19,8 +19,9 @@ package serviceparser import ( "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func lastOf(ss []string) string { diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index 7b8ec441be8..86409f1bfab 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -29,9 +29,11 @@ import ( "time" "github.com/compose-spec/compose-go/v2/types" + "github.com/containerd/containerd/v2/contrib/nvidia" "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) diff --git a/pkg/composer/serviceparser/serviceparser_test.go b/pkg/composer/serviceparser/serviceparser_test.go index 0e178b791d1..65cf517cb67 100644 --- a/pkg/composer/serviceparser/serviceparser_test.go +++ b/pkg/composer/serviceparser/serviceparser_test.go @@ -24,9 +24,10 @@ import ( "testing" "github.com/compose-spec/compose-go/v2/types" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/testutil" - "gotest.tools/v3/assert" ) func TestServicePortConfigToFlagP(t *testing.T) { diff --git a/pkg/composer/stop.go b/pkg/composer/stop.go index eac5266c664..7f514cedaff 100644 --- a/pkg/composer/stop.go +++ b/pkg/composer/stop.go @@ -23,6 +23,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/strutil" diff --git a/pkg/composer/up.go b/pkg/composer/up.go index fe6bd6a5081..15545a977cf 100644 --- a/pkg/composer/up.go +++ b/pkg/composer/up.go @@ -22,7 +22,9 @@ import ( "os" "github.com/compose-spec/compose-go/v2/types" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) diff --git a/pkg/composer/up_network.go b/pkg/composer/up_network.go index 25f86593b8d..a68b63c0f71 100644 --- a/pkg/composer/up_network.go +++ b/pkg/composer/up_network.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) diff --git a/pkg/composer/up_service.go b/pkg/composer/up_service.go index 70dd9e5b4d2..f3f9b26136d 100644 --- a/pkg/composer/up_service.go +++ b/pkg/composer/up_service.go @@ -28,6 +28,7 @@ import ( "golang.org/x/sync/errgroup" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/composer/up_volume.go b/pkg/composer/up_volume.go index 190001956cf..929d96f40cb 100644 --- a/pkg/composer/up_volume.go +++ b/pkg/composer/up_volume.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) diff --git a/pkg/config/config.go b/pkg/config/config.go index eaffe583260..7aacfcd0764 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -19,6 +19,7 @@ package config import ( "github.com/containerd/containerd/v2/defaults" "github.com/containerd/containerd/v2/pkg/namespaces" + ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" ) diff --git a/pkg/consoleutil/detach.go b/pkg/consoleutil/detach.go index 61cfa9e5631..daee28ee8f9 100644 --- a/pkg/consoleutil/detach.go +++ b/pkg/consoleutil/detach.go @@ -21,8 +21,9 @@ import ( "fmt" "io" - "github.com/containerd/log" "github.com/moby/term" + + "github.com/containerd/log" ) const DefaultDetachKeys = "ctrl-p,ctrl-q" diff --git a/pkg/containerinspector/containerinspector.go b/pkg/containerinspector/containerinspector.go index 2e3fe0c86d1..a3a77e1e60d 100644 --- a/pkg/containerinspector/containerinspector.go +++ b/pkg/containerinspector/containerinspector.go @@ -22,8 +22,9 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" "github.com/containerd/log" - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/typeurl/v2" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) func Inspect(ctx context.Context, container containerd.Container) (*native.Container, error) { diff --git a/pkg/containerinspector/containerinspector_linux.go b/pkg/containerinspector/containerinspector_linux.go index 2bf39fd5d56..729f878b764 100644 --- a/pkg/containerinspector/containerinspector_linux.go +++ b/pkg/containerinspector/containerinspector_linux.go @@ -22,9 +22,9 @@ import ( "net" "strings" - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - "github.com/containernetworking/plugins/pkg/ns" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) func InspectNetNS(ctx context.Context, pid int) (*native.NetNS, error) { diff --git a/pkg/containerutil/config.go b/pkg/containerutil/config.go index dc0e28f51aa..4fb5ce45546 100644 --- a/pkg/containerutil/config.go +++ b/pkg/containerutil/config.go @@ -28,6 +28,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index ada48d2b0d4..b19169eb692 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -32,6 +32,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" diff --git a/pkg/containerutil/container_network_manager_linux.go b/pkg/containerutil/container_network_manager_linux.go index 7411525c11b..11004f81c85 100644 --- a/pkg/containerutil/container_network_manager_linux.go +++ b/pkg/containerutil/container_network_manager_linux.go @@ -25,6 +25,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/dnsutil" diff --git a/pkg/containerutil/container_network_manager_other.go b/pkg/containerutil/container_network_manager_other.go index 7f9b83b225f..feb97e20f74 100644 --- a/pkg/containerutil/container_network_manager_other.go +++ b/pkg/containerutil/container_network_manager_other.go @@ -25,6 +25,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 7f661e36196..310955630e1 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -38,6 +38,7 @@ import ( "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/consoleutil" "github.com/containerd/nerdctl/v2/pkg/errutil" "github.com/containerd/nerdctl/v2/pkg/formatter" diff --git a/pkg/containerutil/cp_linux.go b/pkg/containerutil/cp_linux.go index fd7f6e82b98..2036b677630 100644 --- a/pkg/containerutil/cp_linux.go +++ b/pkg/containerutil/cp_linux.go @@ -28,13 +28,15 @@ import ( "strconv" "strings" + securejoin "github.com/cyphar/filepath-securejoin" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/tarutil" - securejoin "github.com/cyphar/filepath-securejoin" ) // CopyFiles implements `nerdctl cp`. diff --git a/pkg/defaults/cgroup_linux.go b/pkg/defaults/cgroup_linux.go index 2a3963c52ee..41e64cece16 100644 --- a/pkg/defaults/cgroup_linux.go +++ b/pkg/defaults/cgroup_linux.go @@ -20,6 +20,7 @@ import ( "os" "github.com/containerd/cgroups/v3" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) diff --git a/pkg/defaults/defaults_linux.go b/pkg/defaults/defaults_linux.go index 41e18118e5c..6de6f294333 100644 --- a/pkg/defaults/defaults_linux.go +++ b/pkg/defaults/defaults_linux.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/containerd/v2/plugins" gocni "github.com/containerd/go-cni" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) diff --git a/pkg/dnsutil/hostsstore/hostsstore.go b/pkg/dnsutil/hostsstore/hostsstore.go index 7783da1da27..cb4458db94a 100644 --- a/pkg/dnsutil/hostsstore/hostsstore.go +++ b/pkg/dnsutil/hostsstore/hostsstore.go @@ -24,9 +24,11 @@ import ( "os" "path/filepath" + types100 "github.com/containernetworking/cni/pkg/types/100" + "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/lockutil" - types100 "github.com/containernetworking/cni/pkg/types/100" ) const ( diff --git a/pkg/dnsutil/hostsstore/updater.go b/pkg/dnsutil/hostsstore/updater.go index 5c68e52e89d..2088c6cbd3c 100644 --- a/pkg/dnsutil/hostsstore/updater.go +++ b/pkg/dnsutil/hostsstore/updater.go @@ -26,6 +26,7 @@ import ( "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/netutil" ) diff --git a/pkg/formatter/formatter.go b/pkg/formatter/formatter.go index de313688792..1c6acdcfced 100644 --- a/pkg/formatter/formatter.go +++ b/pkg/formatter/formatter.go @@ -34,6 +34,7 @@ import ( "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/portutil" ) diff --git a/pkg/idutil/containerwalker/containerwalker.go b/pkg/idutil/containerwalker/containerwalker.go index b889682569a..83e9926046f 100644 --- a/pkg/idutil/containerwalker/containerwalker.go +++ b/pkg/idutil/containerwalker/containerwalker.go @@ -23,6 +23,7 @@ import ( "strings" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/idutil/imagewalker/imagewalker.go b/pkg/idutil/imagewalker/imagewalker.go index 0ab540fec5a..f6effd0fa0a 100644 --- a/pkg/idutil/imagewalker/imagewalker.go +++ b/pkg/idutil/imagewalker/imagewalker.go @@ -26,6 +26,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) diff --git a/pkg/imageinspector/imageinspector.go b/pkg/imageinspector/imageinspector.go index b3bec918692..ce1f0003f05 100644 --- a/pkg/imageinspector/imageinspector.go +++ b/pkg/imageinspector/imageinspector.go @@ -23,6 +23,7 @@ import ( "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index 29d80c1b2ac..44e582052cb 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -42,9 +42,10 @@ import ( "github.com/containerd/containerd/v2/pkg/rootfs" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/platforms" + imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" - "github.com/containerd/platforms" ) type Changes struct { diff --git a/pkg/imgutil/converter/zstd.go b/pkg/imgutil/converter/zstd.go index e6fdb043366..bb177a63442 100644 --- a/pkg/imgutil/converter/zstd.go +++ b/pkg/imgutil/converter/zstd.go @@ -30,6 +30,7 @@ import ( "github.com/containerd/containerd/v2/core/images/converter/uncompress" "github.com/containerd/containerd/v2/pkg/archive/compression" "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go index af59898e93f..935c6035da2 100644 --- a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go +++ b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go @@ -23,14 +23,15 @@ import ( "fmt" "os" + dockercliconfig "github.com/docker/cli/cli/config" + "github.com/docker/cli/cli/config/credentials" + dockercliconfigtypes "github.com/docker/cli/cli/config/types" + "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/containerd/v2/core/remotes/docker" dockerconfig "github.com/containerd/containerd/v2/core/remotes/docker/config" "github.com/containerd/errdefs" "github.com/containerd/log" - dockercliconfig "github.com/docker/cli/cli/config" - "github.com/docker/cli/cli/config/credentials" - dockercliconfigtypes "github.com/docker/cli/cli/config/types" ) var PushTracker = docker.NewInMemoryTracker() diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index f34cbf48234..6942b84353c 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -23,11 +23,13 @@ import ( "strings" "time" + distributionref "github.com/distribution/reference" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" - distributionref "github.com/distribution/reference" ) // Filter types supported to filter images. diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 05eae9c8f9e..5406e83858d 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -37,12 +37,13 @@ import ( "github.com/containerd/imgcrypt" "github.com/containerd/imgcrypt/images/encryption" "github.com/containerd/log" + "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/errutil" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" - "github.com/containerd/platforms" ) // EnsuredImage contains the image existed in containerd and its metadata. diff --git a/pkg/imgutil/pull/pull.go b/pkg/imgutil/pull/pull.go index 21429cb1acf..e677e9cd732 100644 --- a/pkg/imgutil/pull/pull.go +++ b/pkg/imgutil/pull/pull.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/containerd/v2/core/images" "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/imgutil/jobs" "github.com/containerd/nerdctl/v2/pkg/platformutil" ) diff --git a/pkg/imgutil/push/push.go b/pkg/imgutil/push/push.go index 5fd2447dcd5..94c6acca71c 100644 --- a/pkg/imgutil/push/push.go +++ b/pkg/imgutil/push/push.go @@ -34,8 +34,9 @@ import ( "github.com/containerd/containerd/v2/core/remotes/docker" "github.com/containerd/containerd/v2/pkg/progress" "github.com/containerd/log" - "github.com/containerd/nerdctl/v2/pkg/imgutil/jobs" "github.com/containerd/platforms" + + "github.com/containerd/nerdctl/v2/pkg/imgutil/jobs" ) // Push pushes an image to a remote registry. diff --git a/pkg/imgutil/snapshotter.go b/pkg/imgutil/snapshotter.go index c56864413f0..15f63e7c00e 100644 --- a/pkg/imgutil/snapshotter.go +++ b/pkg/imgutil/snapshotter.go @@ -23,10 +23,11 @@ import ( "github.com/containerd/containerd/v2/core/images" ctdsnapshotters "github.com/containerd/containerd/v2/pkg/snapshotters" "github.com/containerd/log" + "github.com/containerd/stargz-snapshotter/fs/source" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" "github.com/containerd/nerdctl/v2/pkg/snapshotterutil" - "github.com/containerd/stargz-snapshotter/fs/source" ) const ( diff --git a/pkg/imgutil/snapshotter_test.go b/pkg/imgutil/snapshotter_test.go index 42d3f68433c..6acc6951ed3 100644 --- a/pkg/imgutil/snapshotter_test.go +++ b/pkg/imgutil/snapshotter_test.go @@ -27,6 +27,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" ctdsnapshotters "github.com/containerd/containerd/v2/pkg/snapshotters" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" ) diff --git a/pkg/infoutil/infoutil.go b/pkg/infoutil/infoutil.go index 1f02fa4b311..36a65a6f96e 100644 --- a/pkg/infoutil/infoutil.go +++ b/pkg/infoutil/infoutil.go @@ -26,10 +26,12 @@ import ( "time" "github.com/Masterminds/semver/v3" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/introspection" ptypes "github.com/containerd/containerd/v2/pkg/protobuf/types" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" diff --git a/pkg/infoutil/infoutil_linux.go b/pkg/infoutil/infoutil_linux.go index c9a90c5b162..93d22ee941c 100644 --- a/pkg/infoutil/infoutil_linux.go +++ b/pkg/infoutil/infoutil_linux.go @@ -20,13 +20,15 @@ import ( "fmt" "strings" + "github.com/docker/docker/pkg/meminfo" + "github.com/containerd/cgroups/v3" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/sysinfo" - "github.com/docker/docker/pkg/meminfo" ) const UnameO = "GNU/Linux" diff --git a/pkg/infoutil/infoutil_test.go b/pkg/infoutil/infoutil_test.go index ebf6d367cf3..33cbe6cc0b4 100644 --- a/pkg/infoutil/infoutil_test.go +++ b/pkg/infoutil/infoutil_test.go @@ -19,8 +19,9 @@ package infoutil import ( "testing" - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" ) func TestParseBuildctlVersion(t *testing.T) { diff --git a/pkg/infoutil/infoutil_windows.go b/pkg/infoutil/infoutil_windows.go index 11a013bfd04..a8075078605 100644 --- a/pkg/infoutil/infoutil_windows.go +++ b/pkg/infoutil/infoutil_windows.go @@ -26,6 +26,7 @@ import ( "golang.org/x/sys/windows/registry" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/sysinfo" ) diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index 56c9f1e071b..16c1a91a282 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -42,6 +42,7 @@ import ( "github.com/containerd/containerd/v2/core/runtime/restart" "github.com/containerd/go-cni" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/labels" diff --git a/pkg/inspecttypes/dockercompat/dockercompat_test.go b/pkg/inspecttypes/dockercompat/dockercompat_test.go index bacbc013db8..efca61c087e 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat_test.go +++ b/pkg/inspecttypes/dockercompat/dockercompat_test.go @@ -27,6 +27,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) diff --git a/pkg/ipcutil/ipcutil.go b/pkg/ipcutil/ipcutil.go index 94df89cd255..7fd3240f15c 100644 --- a/pkg/ipcutil/ipcutil.go +++ b/pkg/ipcutil/ipcutil.go @@ -32,6 +32,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/labels" ) diff --git a/pkg/ipfs/image.go b/pkg/ipfs/image.go index ace90f21820..ca944e279c3 100644 --- a/pkg/ipfs/image.go +++ b/pkg/ipfs/image.go @@ -30,13 +30,14 @@ import ( "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/stargz-snapshotter/ipfs" + ipfsclient "github.com/containerd/stargz-snapshotter/ipfs/client" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/referenceutil" - "github.com/containerd/stargz-snapshotter/ipfs" - ipfsclient "github.com/containerd/stargz-snapshotter/ipfs/client" ) const ipfsPathEnv = "IPFS_PATH" diff --git a/pkg/logging/cri_logger.go b/pkg/logging/cri_logger.go index eada94c6add..cf582d3c887 100644 --- a/pkg/logging/cri_logger.go +++ b/pkg/logging/cri_logger.go @@ -34,9 +34,11 @@ import ( "path/filepath" "time" + "github.com/fsnotify/fsnotify" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/logging/tail" - "github.com/fsnotify/fsnotify" ) // LogStreamType is the type of the stream in CRI container log. diff --git a/pkg/logging/fluentd_logger.go b/pkg/logging/fluentd_logger.go index 6267b058910..0f9fc762053 100644 --- a/pkg/logging/fluentd_logger.go +++ b/pkg/logging/fluentd_logger.go @@ -26,10 +26,12 @@ import ( "sync" "time" + "github.com/fluent/fluent-logger-golang/fluent" + "github.com/containerd/containerd/v2/core/runtime/v2/logging" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/fluent/fluent-logger-golang/fluent" ) type FluentdLogger struct { diff --git a/pkg/logging/journald_logger.go b/pkg/logging/journald_logger.go index 83fa7c6aa64..e2242af73c3 100644 --- a/pkg/logging/journald_logger.go +++ b/pkg/logging/journald_logger.go @@ -28,12 +28,14 @@ import ( "text/template" "time" - "github.com/containerd/containerd/v2/core/runtime/v2/logging" - "github.com/containerd/log" - "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/coreos/go-systemd/v22/journal" "github.com/docker/cli/templates" timetypes "github.com/docker/docker/api/types/time" + + "github.com/containerd/containerd/v2/core/runtime/v2/logging" + "github.com/containerd/log" + + "github.com/containerd/nerdctl/v2/pkg/strutil" ) var JournalDriverLogOpts = []string{ diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index 8f3141657d0..5c38bdd1492 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -26,15 +26,17 @@ import ( "strconv" "time" + "github.com/docker/go-units" + "github.com/fahedouch/go-logrotate" + "github.com/fsnotify/fsnotify" + "github.com/containerd/containerd/v2/core/runtime/v2/logging" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/logging/jsonfile" "github.com/containerd/nerdctl/v2/pkg/logging/tail" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/docker/go-units" - "github.com/fahedouch/go-logrotate" - "github.com/fsnotify/fsnotify" ) var JSONDriverLogOpts = []string{ diff --git a/pkg/logging/jsonfile/jsonfile.go b/pkg/logging/jsonfile/jsonfile.go index eebcff7cd96..2e47b836819 100644 --- a/pkg/logging/jsonfile/jsonfile.go +++ b/pkg/logging/jsonfile/jsonfile.go @@ -26,8 +26,9 @@ import ( "sync" "time" - "github.com/containerd/log" timetypes "github.com/docker/docker/api/types/time" + + "github.com/containerd/log" ) // Entry is compatible with Docker "json-file" logs diff --git a/pkg/logging/log_viewer.go b/pkg/logging/log_viewer.go index 891086bc47c..b2741273450 100644 --- a/pkg/logging/log_viewer.go +++ b/pkg/logging/log_viewer.go @@ -24,6 +24,7 @@ import ( "path/filepath" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/labels/k8slabels" ) diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index b704c874a8f..1baa4a97499 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -29,11 +29,12 @@ import ( "sync" "time" + "github.com/fsnotify/fsnotify" + "github.com/muesli/cancelreader" + "github.com/containerd/containerd/v2/core/runtime/v2/logging" "github.com/containerd/errdefs" "github.com/containerd/log" - "github.com/fsnotify/fsnotify" - "github.com/muesli/cancelreader" ) const ( diff --git a/pkg/logging/syslog_logger.go b/pkg/logging/syslog_logger.go index 63805693279..154478cad2a 100644 --- a/pkg/logging/syslog_logger.go +++ b/pkg/logging/syslog_logger.go @@ -27,11 +27,12 @@ import ( "strings" "sync" - "github.com/containerd/log" "github.com/docker/go-connections/tlsconfig" syslog "github.com/yuchanns/srslog" "github.com/containerd/containerd/v2/core/runtime/v2/logging" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/strutil" ) diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index fa0f80bedd5..56b5fecdad3 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -29,6 +29,7 @@ import ( "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" "github.com/containerd/nerdctl/v2/pkg/strutil" diff --git a/pkg/mountutil/mountutil_freebsd.go b/pkg/mountutil/mountutil_freebsd.go index 5d32299a2ca..58b32075b82 100644 --- a/pkg/mountutil/mountutil_freebsd.go +++ b/pkg/mountutil/mountutil_freebsd.go @@ -23,6 +23,7 @@ import ( "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) diff --git a/pkg/mountutil/mountutil_linux.go b/pkg/mountutil/mountutil_linux.go index dbc605aade4..a6a79d8e963 100644 --- a/pkg/mountutil/mountutil_linux.go +++ b/pkg/mountutil/mountutil_linux.go @@ -34,6 +34,7 @@ import ( "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) diff --git a/pkg/mountutil/mountutil_linux_test.go b/pkg/mountutil/mountutil_linux_test.go index 983108019b9..faa10511e71 100644 --- a/pkg/mountutil/mountutil_linux_test.go +++ b/pkg/mountutil/mountutil_linux_test.go @@ -28,6 +28,7 @@ import ( "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" mocks "github.com/containerd/nerdctl/v2/pkg/mountutil/mountutilmock" ) diff --git a/pkg/mountutil/mountutil_windows.go b/pkg/mountutil/mountutil_windows.go index e6782cb3405..e81c072f39d 100644 --- a/pkg/mountutil/mountutil_windows.go +++ b/pkg/mountutil/mountutil_windows.go @@ -32,6 +32,7 @@ import ( "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) diff --git a/pkg/mountutil/mountutilmock/volumestore.mock.go b/pkg/mountutil/mountutilmock/volumestore.mock.go index 695742f85b7..f4a57f26d7b 100644 --- a/pkg/mountutil/mountutilmock/volumestore.mock.go +++ b/pkg/mountutil/mountutilmock/volumestore.mock.go @@ -19,8 +19,9 @@ package mountutilmock import ( "reflect" - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "go.uber.org/mock/gomock" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) // MockVolumeStore is a mock of VolumeStore interface diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index c7bfc1ccbed..06b440b49b6 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -26,6 +26,7 @@ import ( "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/lockutil" "github.com/containerd/nerdctl/v2/pkg/strutil" diff --git a/pkg/namestore/namestore.go b/pkg/namestore/namestore.go index 0527b0efb68..e2a7b8c7032 100644 --- a/pkg/namestore/namestore.go +++ b/pkg/namestore/namestore.go @@ -23,6 +23,7 @@ import ( "strings" "github.com/containerd/containerd/v2/pkg/identifiers" + "github.com/containerd/nerdctl/v2/pkg/lockutil" ) diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 49341644441..bdaab110f28 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -30,17 +30,19 @@ import ( "strconv" "strings" + "github.com/containernetworking/cni/libcni" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/lockutil" "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" subnetutil "github.com/containerd/nerdctl/v2/pkg/netutil/subnet" "github.com/containerd/nerdctl/v2/pkg/strutil" - "github.com/containernetworking/cni/libcni" ) type CNIEnv struct { diff --git a/pkg/netutil/netutil_test.go b/pkg/netutil/netutil_test.go index c3f692c397f..30c4c4084ac 100644 --- a/pkg/netutil/netutil_test.go +++ b/pkg/netutil/netutil_test.go @@ -26,11 +26,11 @@ import ( "testing" "text/template" + "gotest.tools/v3/assert" + ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/testutil" - - "gotest.tools/v3/assert" ) const preExistingNetworkConfigTemplate = ` diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index 7e803981843..9571ab28a7e 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -29,13 +29,15 @@ import ( "strings" "github.com/Masterminds/semver/v3" + "github.com/go-viper/mapstructure/v2" + "github.com/vishvananda/netlink" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/systemutil" - "github.com/go-viper/mapstructure/v2" - "github.com/vishvananda/netlink" ) const ( diff --git a/pkg/nsutil/nsutil_test.go b/pkg/nsutil/nsutil_test.go index 7b6f19a8933..31d2fdffdc1 100644 --- a/pkg/nsutil/nsutil_test.go +++ b/pkg/nsutil/nsutil_test.go @@ -19,8 +19,9 @@ package nsutil_test import ( "testing" - "github.com/containerd/nerdctl/v2/pkg/nsutil" "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/nsutil" ) func TestValidateNamespaceName(t *testing.T) { diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 6df9fbc42d9..f59ced29ec2 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -35,6 +35,7 @@ import ( gocni "github.com/containerd/go-cni" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/bypass4netnsutil" "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" "github.com/containerd/nerdctl/v2/pkg/labels" diff --git a/pkg/ocihook/ocihook_linux.go b/pkg/ocihook/ocihook_linux.go index 831c7dba695..da961d75435 100644 --- a/pkg/ocihook/ocihook_linux.go +++ b/pkg/ocihook/ocihook_linux.go @@ -19,6 +19,7 @@ package ocihook import ( "github.com/containerd/containerd/v2/contrib/apparmor" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/apparmorutil" "github.com/containerd/nerdctl/v2/pkg/defaults" ) diff --git a/pkg/ocihook/rootless_linux.go b/pkg/ocihook/rootless_linux.go index 9764d5f123a..b319d4f0647 100644 --- a/pkg/ocihook/rootless_linux.go +++ b/pkg/ocihook/rootless_linux.go @@ -19,9 +19,11 @@ package ocihook import ( "context" + rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" + gocni "github.com/containerd/go-cni" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" ) func exposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []gocni.PortMapping) error { diff --git a/pkg/ocihook/rootless_other.go b/pkg/ocihook/rootless_other.go index e4e092df1e2..4109aed8a03 100644 --- a/pkg/ocihook/rootless_other.go +++ b/pkg/ocihook/rootless_other.go @@ -22,8 +22,9 @@ import ( "context" "fmt" - gocni "github.com/containerd/go-cni" rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" + + gocni "github.com/containerd/go-cni" ) func exposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []gocni.PortMapping) error { diff --git a/pkg/platformutil/platformutil.go b/pkg/platformutil/platformutil.go index b8594964804..ac076d0b980 100644 --- a/pkg/platformutil/platformutil.go +++ b/pkg/platformutil/platformutil.go @@ -21,8 +21,9 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/platforms" + + "github.com/containerd/nerdctl/v2/pkg/strutil" ) // NewMatchComparerFromOCISpecPlatformSlice returns MatchComparer. diff --git a/pkg/portutil/portutil.go b/pkg/portutil/portutil.go index ad2848c4e47..a901e2051f5 100644 --- a/pkg/portutil/portutil.go +++ b/pkg/portutil/portutil.go @@ -22,11 +22,13 @@ import ( "net" "strings" + "github.com/docker/go-connections/nat" + gocni "github.com/containerd/go-cni" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/docker/go-connections/nat" ) // return respectively ip, hostPort, containerPort diff --git a/pkg/portutil/portutil_test.go b/pkg/portutil/portutil_test.go index e3ec270c2b5..d4c48c05a64 100644 --- a/pkg/portutil/portutil_test.go +++ b/pkg/portutil/portutil_test.go @@ -23,6 +23,7 @@ import ( "testing" gocni "github.com/containerd/go-cni" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) diff --git a/pkg/rootlessutil/port_linux.go b/pkg/rootlessutil/port_linux.go index 968d08245ae..d885e1263e6 100644 --- a/pkg/rootlessutil/port_linux.go +++ b/pkg/rootlessutil/port_linux.go @@ -20,10 +20,11 @@ import ( "context" "net" - "github.com/containerd/errdefs" - gocni "github.com/containerd/go-cni" "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" "github.com/rootless-containers/rootlesskit/v2/pkg/port" + + "github.com/containerd/errdefs" + gocni "github.com/containerd/go-cni" ) func NewRootlessCNIPortManager(client client.Client) (*RootlessCNIPortManager, error) { diff --git a/pkg/signutil/cosignutil.go b/pkg/signutil/cosignutil.go index 8a3a3b26417..766ec9824e2 100644 --- a/pkg/signutil/cosignutil.go +++ b/pkg/signutil/cosignutil.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/imgutil" ) diff --git a/pkg/signutil/notationutil.go b/pkg/signutil/notationutil.go index 297756ae470..0e5a69a0b2b 100644 --- a/pkg/signutil/notationutil.go +++ b/pkg/signutil/notationutil.go @@ -24,6 +24,7 @@ import ( "strings" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/imgutil" ) diff --git a/pkg/signutil/signutil.go b/pkg/signutil/signutil.go index 6ddef610b6c..de370e0d369 100644 --- a/pkg/signutil/signutil.go +++ b/pkg/signutil/signutil.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/snapshotterutil/sociutil.go b/pkg/snapshotterutil/sociutil.go index 54ceb9e7985..a2148de027c 100644 --- a/pkg/snapshotterutil/sociutil.go +++ b/pkg/snapshotterutil/sociutil.go @@ -24,6 +24,7 @@ import ( "strings" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" ) diff --git a/pkg/statsutil/stats_linux.go b/pkg/statsutil/stats_linux.go index 147547de931..3d88685daf9 100644 --- a/pkg/statsutil/stats_linux.go +++ b/pkg/statsutil/stats_linux.go @@ -19,9 +19,10 @@ package statsutil import ( "time" + "github.com/vishvananda/netlink" + v1 "github.com/containerd/cgroups/v3/cgroup1/stats" v2 "github.com/containerd/cgroups/v3/cgroup2/stats" - "github.com/vishvananda/netlink" ) func SetCgroupStatsFields(previousStats *ContainerStats, data *v1.Metrics, links []netlink.Link) (StatsEntry, error) { diff --git a/pkg/sysinfo/cgroup2_linux.go b/pkg/sysinfo/cgroup2_linux.go index 1984685e139..d8dbe27eec0 100644 --- a/pkg/sysinfo/cgroup2_linux.go +++ b/pkg/sysinfo/cgroup2_linux.go @@ -29,10 +29,11 @@ import ( "path" "strings" + "github.com/moby/sys/userns" + "github.com/containerd/cgroups/v3" cgroupsV2 "github.com/containerd/cgroups/v3/cgroup2" "github.com/containerd/log" - "github.com/moby/sys/userns" ) func newV2(options ...Opt) *SysInfo { diff --git a/pkg/sysinfo/sysinfo_linux.go b/pkg/sysinfo/sysinfo_linux.go index 1851d3a6225..f8b50440878 100644 --- a/pkg/sysinfo/sysinfo_linux.go +++ b/pkg/sysinfo/sysinfo_linux.go @@ -31,11 +31,12 @@ import ( "strings" "sync" + "github.com/moby/sys/mountinfo" + "github.com/containerd/cgroups/v3" "github.com/containerd/cgroups/v3/cgroup1" "github.com/containerd/containerd/v2/pkg/seccomp" "github.com/containerd/log" - "github.com/moby/sys/mountinfo" ) var ( diff --git a/pkg/taskutil/taskutil.go b/pkg/taskutil/taskutil.go index 1777e292238..fe6cd15fd83 100644 --- a/pkg/taskutil/taskutil.go +++ b/pkg/taskutil/taskutil.go @@ -35,6 +35,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/cioutil" "github.com/containerd/nerdctl/v2/pkg/consoleutil" "github.com/containerd/nerdctl/v2/pkg/infoutil" diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index f42b4861e8e..296e6859866 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -36,6 +36,7 @@ import ( "gotest.tools/v3/icmd" "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/infoutil" From 77b0a291c211d8a0191c9f84acc136d8bde7573e Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 11 Aug 2024 20:45:35 -0700 Subject: [PATCH 0641/1066] Go imports tooling Signed-off-by: apostasie --- .github/workflows/test.yml | 4 ++++ Makefile | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index db353390d13..d6a423614b6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,6 +34,10 @@ jobs: run: make lint-yaml - name: shellcheck run: make lint-shell + - name: go imports ordering + run: | + go install -v github.com/incu6us/goimports-reviser/v3@latest + make lint-imports test-unit: runs-on: ubuntu-24.04 diff --git a/Makefile b/Makefile index 2a8c14cb63e..08ace13220d 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,13 @@ clean: lint: lint-go lint-yaml lint-shell lint-go: - cd $(MAKEFILE_DIR) && golangci-lint run $(VERBOSE_FLAG_LONG) + cd $(MAKEFILE_DIR) && golangci-lint run $(VERBOSE_FLAG_LONG) ./... + +lint-imports: + cd $(MAKEFILE_DIR) && goimports-reviser -list-diff -company-prefixes "github.com/containerd" ./... + +lint-fix-imports: + cd $(MAKEFILE_DIR) && goimports-reviser -company-prefixes "github.com/containerd" ./... lint-yaml: cd $(MAKEFILE_DIR) && yamllint . From 7f05aad9b4716c4fcaf3ab8cb54dbf9d5301ebc1 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 12 Aug 2024 13:34:13 -0700 Subject: [PATCH 0642/1066] Fix panics involving -ti when not on a tty Signed-off-by: apostasie --- cmd/nerdctl/compose_exec.go | 5 ++++- cmd/nerdctl/container_exec.go | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/compose_exec.go b/cmd/nerdctl/compose_exec.go index f8f4019bc42..863ff1eb281 100644 --- a/cmd/nerdctl/compose_exec.go +++ b/cmd/nerdctl/compose_exec.go @@ -18,7 +18,9 @@ package main import ( "errors" + "os" + "github.com/moby/term" "github.com/spf13/cobra" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -37,7 +39,8 @@ func newComposeExecCommand() *cobra.Command { } composeExecCommand.Flags().SetInterspersed(false) - composeExecCommand.Flags().BoolP("no-TTY", "T", false, "Disable pseudo-TTY allocation. By default nerdctl compose exec allocates a TTY.") + _, isTerminal := term.GetFdInfo(os.Stdout) + composeExecCommand.Flags().BoolP("no-TTY", "T", !isTerminal, "Disable pseudo-TTY allocation. By default nerdctl compose exec allocates a TTY.") composeExecCommand.Flags().BoolP("detach", "d", false, "Detached mode: Run containers in the background") composeExecCommand.Flags().StringP("workdir", "w", "", "Working directory inside the container") // env needs to be StringArray, not StringSlice, to prevent "FOO=foo1,foo2" from being split to {"FOO=foo1", "foo2"} diff --git a/cmd/nerdctl/container_exec.go b/cmd/nerdctl/container_exec.go index 267bc61a646..8e3b5d15d95 100644 --- a/cmd/nerdctl/container_exec.go +++ b/cmd/nerdctl/container_exec.go @@ -18,7 +18,9 @@ package main import ( "errors" + "os" + "github.com/moby/term" "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" @@ -84,6 +86,13 @@ func processExecCommandOptions(cmd *cobra.Command) (types.ContainerExecOptions, } } + _, isTerminal := term.GetFdInfo(os.Stdin) + if !flagD { + if flagT && flagI && !isTerminal { + return types.ContainerExecOptions{}, errors.New("the input device is not a TTY") + } + } + workdir, err := cmd.Flags().GetString("workdir") if err != nil { return types.ContainerExecOptions{}, err From 81684636fd4eae3dfc2e0e3ca1eb0c5beaead86c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 22:14:42 +0000 Subject: [PATCH 0643/1066] build(deps): bump github.com/go-viper/mapstructure/v2 Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.0.0 to 2.1.0. - [Release notes](https://github.com/go-viper/mapstructure/releases) - [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md) - [Commits](https://github.com/go-viper/mapstructure/compare/v2.0.0...v2.1.0) --- updated-dependencies: - dependency-name: github.com/go-viper/mapstructure/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 16b09b02bbf..973d503462e 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( github.com/fatih/color v1.17.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/fsnotify/fsnotify v1.7.0 - github.com/go-viper/mapstructure/v2 v2.0.0 + github.com/go-viper/mapstructure/v2 v2.1.0 github.com/ipfs/go-cid v0.4.1 github.com/klauspost/compress v1.17.9 github.com/mattn/go-isatty v0.0.20 diff --git a/go.sum b/go.sum index 1bc619aabdd..55c4207c2d4 100644 --- a/go.sum +++ b/go.sum @@ -123,8 +123,8 @@ github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7 github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc= -github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= +github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= From f23fcd724ccc7abba24d9f9e7dc023283d653955 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 15 Aug 2024 01:57:45 +0000 Subject: [PATCH 0644/1066] fix set go env in windows Signed-off-by: Kay Yan --- .github/workflows/test-canary.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 2e954c3caf0..9a6b0a16fc3 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -48,6 +48,9 @@ jobs: steps: - name: Set GO env run: | + # Enable extended globbing features to use advanced pattern matching + shopt -s extglob + # Get latest containerd args=(curl --proto '=https' --tlsv1.2 -fsSL -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28") [ "${GITHUB_TOKEN:-}" == "" ] && { @@ -59,7 +62,8 @@ jobs: # Get latest golang version and split it in components norm=() while read -r line; do - norm+=("$line") + line_trimmed="${line//+([[:space:]])/}" + norm+=("$line_trimmed") done < \ <(sed -E 's/^go([0-9]+)[.]([0-9]+)([.]([0-9]+))?(([a-z]+)([0-9]+))?/\1.\2\n\4\n\6\n\7/i' \ <(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version) \ From 4de7e5f4b0fd015f6bdfbc997117ba32bbc9cbf7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:51:42 +0000 Subject: [PATCH 0645/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.1.1+incompatible to 27.1.2+incompatible - [Commits](https://github.com/docker/cli/compare/v27.1.1...v27.1.2) Updates `github.com/docker/docker` from 27.1.1+incompatible to 27.1.2+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.1.1...v27.1.2) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 973d503462e..b246e798363 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.1 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.1.1+incompatible - github.com/docker/docker v27.1.1+incompatible + github.com/docker/cli v27.1.2+incompatible + github.com/docker/docker v27.1.2+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 55c4207c2d4..6bc3377fd06 100644 --- a/go.sum +++ b/go.sum @@ -88,10 +88,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE= -github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= -github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.1.2+incompatible h1:nYviRv5Y+YAKx3dFrTvS1ErkyVVunKOhoweCTE1BsnI= +github.com/docker/cli v27.1.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.1.2+incompatible h1:AhGzR1xaQIy53qCkxARaFluI00WPGtXn0AJuoQsVYTY= +github.com/docker/docker v27.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 3d2db6e7afff6266aefce63dc0526a42cf5a1151 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 14:58:34 +0000 Subject: [PATCH 0646/1066] build(deps): bump docker/build-push-action from 6.6.1 to 6.7.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.6.1 to 6.7.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.6.1...v6.7.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index fc435888a3d..4227fb6a228 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.6.1 + uses: docker/build-push-action@v6.7.0 with: context: . platforms: linux/amd64,linux/arm64 From 4fce7aaa0505c3c9e4914622a07c04215a848b76 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 12 Aug 2024 09:36:12 -0700 Subject: [PATCH 0647/1066] Ensure binfmt does install emulation for arm7 on the CI Signed-off-by: apostasie --- .github/workflows/test-canary.yml | 9 +++++++- .github/workflows/test.yml | 36 +++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 9a6b0a16fc3..05a975f37ae 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -32,7 +32,14 @@ jobs: sudo losetup -Dv sudo losetup -lv - name: "Register QEMU (tonistiigi/binfmt)" - run: docker run --privileged --rm tonistiigi/binfmt --install all + run: | + # `--install all` will only install emulation for architectures that cannot be natively executed + # Since some arm64 platforms do provide native fallback execution for 32 bits, + # armv7 emulation may or may not be installed, causing variance in the result of `uname -m`. + # To avoid that, we explicitly list the architectures we do want emulation for. + docker run --privileged --rm tonistiigi/binfmt --install linux/amd64 + docker run --privileged --rm tonistiigi/binfmt --install linux/arm64 + docker run --privileged --rm tonistiigi/binfmt --install linux/arm/v7 - name: "Run unit tests" run: go test -v ./pkg/... - name: "Run integration tests" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d6a423614b6..224878934ce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -84,7 +84,14 @@ jobs: sudo losetup -Dv sudo losetup -lv - name: "Register QEMU (tonistiigi/binfmt)" - run: docker run --privileged --rm tonistiigi/binfmt --install all + run: | + # `--install all` will only install emulation for architectures that cannot be natively executed + # Since some arm64 platforms do provide native fallback execution for 32 bits, + # armv7 emulation may or may not be installed, causing variance in the result of `uname -m`. + # To avoid that, we explicitly list the architectures we do want emulation for. + docker run --privileged --rm tonistiigi/binfmt --install linux/amd64 + docker run --privileged --rm tonistiigi/binfmt --install linux/arm64 + docker run --privileged --rm tonistiigi/binfmt --install linux/arm/v7 - name: "Run integration tests" uses: nick-fields/retry@v3 with: @@ -128,7 +135,14 @@ jobs: sudo losetup -Dv sudo losetup -lv - name: "Register QEMU (tonistiigi/binfmt)" - run: docker run --privileged --rm tonistiigi/binfmt --install all + run: | + # `--install all` will only install emulation for architectures that cannot be natively executed + # Since some arm64 platforms do provide native fallback execution for 32 bits, + # armv7 emulation may or may not be installed, causing variance in the result of `uname -m`. + # To avoid that, we explicitly list the architectures we do want emulation for. + docker run --privileged --rm tonistiigi/binfmt --install linux/amd64 + docker run --privileged --rm tonistiigi/binfmt --install linux/arm64 + docker run --privileged --rm tonistiigi/binfmt --install linux/arm/v7 - name: "Run integration tests" # The nested IPv6 network inside docker and qemu is complex and needs a bunch of sysctl config. # Therefore it's hard to debug why the IPv6 tests fail in such an isolation layer. @@ -191,7 +205,14 @@ jobs: with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" - run: docker run --privileged --rm tonistiigi/binfmt --install all + run: | + # `--install all` will only install emulation for architectures that cannot be natively executed + # Since some arm64 platforms do provide native fallback execution for 32 bits, + # armv7 emulation may or may not be installed, causing variance in the result of `uname -m`. + # To avoid that, we explicitly list the architectures we do want emulation for. + docker run --privileged --rm tonistiigi/binfmt --install linux/amd64 + docker run --privileged --rm tonistiigi/binfmt --install linux/arm64 + docker run --privileged --rm tonistiigi/binfmt --install linux/arm/v7 - name: "Prepare (network driver=slirp4netns, port driver=builtin)" run: docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} --build-arg ROOTLESSKIT_VERSION=${ROOTLESSKIT_VERSION} . - name: "Disable BuildKit for RootlessKit v1 (workaround for issue #622)" @@ -246,7 +267,14 @@ jobs: docker info docker version - name: "Register QEMU (tonistiigi/binfmt)" - run: docker run --privileged --rm tonistiigi/binfmt --install all + run: | + # `--install all` will only install emulation for architectures that cannot be natively executed + # Since some arm64 platforms do provide native fallback execution for 32 bits, + # armv7 emulation may or may not be installed, causing variance in the result of `uname -m`. + # To avoid that, we explicitly list the architectures we do want emulation for. + docker run --privileged --rm tonistiigi/binfmt --install linux/amd64 + docker run --privileged --rm tonistiigi/binfmt --install linux/arm64 + docker run --privileged --rm tonistiigi/binfmt --install linux/arm/v7 - name: "Prepare integration test environment" run: | sudo apt-get install -y expect From f5d1d6d5c11627b5d1a23d432f76e69d633079e2 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Thu, 15 Aug 2024 14:52:17 +0000 Subject: [PATCH 0648/1066] Add builder prune --all and --force flag support This change adds support for builder prune --all and --force. A refactor of previous tests which used builder prune functionality was required to handle the new confirmation prompt. A test utility was added to handle this for reuse by current and future tests. Signed-off-by: Austin Vazquez --- cmd/nerdctl/builder.go | 82 +++++++++++++++---- cmd/nerdctl/builder_build_test.go | 38 ++++----- cmd/nerdctl/builder_linux_test.go | 36 +++++++- cmd/nerdctl/compose_build_linux_test.go | 2 +- cmd/nerdctl/compose_create_linux_test.go | 2 +- cmd/nerdctl/compose_run_linux_test.go | 2 +- cmd/nerdctl/compose_up_linux_test.go | 2 +- cmd/nerdctl/container_run_mount_linux_test.go | 10 +-- cmd/nerdctl/container_run_test.go | 2 +- .../container_run_verify_linux_test.go | 2 +- cmd/nerdctl/image_encrypt_linux_test.go | 2 +- cmd/nerdctl/image_prune_test.go | 4 +- cmd/nerdctl/image_pull_linux_test.go | 6 +- cmd/nerdctl/ipfs_build_linux_test.go | 2 +- cmd/nerdctl/ipfs_compose_linux_test.go | 2 +- cmd/nerdctl/multi_platform_linux_test.go | 6 +- docs/command-reference.md | 6 +- pkg/api/types/builder_types.go | 2 + pkg/testutil/testutil.go | 8 ++ 19 files changed, 158 insertions(+), 58 deletions(-) diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index cec6ddb8597..a5f82727ecf 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -22,11 +22,11 @@ import ( "os/exec" "strings" + "github.com/docker/go-units" "github.com/spf13/cobra" - "github.com/containerd/log" - - "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/cmd/builder" ) func newBuilderCommand() *cobra.Command { @@ -58,29 +58,83 @@ func newBuilderPruneCommand() *cobra.Command { } AddStringFlag(buildPruneCommand, "buildkit-host", nil, "", "BUILDKIT_HOST", "BuildKit address") + + buildPruneCommand.Flags().BoolP("all", "a", false, "Remove all unused build cache, not just dangling ones") + buildPruneCommand.Flags().BoolP("force", "f", false, "Do not prompt for confirmation") return buildPruneCommand } func builderPruneAction(cmd *cobra.Command, _ []string) error { - globalOptions, err := processRootCmdFlags(cmd) + options, err := processBuilderPruneOptions(cmd) if err != nil { return err } - buildkitHost, err := getBuildkitHost(cmd, globalOptions.Namespace) + + if !options.Force { + var ( + confirm string + msg string + ) + + if options.All { + msg = "This will remove all build cache." + } else { + msg = "This will remove any dangling build cache." + } + msg += " Are you sure you want to continue? [y/N] " + + fmt.Fprintf(cmd.OutOrStdout(), "WARNING! %s", msg) + fmt.Fscanf(cmd.InOrStdin(), "%s", &confirm) + + if strings.ToLower(confirm) != "y" { + return nil + } + } + + prunedObjects, err := builder.Prune(cmd.Context(), options) if err != nil { return err } - buildctlBinary, err := buildkitutil.BuildctlBinary() + + var totalReclaimedSpace int64 + + for _, prunedObject := range prunedObjects { + totalReclaimedSpace += prunedObject.Size + } + + fmt.Fprintf(cmd.OutOrStdout(), "Total: %s\n", units.BytesSize(float64(totalReclaimedSpace))) + + return nil +} + +func processBuilderPruneOptions(cmd *cobra.Command) (types.BuilderPruneOptions, error) { + globalOptions, err := processRootCmdFlags(cmd) + if err != nil { + return types.BuilderPruneOptions{}, err + } + + buildkitHost, err := getBuildkitHost(cmd, globalOptions.Namespace) + if err != nil { + return types.BuilderPruneOptions{}, err + } + + all, err := cmd.Flags().GetBool("all") if err != nil { - return err + return types.BuilderPruneOptions{}, err } - buildctlArgs := buildkitutil.BuildctlBaseArgs(buildkitHost) - buildctlArgs = append(buildctlArgs, "prune") - log.L.Debugf("running %s %v", buildctlBinary, buildctlArgs) - buildctlCmd := exec.Command(buildctlBinary, buildctlArgs...) - buildctlCmd.Env = os.Environ() - buildctlCmd.Stdout = cmd.OutOrStdout() - return buildctlCmd.Run() + + force, err := cmd.Flags().GetBool("force") + if err != nil { + return types.BuilderPruneOptions{}, err + } + + return types.BuilderPruneOptions{ + Stderr: cmd.OutOrStderr(), + GOptions: globalOptions, + BuildKitHost: buildkitHost, + All: all, + Force: force, + }, nil } func newBuilderDebugCommand() *cobra.Command { diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index 9da239c786b..f187fe6441b 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -32,8 +32,8 @@ import ( func TestBuild(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() @@ -57,8 +57,8 @@ CMD ["echo", "nerdctl-build-test-string"] func TestBuildIsShareableForCompatiblePlatform(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() @@ -87,8 +87,8 @@ CMD ["echo", "nerdctl-build-test-string"] // This isn't currently supported by nerdctl with BuildKit OCI worker. func TestBuildBaseImage(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() imageName2 := imageName + "-2" @@ -122,8 +122,8 @@ CMD ["cat", "/hello2"] func TestBuildFromContainerd(t *testing.T) { testutil.DockerIncompatible(t) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() imageName2 := imageName + "-2" @@ -152,8 +152,8 @@ CMD ["cat", "/hello2"] func TestBuildFromStdin(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() @@ -166,8 +166,8 @@ CMD ["echo", "nerdctl-build-test-stdin"] func TestBuildWithDockerfile(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() @@ -198,8 +198,8 @@ CMD ["echo", "nerdctl-build-test-dockerfile"] func TestBuildLocal(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() const testFileName = "nerdctl-build-test" const testContent = "nerdctl" outputDir := t.TempDir() @@ -243,8 +243,8 @@ func createBuildContext(t *testing.T, dockerfile string) string { func TestBuildWithBuildArg(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() @@ -288,8 +288,8 @@ CMD echo $TEST_STRING func TestBuildWithIIDFile(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() @@ -312,8 +312,8 @@ CMD ["echo", "nerdctl-build-test-string"] func TestBuildWithLabels(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) dockerfile := fmt.Sprintf(`FROM %s @@ -330,8 +330,8 @@ LABEL name=nerdctl-build-test-label func TestBuildMultipleTags(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() img := testutil.Identifier(t) imgWithNoTag, imgWithCustomTag := fmt.Sprintf("%s%d", img, 2), fmt.Sprintf("%s%d:hello", img, 3) defer base.Cmd("rmi", img).AssertOK() @@ -354,10 +354,10 @@ func TestBuildMultipleTags(t *testing.T) { } func TestBuildWithContainerfile(t *testing.T) { - testutil.RequiresBuild(t) testutil.DockerIncompatible(t) + testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() @@ -375,8 +375,8 @@ CMD ["echo", "nerdctl-build-test-string"] func TestBuildWithDockerFileAndContainerfile(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() @@ -404,8 +404,8 @@ CMD ["echo", "dockerfile"] func TestBuildNoTag(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").AssertOK() base.Cmd("image", "prune", "--force", "--all").AssertOK() dockerfile := fmt.Sprintf(`FROM %s @@ -420,8 +420,8 @@ CMD ["echo", "nerdctl-build-notag-string"] func TestBuildContextDockerImageAlias(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").AssertOK() base.Cmd("image", "prune", "--force", "--all").AssertOK() dockerfile := `FROM myorg/myapp @@ -435,8 +435,8 @@ CMD ["echo", "nerdctl-build-myorg/myapp"]` func TestBuildContextWithCopyFromDir(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").AssertOK() base.Cmd("image", "prune", "--force", "--all").AssertOK() content := "hello_from_dir_2" @@ -487,8 +487,8 @@ CMD ["cat", "/source-date-epoch"] func TestBuildNetwork(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").AssertOK() dockerfile := fmt.Sprintf(`FROM %s RUN apk add --no-cache curl @@ -540,6 +540,7 @@ func buildWithNamedBuilder(base *testutil.Base, builderName string, args ...stri func TestBuildAttestation(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) builderName := testutil.Identifier(t) if testutil.GetTarget() == testutil.Docker { @@ -547,7 +548,6 @@ func TestBuildAttestation(t *testing.T) { defer base.Cmd("buildx", "rm", builderName).AssertOK() base.Cmd("buildx", "create", "--name", builderName, "--bootstrap", "--use").AssertOK() } - defer base.Cmd("builder", "prune").Run() dockerfile := "FROM " + testutil.NginxAlpineImage buildCtx := createBuildContext(t, dockerfile) diff --git a/cmd/nerdctl/builder_linux_test.go b/cmd/nerdctl/builder_linux_test.go index bca3a4649ba..cc70bd640de 100644 --- a/cmd/nerdctl/builder_linux_test.go +++ b/cmd/nerdctl/builder_linux_test.go @@ -30,6 +30,39 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil" ) +func TestBuilderPrune(t *testing.T) { + testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) + + base := testutil.NewBase(t) + + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-test-builder-prune"]`, testutil.CommonImage) + + buildCtx := createBuildContext(t, dockerfile) + + testCases := []struct { + name string + commandArgs []string + }{ + { + name: "TestBuilderPruneForce", + commandArgs: []string{"builder", "prune", "--force"}, + }, + { + name: "TestBuilderPruneForceAll", + commandArgs: []string{"builder", "prune", "--force", "--all"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + base.Cmd("build", buildCtx).AssertOK() + base.Cmd(tc.commandArgs...).AssertOK() + }) + } +} + func TestBuilderDebug(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) @@ -49,6 +82,7 @@ func TestBuildWithPull(t *testing.T) { t.Skipf("skipped because the test needs a custom buildkitd config") } testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) oldImage := testutil.BusyboxImage oldImageSha := "141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47" @@ -86,8 +120,8 @@ namespace = "%s"`, testutil.Namespace) for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").AssertOK() base.Cmd("image", "prune", "--force", "--all").AssertOK() base.Cmd("pull", oldImage).Run() diff --git a/cmd/nerdctl/compose_build_linux_test.go b/cmd/nerdctl/compose_build_linux_test.go index 9e5cfbecc53..69046355e6a 100644 --- a/cmd/nerdctl/compose_build_linux_test.go +++ b/cmd/nerdctl/compose_build_linux_test.go @@ -46,8 +46,8 @@ services: dockerfile := fmt.Sprintf(`FROM %s`, testutil.AlpineImage) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() diff --git a/cmd/nerdctl/compose_create_linux_test.go b/cmd/nerdctl/compose_create_linux_test.go index 829e3ebded5..9ad9ea59429 100644 --- a/cmd/nerdctl/compose_create_linux_test.go +++ b/cmd/nerdctl/compose_create_linux_test.go @@ -116,8 +116,8 @@ services: dockerfile := fmt.Sprintf(`FROM %s`, testutil.AlpineImage) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() diff --git a/cmd/nerdctl/compose_run_linux_test.go b/cmd/nerdctl/compose_run_linux_test.go index bdbe95a9760..cd8d353bc9a 100644 --- a/cmd/nerdctl/compose_run_linux_test.go +++ b/cmd/nerdctl/compose_run_linux_test.go @@ -426,6 +426,7 @@ func TestComposePushAndPullWithCosignVerify(t *testing.T) { testutil.RequireExecutable(t, "cosign") testutil.DockerIncompatible(t) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) t.Parallel() base := testutil.NewBase(t) @@ -435,7 +436,6 @@ func TestComposePushAndPullWithCosignVerify(t *testing.T) { reg := testregistry.NewWithNoAuth(base, 0, false) t.Cleanup(func() { keyPair.cleanup() - base.Cmd("builder", "prune").Run() reg.Cleanup(nil) }) diff --git a/cmd/nerdctl/compose_up_linux_test.go b/cmd/nerdctl/compose_up_linux_test.go index f6a0f0a35ba..cbcdbb7e43b 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/cmd/nerdctl/compose_up_linux_test.go @@ -125,8 +125,8 @@ func testComposeUp(t *testing.T, base *testutil.Base, dockerComposeYAML string, func TestComposeUpBuild(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() const dockerComposeYAML = ` services: diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container_run_mount_linux_test.go index d91d37971af..5a6a64a2f20 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container_run_mount_linux_test.go @@ -115,8 +115,8 @@ func TestRunAnonymousVolumeWithTypeMountFlag(t *testing.T) { func TestRunAnonymousVolumeWithBuild(t *testing.T) { t.Parallel() testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() @@ -134,8 +134,8 @@ VOLUME /foo func TestRunCopyingUpInitialContentsOnVolume(t *testing.T) { t.Parallel() testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() volName := testutil.Identifier(t) + "-vol" @@ -161,8 +161,8 @@ CMD ["cat", "/mnt/initial_file"] func TestRunCopyingUpInitialContentsOnDockerfileVolume(t *testing.T) { t.Parallel() testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() volName := testutil.Identifier(t) + "-vol" @@ -195,8 +195,8 @@ CMD ["cat", "/mnt/initial_file"] func TestRunCopyingUpInitialContentsOnVolumeShouldRetainSymlink(t *testing.T) { t.Parallel() testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() @@ -218,8 +218,8 @@ CMD ["readlink", "/mnt/passwd"] func TestRunCopyingUpInitialContentsShouldNotResetTheCopiedContents(t *testing.T) { t.Parallel() testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) imageName := tID + "-img" volumeName := tID + "-vol" diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index 940eb6e5743..53103317451 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -40,8 +40,8 @@ import ( func TestRunEntrypointWithBuild(t *testing.T) { t.Parallel() testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).Run() diff --git a/cmd/nerdctl/container_run_verify_linux_test.go b/cmd/nerdctl/container_run_verify_linux_test.go index 9ef955dc986..3522f12cfa6 100644 --- a/cmd/nerdctl/container_run_verify_linux_test.go +++ b/cmd/nerdctl/container_run_verify_linux_test.go @@ -28,6 +28,7 @@ func TestRunVerifyCosign(t *testing.T) { testutil.RequireExecutable(t, "cosign") testutil.DockerIncompatible(t) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) t.Parallel() base := testutil.NewBase(t) @@ -37,7 +38,6 @@ func TestRunVerifyCosign(t *testing.T) { reg := testregistry.NewWithNoAuth(base, 0, false) t.Cleanup(func() { keyPair.cleanup() - base.Cmd("builder", "prune").Run() reg.Cleanup(nil) }) diff --git a/cmd/nerdctl/image_encrypt_linux_test.go b/cmd/nerdctl/image_encrypt_linux_test.go index e8998a83060..e6809d29f5b 100644 --- a/cmd/nerdctl/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image_encrypt_linux_test.go @@ -78,7 +78,7 @@ func rmiAll(base *testutil.Base) { base.T.Logf("Pruning build caches") if _, err := buildkitutil.GetBuildkitHost(testutil.Namespace); err == nil { - base.Cmd("builder", "prune").AssertOK() + base.Cmd("builder", "prune", "--force").AssertOK() } // For BuildKit >= 0.11, pruning cache isn't enough to remove manifest blobs that are referred by build history blobs diff --git a/cmd/nerdctl/image_prune_test.go b/cmd/nerdctl/image_prune_test.go index 560c0df8e37..e2babfbde24 100644 --- a/cmd/nerdctl/image_prune_test.go +++ b/cmd/nerdctl/image_prune_test.go @@ -25,9 +25,9 @@ import ( func TestImagePrune(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").AssertOK() imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).AssertOK() @@ -47,9 +47,9 @@ func TestImagePrune(t *testing.T) { func TestImagePruneAll(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").AssertOK() imageName := testutil.Identifier(t) dockerfile := fmt.Sprintf(`FROM %s diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image_pull_linux_test.go index edfc5af1854..dbb0ff4d8e8 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image_pull_linux_test.go @@ -63,9 +63,9 @@ func TestImageVerifyWithCosign(t *testing.T) { testutil.RequireExecutable(t, "cosign") testutil.DockerIncompatible(t) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) base.Env = append(base.Env, "COSIGN_PASSWORD=1") - defer base.Cmd("builder", "prune").Run() keyPair := newCosignKeyPair(t, "cosign-key-pair", "1") defer keyPair.cleanup() tID := testutil.Identifier(t) @@ -91,8 +91,8 @@ CMD ["echo", "nerdctl-build-test-string"] func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { testutil.DockerIncompatible(t) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() reg := testregistry.NewWithNoAuth(base, 80, false) defer reg.Cleanup(nil) testImageRef := fmt.Sprintf("%s/%s:%s", @@ -113,11 +113,11 @@ func TestImageVerifyWithCosignShouldFailWhenKeyIsNotCorrect(t *testing.T) { testutil.RequireExecutable(t, "cosign") testutil.DockerIncompatible(t) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) base.Env = append(base.Env, "COSIGN_PASSWORD=1") keyPair := newCosignKeyPair(t, "cosign-key-pair", "1") defer keyPair.cleanup() - defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) reg := testregistry.NewWithNoAuth(base, 0, false) defer reg.Cleanup(nil) diff --git a/cmd/nerdctl/ipfs_build_linux_test.go b/cmd/nerdctl/ipfs_build_linux_test.go index 0623fee2b19..c3373715fa9 100644 --- a/cmd/nerdctl/ipfs_build_linux_test.go +++ b/cmd/nerdctl/ipfs_build_linux_test.go @@ -31,8 +31,8 @@ import ( func TestIPFSBuild(t *testing.T) { testutil.DockerIncompatible(t) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage) ipfsCIDBase := strings.TrimPrefix(ipfsCID, "ipfs://") diff --git a/cmd/nerdctl/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs_compose_linux_test.go index e0646cc2632..3257fef88d3 100644 --- a/cmd/nerdctl/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs_compose_linux_test.go @@ -118,8 +118,8 @@ volumes: func TestIPFSComposeUpBuild(t *testing.T) { testutil.DockerIncompatible(t) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() ipfsCID := pushImageToIPFS(t, base, testutil.NginxAlpineImage) ipfsCIDBase := strings.TrimPrefix(ipfsCID, "ipfs://") diff --git a/cmd/nerdctl/multi_platform_linux_test.go b/cmd/nerdctl/multi_platform_linux_test.go index 638b265eae5..944bcf48e28 100644 --- a/cmd/nerdctl/multi_platform_linux_test.go +++ b/cmd/nerdctl/multi_platform_linux_test.go @@ -54,9 +54,9 @@ func TestMultiPlatformRun(t *testing.T) { func TestMultiPlatformBuildPush(t *testing.T) { testutil.DockerIncompatible(t) // non-buildx version of `docker build` lacks multi-platform. Also, `docker push` lacks --platform. testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) testutil.RequireExecPlatform(t, "linux/amd64", "linux/arm64", "linux/arm/v7") base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) reg := testregistry.NewWithNoAuth(base, 0, false) defer reg.Cleanup(nil) @@ -81,9 +81,9 @@ RUN echo dummy func TestMultiPlatformBuildPushNoRun(t *testing.T) { testutil.DockerIncompatible(t) // non-buildx version of `docker build` lacks multi-platform. Also, `docker push` lacks --platform. testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) testutil.RequireExecPlatform(t, "linux/amd64", "linux/arm64", "linux/arm/v7") base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() tID := testutil.Identifier(t) reg := testregistry.NewWithNoAuth(base, 0, false) defer reg.Cleanup(nil) @@ -121,9 +121,9 @@ func TestMultiPlatformPullPushAllPlatforms(t *testing.T) { func TestMultiPlatformComposeUpBuild(t *testing.T) { testutil.DockerIncompatible(t) testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) testutil.RequireExecPlatform(t, "linux/amd64", "linux/arm64", "linux/arm/v7") base := testutil.NewBase(t) - defer base.Cmd("builder", "prune").Run() const dockerComposeYAML = ` services: diff --git a/docs/command-reference.md b/docs/command-reference.md index 459d4c1bba5..caffd51e457 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1242,6 +1242,10 @@ Usage: `nerdctl builder prune` Flags: - :nerd_face: `--buildkit-host=`: BuildKit address +- :whale: `--all`: Remove all unused build cache, not just dangling ones +- :whale: `--force`: Do not prompt for confirmation + +Unimplemented `docker builder prune` flags: `--filter`, `--keep-storage` ### :nerd_face: nerdctl builder debug @@ -1260,8 +1264,6 @@ Flags: - :nerd_face: `--target`: Set the target build stage to build - :nerd_face: `--build-arg`: Set build-time variables -Unimplemented `docker builder prune` flags: `--all`, `--filter`, `--force`, `--keep-storage` - ## System ### :whale: nerdctl events diff --git a/pkg/api/types/builder_types.go b/pkg/api/types/builder_types.go index fd8f7d87ca9..c68ec7c44b7 100644 --- a/pkg/api/types/builder_types.go +++ b/pkg/api/types/builder_types.go @@ -82,4 +82,6 @@ type BuilderPruneOptions struct { BuildKitHost string // All will remove all unused images and all build cache, not just dangling ones All bool + // Force will not prompt for confirmation. + Force bool } diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 296e6859866..492ecd79d04 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -747,3 +747,11 @@ func ImageRepo(s string) string { repo, _ := imgutil.ParseRepoTag(s) return repo } + +// RegisterBuildCacheCleanup adds a 'builder prune --all --force' cleanup function +// to run on test teardown. +func RegisterBuildCacheCleanup(t *testing.T) { + t.Cleanup(func() { + NewBase(t).Cmd("builder", "prune", "--all", "--force").Run() + }) +} From 1fbd776685d3841ea1b580acadf01b755f3526a7 Mon Sep 17 00:00:00 2001 From: Shubharanshu Mahapatra Date: Tue, 6 Aug 2024 16:05:41 -0700 Subject: [PATCH 0649/1066] fix: relax identifier limits Signed-off-by: Shubharanshu Mahapatra --- cmd/nerdctl/network_create.go | 7 ++-- pkg/composer/composer.go | 6 +-- pkg/composer/serviceparser/build.go | 8 ++-- pkg/composer/serviceparser/serviceparser.go | 6 +-- pkg/identifiers/validate.go | 45 +++++++++++++++++++++ pkg/mountutil/mountutil.go | 4 +- pkg/mountutil/volumestore/volumestore.go | 15 +++---- pkg/namestore/namestore.go | 15 ++++--- 8 files changed, 76 insertions(+), 30 deletions(-) create mode 100644 pkg/identifiers/validate.go diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index a1bfe008619..9a33cb5c67d 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -21,10 +21,9 @@ import ( "github.com/spf13/cobra" - "github.com/containerd/containerd/v2/pkg/identifiers" - "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" + "github.com/containerd/nerdctl/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/strutil" ) @@ -58,8 +57,8 @@ func networkCreateAction(cmd *cobra.Command, args []string) error { return err } name := args[0] - if err := identifiers.Validate(name); err != nil { - return fmt.Errorf("malformed name %s: %w", name, err) + if err := identifiers.ValidateDockerCompat(name); err != nil { + return fmt.Errorf("invalid network name: %w", err) } driver, err := cmd.Flags().GetString("driver") if err != nil { diff --git a/pkg/composer/composer.go b/pkg/composer/composer.go index 6ef597fbfa9..d159fbbbfaf 100644 --- a/pkg/composer/composer.go +++ b/pkg/composer/composer.go @@ -27,10 +27,10 @@ import ( compose "github.com/compose-spec/compose-go/v2/types" containerd "github.com/containerd/containerd/v2/client" - "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" + "github.com/containerd/nerdctl/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) @@ -63,8 +63,8 @@ func New(o Options, client *containerd.Client) (*Composer, error) { } if o.Project != "" { - if err := identifiers.Validate(o.Project); err != nil { - return nil, fmt.Errorf("got invalid project name %q: %w", o.Project, err) + if err := identifiers.ValidateDockerCompat(o.Project); err != nil { + return nil, fmt.Errorf("invalid project name: %w", err) } } diff --git a/pkg/composer/serviceparser/build.go b/pkg/composer/serviceparser/build.go index eea441cb77a..c13b264301a 100644 --- a/pkg/composer/serviceparser/build.go +++ b/pkg/composer/serviceparser/build.go @@ -25,10 +25,10 @@ import ( "github.com/compose-spec/compose-go/v2/types" securejoin "github.com/cyphar/filepath-securejoin" - "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) @@ -84,9 +84,11 @@ func parseBuildConfig(c *types.BuildConfig, project *types.Project, imageName st for _, s := range c.Secrets { fileRef := types.FileReferenceConfig(s) - if err := identifiers.Validate(fileRef.Source); err != nil { - return nil, fmt.Errorf("secret source %q is invalid: %w", fileRef.Source, err) + + if err := identifiers.ValidateDockerCompat(fileRef.Source); err != nil { + return nil, fmt.Errorf("invalid secret source name: %w", err) } + projectSecret, ok := project.Secrets[fileRef.Source] if !ok { return nil, fmt.Errorf("build: secret %s is undefined", fileRef.Source) diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index 86409f1bfab..e59f7cc4368 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -31,9 +31,9 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/containerd/containerd/v2/contrib/nvidia" - "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/reflectutil" ) @@ -851,8 +851,8 @@ func fileReferenceConfigToFlagV(c types.FileReferenceConfig, project *types.Proj log.L.Warnf("Ignoring: %s: %+v", objType, unknown) } - if err := identifiers.Validate(c.Source); err != nil { - return "", fmt.Errorf("%s source %q is invalid: %w", objType, c.Source, err) + if err := identifiers.ValidateDockerCompat(c.Source); err != nil { + return "", fmt.Errorf("invalid source name for %s: %w", objType, err) } var obj types.FileObjectConfig diff --git a/pkg/identifiers/validate.go b/pkg/identifiers/validate.go new file mode 100644 index 00000000000..c5276c8b17d --- /dev/null +++ b/pkg/identifiers/validate.go @@ -0,0 +1,45 @@ +/* + 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 identifiers implements functions for docker compatible identifier validation. +package identifiers + +import ( + "fmt" + "regexp" + + "github.com/containerd/errdefs" +) + +const AllowedIdentfierChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]` + +var AllowedIdentifierPattern = regexp.MustCompile(`^` + AllowedIdentfierChars + `+$`) + +// ValidateDockerCompat implements docker compatible identifier validation. +// The containerd implementation allows single character identifiers, while the +// Docker compatible implementation requires at least 2 characters for identifiers. +// The containerd implementation enforces a maximum length constraint of 76 characters, +// while the Docker compatible implementation omits the length check entirely. +func ValidateDockerCompat(s string) error { + if len(s) == 0 { + return fmt.Errorf("identifier must not be empty %w", errdefs.ErrInvalidArgument) + } + + if !AllowedIdentifierPattern.MatchString(s) { + return fmt.Errorf("identifier %q must match pattern %q: %w", s, AllowedIdentfierChars, errdefs.ErrInvalidArgument) + } + return nil +} diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index 56b5fecdad3..b2a7b90dd30 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -26,10 +26,10 @@ import ( "github.com/moby/sys/userns" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" "github.com/containerd/nerdctl/v2/pkg/strutil" @@ -260,7 +260,7 @@ func createDirOnHost(src string, createDir bool) error { } func isNamedVolume(s string) bool { - err := identifiers.Validate(s) + err := identifiers.ValidateDockerCompat(s) // If the volume name is invalid, we assume it is a path return err == nil diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index 06b440b49b6..20628db56a5 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -23,10 +23,10 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd/v2/pkg/identifiers" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/lockutil" "github.com/containerd/nerdctl/v2/pkg/strutil" @@ -109,9 +109,10 @@ func (vs *volumeStore) Unlock() error { // Create will create a new volume, or return an existing one if there is one already by that name // Besides a possible locking error, it might return ErrInvalidArgument, hard filesystem errors, json errors func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, error) { - if err := identifiers.Validate(name); err != nil { - return nil, fmt.Errorf("malformed volume name: %w (%w)", err, errdefs.ErrInvalidArgument) + if err := identifiers.ValidateDockerCompat(name); err != nil { + return nil, fmt.Errorf("invalid volume name: %w", err) } + volPath := filepath.Join(vs.dir, name) volDataPath := filepath.Join(volPath, dataDirName) volFilePath := filepath.Join(volPath, volumeJSONFileName) @@ -178,8 +179,8 @@ func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, err // Get retrieves a native volume from the store // Besides a possible locking error, it might return ErrInvalidArgument, ErrNotFound, or a filesystem error func (vs *volumeStore) Get(name string, size bool) (*native.Volume, error) { - if err := identifiers.Validate(name); err != nil { - return nil, fmt.Errorf("malformed volume name %q: %w", name, err) + if err := identifiers.ValidateDockerCompat(name); err != nil { + return nil, fmt.Errorf("invalid volume name: %w", err) } volPath := filepath.Join(vs.dir, name) volDataPath := filepath.Join(volPath, dataDirName) @@ -274,8 +275,8 @@ func (vs *volumeStore) Remove(names []string) (removed []string, warns []error, fn := func() error { for _, name := range names { // Invalid name, soft error - if err := identifiers.Validate(name); err != nil { - warns = append(warns, fmt.Errorf("malformed volume name: %w (%w)", err, errdefs.ErrInvalidArgument)) + if err := identifiers.ValidateDockerCompat(name); err != nil { + warns = append(warns, fmt.Errorf("invalid volume name: %w", err)) continue } dir := filepath.Join(vs.dir, name) diff --git a/pkg/namestore/namestore.go b/pkg/namestore/namestore.go index e2a7b8c7032..227a08a494c 100644 --- a/pkg/namestore/namestore.go +++ b/pkg/namestore/namestore.go @@ -22,8 +22,7 @@ import ( "path/filepath" "strings" - "github.com/containerd/containerd/v2/pkg/identifiers" - + "github.com/containerd/nerdctl/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/lockutil" ) @@ -49,8 +48,8 @@ type nameStore struct { } func (x *nameStore) Acquire(name, id string) error { - if err := identifiers.Validate(name); err != nil { - return fmt.Errorf("invalid name %q: %w", name, err) + if err := identifiers.ValidateDockerCompat(name); err != nil { + return fmt.Errorf("invalid name: %w", err) } if strings.TrimSpace(id) != id { return fmt.Errorf("untrimmed ID %q", id) @@ -69,8 +68,8 @@ func (x *nameStore) Release(name, id string) error { if name == "" { return nil } - if err := identifiers.Validate(name); err != nil { - return fmt.Errorf("invalid name %q: %w", name, err) + if err := identifiers.ValidateDockerCompat(name); err != nil { + return fmt.Errorf("invalid name: %w", err) } if strings.TrimSpace(id) != id { return fmt.Errorf("untrimmed ID %q", id) @@ -96,8 +95,8 @@ func (x *nameStore) Rename(oldName, id, newName string) error { if oldName == "" || newName == "" { return nil } - if err := identifiers.Validate(newName); err != nil { - return fmt.Errorf("invalid name %q: %w", oldName, err) + if err := identifiers.ValidateDockerCompat(newName); err != nil { + return fmt.Errorf("invalid name %q: %w", newName, err) } fn := func() error { oldFileName := filepath.Join(x.dir, oldName) From fc4b2700ae73c580393f6a0b1fec7f9d127d66c1 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Fri, 31 May 2024 12:21:12 +0000 Subject: [PATCH 0650/1066] support ci arm64 Signed-off-by: Kay Yan --- .github/workflows/test.yml | 8 +++++++- pkg/testutil/testutil_linux.go | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 224878934ce..4aa94e972a9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -55,7 +55,7 @@ jobs: run: go test -v ./pkg/... test-integration: - runs-on: "ubuntu-${{ matrix.ubuntu }}" + runs-on: "${{ matrix.runner }}" timeout-minutes: 40 strategy: fail-fast: false @@ -64,10 +64,16 @@ jobs: include: - ubuntu: 20.04 containerd: v1.6.33 + runner: "ubuntu-20.04" - ubuntu: 22.04 containerd: v1.7.19 + runner: "ubuntu-22.04" + - ubuntu: 24.04 + containerd: v2.0.0-rc.3 + runner: "ubuntu-24.04" - ubuntu: 24.04 containerd: v2.0.0-rc.3 + runner: github-arm64-2c-8gb env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index 7aa47117294..0629abbdac2 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -40,7 +40,7 @@ var ( WordpressIndexHTMLSnippet = "WordPress › Installation" MariaDBImage = mirrorOf("mariadb:10.5") DockerAuthImage = mirrorOf("cesanta/docker_auth:1.7") - FluentdImage = mirrorOf("fluent/fluentd:v1.14-1") + FluentdImage = "fluent/fluentd:v1.17.0-debian-1.0" KuboImage = mirrorOf("ipfs/kubo:v0.16.0") SystemdImage = "ghcr.io/containerd/stargz-snapshotter:0.15.1-kind" From 97c5492bb902dc0ba2fffd56a36e97d473ca3a62 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 11 Aug 2024 20:41:43 -0700 Subject: [PATCH 0651/1066] Kube on the CI Signed-off-by: apostasie --- .github/workflows/test-kube.yml | 27 ++ .github/workflows/test.yml | 4 +- Dockerfile | 6 +- cmd/nerdctl/container_commit_linux_test.go | 70 ++++++ .../container_run_restart_linux_test.go | 2 +- hack/build-integration-canary.sh | 150 +---------- hack/build-integration-kube.sh | 100 ++++++++ hack/kind.yaml | 12 + hack/scripts/lib.sh | 236 ++++++++++++++++++ pkg/testutil/testutil.go | 47 +++- 10 files changed, 497 insertions(+), 157 deletions(-) create mode 100644 .github/workflows/test-kube.yml create mode 100644 cmd/nerdctl/container_commit_linux_test.go create mode 100755 hack/build-integration-kube.sh create mode 100644 hack/kind.yaml create mode 100755 hack/scripts/lib.sh diff --git a/.github/workflows/test-kube.yml b/.github/workflows/test-kube.yml new file mode 100644 index 00000000000..593cc5b4511 --- /dev/null +++ b/.github/workflows/test-kube.yml @@ -0,0 +1,27 @@ +# This pipeline purpose is solely meant to run a subset of our test suites against a kube cluster +name: kube + +on: + push: + branches: + - main + - 'release/**' + pull_request: + paths-ignore: + - '**.md' + +env: + ROOTFUL: true + +jobs: + linux: + runs-on: "ubuntu-24.04" + timeout-minutes: 40 + steps: + - uses: actions/checkout@v4.1.7 + with: + fetch-depth: 1 + - name: "Run Kube integration tests" + run: | + ./hack/build-integration-kube.sh + sudo ./_output/nerdctl exec nerdctl-test-control-plane bash -c -- 'export TMPDIR="$HOME"/tmp; mkdir -p "$TMPDIR"; cd /nerdctl-source; /usr/local/go/bin/go test ./cmd/nerdctl/ -test.only-kube' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 224878934ce..10da7bca6f0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -284,14 +284,14 @@ jobs: timeout_minutes: 30 max_attempts: 2 retry_on: error - command: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon + command: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon - name: "Ensure that the IPv6 integration test suite is compatible with Docker" uses: nick-fields/retry@v3 with: timeout_minutes: 30 max_attempts: 2 retry_on: error - command: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.kill-daemon -test.ipv6 + command: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon -test.only-ipv6 test-integration-windows: runs-on: windows-2022 diff --git a/Dockerfile b/Dockerfile index dca67237b11..43bedeaeb64 100644 --- a/Dockerfile +++ b/Dockerfile @@ -319,7 +319,7 @@ RUN curl -o nydus-static.tgz -fsSL --proto '=https' --tlsv1.2 "https://github.co mv nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/bin/ && \ rm nydus-static.tgz CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/v2/cmd/nerdctl/...", \ - "--", "-timeout=60m", "-args", "-test.kill-daemon"] + "--", "-timeout=60m", "-args", "-test.allow-kill-daemon"] FROM test-integration AS test-integration-rootless # Install SSH for creating systemd user session. @@ -345,7 +345,7 @@ COPY ./Dockerfile.d/test-integration-rootless.sh / CMD ["/test-integration-rootless.sh", \ "gotestsum", "--format=testname", "--rerun-fails=2", "--raw-command", \ "--", "/usr/local/go/bin/go", "tool", "test2json", "-t", "-p", "github.com/containerd/nerdctl/v2/cmd/nerdctl", \ - "/usr/local/bin/nerdctl.test", "-test.v", "-test.timeout=60m", "-test.kill-daemon"] + "/usr/local/bin/nerdctl.test", "-test.v", "-test.timeout=60m", "-test.allow-kill-daemon"] # test for CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=slirp4netns FROM test-integration-rootless AS test-integration-rootless-port-slirp4netns @@ -354,6 +354,6 @@ RUN chown -R rootless:rootless /home/rootless/.config FROM test-integration AS test-integration-ipv6 CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/v2/cmd/nerdctl/...", \ - "--", "-timeout=60m", "-args", "-test.kill-daemon", "-test.ipv6"] + "--", "-timeout=60m", "-args", "-test.allow-kill-daemon", "-test.only-ipv6"] FROM base AS demo diff --git a/cmd/nerdctl/container_commit_linux_test.go b/cmd/nerdctl/container_commit_linux_test.go new file mode 100644 index 00000000000..a26c3b1eff6 --- /dev/null +++ b/cmd/nerdctl/container_commit_linux_test.go @@ -0,0 +1,70 @@ +/* + 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 ( + "strings" + "testing" + + "gotest.tools/v3/icmd" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestKubeCommitPush(t *testing.T) { + t.Parallel() + + base := testutil.NewBaseForKube(t) + tID := testutil.Identifier(t) + + var containerID string + + setup := func() { + testutil.KubectlHelper(base, "run", "--image", testutil.CommonImage, tID, "--", "sleep", "Inf"). + AssertOK() + + testutil.KubectlHelper(base, "wait", "pod", tID, "--for=condition=ready", "--timeout=1m"). + AssertOK() + + testutil.KubectlHelper(base, "exec", tID, "--", "mkdir", "-p", "/tmp/whatever"). + AssertOK() + + cmd := testutil.KubectlHelper(base, "get", "pods", tID, "-o", "jsonpath={ .status.containerStatuses[0].containerID }") + cmd.Run() + containerID = strings.TrimPrefix(cmd.Out(), "containerd://") + } + + tearDown := func() { + testutil.KubectlHelper(base, "delete", "pod", tID).Run() + } + + tearDown() + t.Cleanup(tearDown) + setup() + + t.Run("test commit / push on Kube (https://github.com/containerd/nerdctl/issues/827)", func(t *testing.T) { + t.Log("This test is meant to verify that we can commit / push an image from a pod." + + "Currently, this is broken, hence the test assumes it will fail. Once the problem is fixed, we should just" + + "change the expectation to 'success'.") + + base.Cmd("commit", containerID, "registry.example.com/my-app:v1").AssertOK() + base.Cmd("push", "registry.example.com/my-app:v1").Assert(icmd.Expected{ + ExitCode: 1, + Err: "failed to create a tmp single-platform image", + }) + }) +} diff --git a/cmd/nerdctl/container_run_restart_linux_test.go b/cmd/nerdctl/container_run_restart_linux_test.go index d9ba357b8fc..6aeb08613b6 100644 --- a/cmd/nerdctl/container_run_restart_linux_test.go +++ b/cmd/nerdctl/container_run_restart_linux_test.go @@ -41,7 +41,7 @@ func TestRunRestart(t *testing.T) { } base := testutil.NewBase(t) if !base.DaemonIsKillable { - t.Skip("daemon is not killable (hint: set \"-test.kill-daemon\")") + t.Skip("daemon is not killable (hint: set \"-test.allow-kill-daemon\")") } t.Log("NOTE: this test may take a while") diff --git a/hack/build-integration-canary.sh b/hack/build-integration-canary.sh index 8091a192034..4a75a0d427b 100755 --- a/hack/build-integration-canary.sh +++ b/hack/build-integration-canary.sh @@ -16,6 +16,10 @@ # 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" ###################### # Definitions @@ -67,141 +71,6 @@ STARGZ_SNAPSHOTTER_CHECKSUM=linux # We specifically want the static ones TINI_CHECKSUM=static - -###################### -# Lib -###################### - -# Simple logger -readonly LOG_LEVEL_DEBUG=0 -readonly LOG_LEVEL_INFO=1 -readonly LOG_LEVEL_WARNING=2 -readonly LOG_LEVEL_ERROR=3 - -readonly LOG_COLOR_BLACK=0 -readonly LOG_COLOR_RED=1 -readonly LOG_COLOR_GREEN=2 -readonly LOG_COLOR_YELLOW=3 -readonly LOG_COLOR_BLUE=4 -readonly LOG_COLOR_MAGENTA=5 -readonly LOG_COLOR_CYAN=6 -readonly LOG_COLOR_WHITE=7 -readonly LOG_COLOR_DEFAULT=9 - -readonly LOG_STYLE_DEBUG=( setaf "$LOG_COLOR_WHITE" ) -readonly LOG_STYLE_INFO=( setaf "$LOG_COLOR_GREEN" ) -readonly LOG_STYLE_WARNING=( setaf "$LOG_COLOR_YELLOW" ) -readonly LOG_STYLE_ERROR=( setaf "$LOG_COLOR_RED" ) - -_log::log(){ - local level - local style - local numeric_level - local message="$2" - - level="$(printf "%s" "$1" | tr '[:lower:]' '[:upper:]')" - numeric_level="$(printf "LOG_LEVEL_%s" "$level")" - style="LOG_STYLE_${level}[@]" - - [ "${!numeric_level}" -ge "$LOG_LEVEL" ] || return 0 - - [ ! "$TERM" ] || [ ! -t 2 ] || >&2 tput "${!style}" 2>/dev/null || true - >&2 printf "[%s] %s: %s\n" "$(date 2>/dev/null || true)" "$(printf "%s" "$level" | tr '[:lower:]' '[:upper:]')" "$message" - [ ! "$TERM" ] || [ ! -t 2 ] || >&2 tput op 2>/dev/null || true -} - -log::init(){ - local _ll - # Default log to warning if unspecified - _ll="$(printf "LOG_LEVEL_%s" "${NERDCTL_CI_LOG_LEVEL:-warning}" | tr '[:lower:]' '[:upper:]')" - # Default to 3 (warning) if unrecognized - LOG_LEVEL="${!_ll:-3}" -} - -log::debug(){ - _log::log debug "$@" -} - -log::info(){ - _log::log info "$@" -} - -log::warning(){ - _log::log warning "$@" -} - -log::error(){ - _log::log error "$@" -} - -# Helpers -host::require(){ - local binary="$1" - command -v "$binary" >/dev/null || { - log::error "You need $binary for this script to work, and it cannot be found in your path" - exit 1 - } -} - -fs::mktemp(){ - mktemp -dq "${TMPDIR:-/tmp}/$prefix.XXXXXX" 2>/dev/null || mktemp -dq || { - log::error "Failed to create temporary directory" - exit 1 - } -} - -http::get(){ - local args=(curl --proto '=https' --tlsv1.2 -fsSL) - args+=("$@") - - log::debug "${args[*]}" - "${args[@]}" -} - -http::checksum(){ - local urls=("$@") - local url - - local prefix="nerdctl-checksum" - - local temp - temp="$(fs::mktemp)" - - for url in "${urls[@]}"; do - http::get -o "$temp/${url##*/}" "$url" - done - - cd "$temp" - shasum -a 256 ./* - cd - >/dev/null || true -} - -# Github API helpers -# Set GITHUB_TOKEN to use authenticated requests to workaround limitations -github::request(){ - local endpoint="$1" - local args=( - -H "Accept: application/vnd.github+json" - -H "X-GitHub-Api-Version: 2022-11-28" - ) - - [ "${GITHUB_TOKEN:-}" == "" ] || args+=(-H "Authorization: Bearer $GITHUB_TOKEN") - - http::get "${args[@]}" https://api.github.com/"$endpoint" -} - -github::tags::getlatest(){ - local repo="$1" - github::request "repos/$repo/tags" | - jq -rc .[0].name -} - -github::releases::latest(){ - local repo="$1" - github::request "repos/$repo/releases" | - jq -rc .[] -} - version::compare(){ local raw_version_fd="$1" local parsed @@ -304,7 +173,7 @@ latest::release(){ higher_data="$line" higher_readable="$(echo "$line" | jq -rc .name | sed -E 's/(.*[ ])?(v?[0-9][0-9.a-z-]+).*/\2/')" fi - done < <(github::releases::latest "$repo") + done < <(github::releases "$repo") log::info " >>> latest release detected: $higher_readable" } @@ -314,7 +183,7 @@ latest::tag(){ local repo="$1" log::info "Analyzing tags for $repo" - github::tags::getlatest "$repo" + github::tags::latest "$repo" } # Once a latest release has been retrieved for a given project, you can get the url to the asset matching OS and ARCH @@ -342,13 +211,6 @@ assets::get(){ } } -log::init -host::require jq -host::require curl -host::require shasum -host::require docker -host::require tput - ###################### # Script ###################### diff --git a/hack/build-integration-kube.sh b/hack/build-integration-kube.sh new file mode 100755 index 00000000000..0f867530e2c --- /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.22 +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/hack/kind.yaml b/hack/kind.yaml new file mode 100644 index 00000000000..1695fafdb88 --- /dev/null +++ b/hack/kind.yaml @@ -0,0 +1,12 @@ +# https://pkg.go.dev/sigs.k8s.io/kind/pkg/apis/config/v1alpha4#Cluster +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: + - role: control-plane + extraMounts: + - hostPath: _output/nerdctl + containerPath: /usr/local/bin/nerdctl + - hostPath: /tmp/go + containerPath: /usr/local/go + - hostPath: . + containerPath: /nerdctl-source diff --git a/hack/scripts/lib.sh b/hack/scripts/lib.sh new file mode 100755 index 00000000000..de0fa173bae --- /dev/null +++ b/hack/scripts/lib.sh @@ -0,0 +1,236 @@ +#!/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 + +## This is a library of generic helpers that can be used across different projects + +# Simple logger +readonly LOG_LEVEL_DEBUG=0 +readonly LOG_LEVEL_INFO=1 +readonly LOG_LEVEL_WARNING=2 +readonly LOG_LEVEL_ERROR=3 + +readonly LOG_COLOR_BLACK=0 +readonly LOG_COLOR_RED=1 +readonly LOG_COLOR_GREEN=2 +readonly LOG_COLOR_YELLOW=3 +readonly LOG_COLOR_BLUE=4 +readonly LOG_COLOR_MAGENTA=5 +readonly LOG_COLOR_CYAN=6 +readonly LOG_COLOR_WHITE=7 +readonly LOG_COLOR_DEFAULT=9 + +readonly LOG_STYLE_DEBUG=( setaf "$LOG_COLOR_WHITE" ) +readonly LOG_STYLE_INFO=( setaf "$LOG_COLOR_GREEN" ) +readonly LOG_STYLE_WARNING=( setaf "$LOG_COLOR_YELLOW" ) +readonly LOG_STYLE_ERROR=( setaf "$LOG_COLOR_RED" ) + +_log::log(){ + local level + local style + local numeric_level + local message="$2" + + level="$(printf "%s" "$1" | tr '[:lower:]' '[:upper:]')" + numeric_level="$(printf "LOG_LEVEL_%s" "$level")" + style="LOG_STYLE_${level}[@]" + + [ "${!numeric_level}" -ge "$LOG_LEVEL" ] || return 0 + + [ ! "$TERM" ] || [ ! -t 2 ] || >&2 tput "${!style}" 2>/dev/null || true + >&2 printf "[%s] %s: %s\n" "$(date 2>/dev/null || true)" "$(printf "%s" "$level" | tr '[:lower:]' '[:upper:]')" "$message" + [ ! "$TERM" ] || [ ! -t 2 ] || >&2 tput op 2>/dev/null || true +} + +log::init(){ + local _ll + # Default log to warning if unspecified + _ll="$(printf "LOG_LEVEL_%s" "${LOG_LEVEL:-warning}" | tr '[:lower:]' '[:upper:]')" + # Default to 3 (warning) if unrecognized + LOG_LEVEL="${!_ll:-3}" +} + +log::debug(){ + _log::log debug "$@" +} + +log::info(){ + _log::log info "$@" +} + +log::warning(){ + _log::log warning "$@" +} + +log::error(){ + _log::log error "$@" +} + +# Helpers +host::require(){ + local binary="$1" + + log::debug "Checking presence of $binary" + command -v "$binary" >/dev/null || { + log::error "You need $binary for this script to work, and it cannot be found in your path" + return 1 + } +} + +host::install(){ + local binary + + for binary in "$@"; do + log::debug "sudo install -D -m 755 $binary /usr/local/bin/$(basename "$binary")" + sudo install -D -m 755 "$binary" /usr/local/bin/"$(basename "$binary")" + done +} + +fs::mktemp(){ + local prefix="${1:-temporary}" + + mktemp -dq "${TMPDIR:-/tmp}/$prefix.XXXXXX" 2>/dev/null || mktemp -dq || { + log::error "Failed to create temporary directory" + return 1 + } +} + +tar::expand(){ + local dir="$1" + local arc="$2" + + log::debug "tar -C $dir -xzf $arc" + tar -C "$dir" -xzf "$arc" +} + +_http::get(){ + local url="$1" + local output="$2" + local retry="$3" + local delay="$4" + local user="${5:-}" + local password="${6:-}" + shift + shift + shift + shift + shift + shift + + local header + local command=(curl -fsSL --retry "$retry" --retry-delay "$delay" -o "$output") + # Add a basic auth user if necessary + [ "$user" == "" ] || command+=(--user "$user:$password") + # Force tls v1.2 and no redirect to http if url scheme is https + [ "${url:0:5}" != "https" ] || command+=(--proto '=https' --tlsv1.2) + # Stuff in any additional arguments as headers + for header in "$@"; do + command+=(-H "$header") + done + # Debug + log::debug "${command[*]} $url" + # Exec + "${command[@]}" "$url" || { + log::error "Failed to connect to $url with $retry retries every $delay seconds" + return 1 + } +} + +http::get(){ + local output="$1" + local url="$2" + shift + shift + + _http::get "$url" "$output" "2" "1" "" "" "$@" +} + +http::healthcheck(){ + local url="$1" + local retry="${2:-5}" + local delay="${3:-1}" + local user="${4:-}" + local password="${5:-}" + shift + shift + shift + shift + shift + + _http::get "$url" /dev/null "$retry" "$delay" "$user" "$password" "$@" +} + +http::checksum(){ + local urls=("$@") + local url + + local temp + temp="$(fs::mktemp "http-checksum")" + + for url in "${urls[@]}"; do + http::get "$temp/${url##*/}" "$url" + done + + cd "$temp" + shasum -a 256 ./* + cd - >/dev/null || true +} + +# Github API helpers +# Set GITHUB_TOKEN to use authenticated requests to workaround limitations + +github::settoken(){ + local token="$1" + # If passed token is a github action pattern replace, and we are NOT on github, ignore it + # shellcheck disable=SC2016 + [ "${token:0:3}" == '${{' ] || GITHUB_TOKEN="$token" +} + +github::request(){ + local endpoint="$1" + local args=( + "Accept: application/vnd.github+json" + "X-GitHub-Api-Version: 2022-11-28" + ) + + [ "${GITHUB_TOKEN:-}" == "" ] || args+=("Authorization: Bearer $GITHUB_TOKEN") + + http::get /dev/stdout https://api.github.com/"$endpoint" "${args[@]}" +} + +github::tags::latest(){ + local repo="$1" + github::request "repos/$repo/tags" | jq -rc .[0].name +} + +github::releases(){ + local repo="$1" + github::request "repos/$repo/releases" | + jq -rc .[] +} + +github::releases::latest(){ + local repo="$1" + github::request "repos/$repo/releases/latest" | jq -rc . +} + +log::init +host::require jq +host::require tar +host::require curl +host::require shasum diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 492ecd79d04..e1d4b1128d3 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -52,6 +52,8 @@ type Base struct { DaemonIsKillable bool EnableIPv6 bool IPv6Compatible bool + EnableKube bool + KubeCompatible bool Binary string Args []string Env []string @@ -148,7 +150,7 @@ func (b *Base) systemctlArgs() []string { func (b *Base) KillDaemon() { b.T.Helper() if !b.DaemonIsKillable { - b.T.Skip("daemon is not killable (hint: set \"-test.kill-daemon\")") + b.T.Skip("daemon is not killable (hint: set \"-test.allow-kill-daemon\")") } target := b.systemctlTarget() b.T.Logf("killing %q", target) @@ -540,12 +542,14 @@ var ( flagTestTarget Target flagTestKillDaemon bool flagTestIPv6 bool + flagTestKube bool ) func M(m *testing.M) { flag.StringVar(&flagTestTarget, "test.target", Nerdctl, "target to test") - flag.BoolVar(&flagTestKillDaemon, "test.kill-daemon", false, "enable tests that kill the daemon") - flag.BoolVar(&flagTestIPv6, "test.ipv6", false, "enable tests on IPv6") + flag.BoolVar(&flagTestKillDaemon, "test.allow-kill-daemon", false, "enable tests that kill the daemon") + flag.BoolVar(&flagTestIPv6, "test.only-ipv6", false, "enable tests on IPv6") + flag.BoolVar(&flagTestKube, "test.only-kube", false, "enable tests on Kube") flag.Parse() fmt.Fprintf(os.Stderr, "test target: %q\n", flagTestTarget) os.Exit(m.Run()) @@ -562,6 +566,10 @@ func GetEnableIPv6() bool { return flagTestIPv6 } +func GetEnableKube() bool { + return flagTestKube +} + func GetDaemonIsKillable() bool { return flagTestKillDaemon } @@ -681,24 +689,34 @@ func NewBaseWithNamespace(t *testing.T, ns string) *Base { if ns == "" || ns == "default" || ns == Namespace { t.Fatalf(`the other base namespace cannot be "%s"`, ns) } - return newBase(t, ns, false) + return newBase(t, ns, false, false) } func NewBaseWithIPv6Compatible(t *testing.T) *Base { - return newBase(t, Namespace, true) + return newBase(t, Namespace, true, false) +} + +func NewBaseForKube(t *testing.T) *Base { + base := newBase(t, "k8s.io", false, true) + // NOTE: kubectl namespaces are not the same as containerd namespaces. + // We still want kube test objects segregated in their own Kube API namespace. + KubectlHelper(base, "create", "namespace", Namespace).Run() + return base } func NewBase(t *testing.T) *Base { - return newBase(t, Namespace, false) + return newBase(t, Namespace, false, false) } -func newBase(t *testing.T, ns string, ipv6Compatible bool) *Base { +func newBase(t *testing.T, ns string, ipv6Compatible bool, kubeCompatible bool) *Base { base := &Base{ T: t, Target: GetTarget(), DaemonIsKillable: GetDaemonIsKillable(), EnableIPv6: GetEnableIPv6(), IPv6Compatible: ipv6Compatible, + EnableKube: GetEnableKube(), + KubeCompatible: kubeCompatible, Env: os.Environ(), } if base.EnableIPv6 && !base.IPv6Compatible { @@ -706,6 +724,11 @@ func newBase(t *testing.T, ns string, ipv6Compatible bool) *Base { } else if !base.EnableIPv6 && base.IPv6Compatible { t.Skip("runner skips IPv6 compatible tests in the non-IPv6 environment") } + if base.EnableKube && !base.KubeCompatible { + t.Skip("runner skips non-kube compatible tests in the kube environment") + } else if !base.EnableKube && base.KubeCompatible { + t.Skip("runner skips kube compatible tests in the non-kube environment") + } var err error switch base.Target { case Nerdctl: @@ -755,3 +778,13 @@ func RegisterBuildCacheCleanup(t *testing.T) { NewBase(t).Cmd("builder", "prune", "--all", "--force").Run() }) } + +func KubectlHelper(base *Base, args ...string) *Cmd { + base.T.Helper() + icmdCmd := icmd.Command("kubectl", append([]string{"--namespace", Namespace}, args...)...) + icmdCmd.Env = base.Env + return &Cmd{ + Cmd: icmdCmd, + Base: base, + } +} From adf403544b47558a61c1b79c23b4e91526102415 Mon Sep 17 00:00:00 2001 From: Sam Chew Date: Fri, 16 Aug 2024 09:54:46 -0700 Subject: [PATCH 0652/1066] Include init NetworkSettings within inspect response Related to [containerd#3310](https://github.com/containerd/nerdctl/issues/3310) New behavior will always initialize a NetworkSettings entity for the inspect response, including Ports child member. If inspecting a running container with published ports, then all information will be correctly returned. If inspecting a running container without published ports, then NetworkSettings will include an initialized Ports member. If inspecting a stopped/exited container, then an entirely initialized, "empty-value" NetworkSettings is returned. Signed-off-by: Sam Chew --- pkg/inspecttypes/dockercompat/dockercompat.go | 16 ++- .../dockercompat/dockercompat_test.go | 130 +++++++++++++++++- 2 files changed, 139 insertions(+), 7 deletions(-) diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index 16c1a91a282..f1704f1781a 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -186,7 +186,7 @@ type ContainerState struct { } type NetworkSettings struct { - Ports *nat.PortMap `json:",omitempty"` + Ports *nat.PortMap DefaultNetworkSettings Networks map[string]*NetworkEndpointSettings } @@ -398,12 +398,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 { @@ -447,8 +450,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 index efca61c087e..483f7aed3d8 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat_test.go +++ b/pkg/inspecttypes/dockercompat/dockercompat_test.go @@ -17,11 +17,13 @@ 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" @@ -91,6 +93,10 @@ func TestContainerFromNative(t *testing.T) { }, 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 @@ -172,6 +178,10 @@ func TestContainerFromNative(t *testing.T) { // ignore sysfs mountpoint }, Config: &Config{}, + NetworkSettings: &NetworkSettings{ + Ports: &nat.PortMap{}, + Networks: map[string]*NetworkEndpointSettings{}, + }, }, }, // ctr container, mount /mnt/foo:/mnt/foo:rw,rslave; internal sysfs mount; hostname @@ -226,12 +236,128 @@ func TestContainerFromNative(t *testing.T) { Config: &Config{ Hostname: "host1", }, + 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 { - d, _ := ContainerFromNative(tc.n) - assert.DeepEqual(t, d, tc.expected) + t.Run(tc.name, func(tt *testing.T) { + d, _ := networkSettingsFromNative(tc.n, tc.s) + assert.DeepEqual(tt, d, tc.expected) + }) } } From ec7c3958679f3c547e428a1d9f9bc357bf7fcc8c Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Sat, 17 Aug 2024 04:09:14 +0000 Subject: [PATCH 0653/1066] Refactor imgutil filtering Signed-off-by: Austin Vazquez --- cmd/nerdctl/image_list_test.go | 2 + docs/command-reference.md | 2 +- pkg/cmd/image/list.go | 37 ++-- pkg/cmd/image/prune.go | 5 +- pkg/imgutil/filtering.go | 215 ++++++++++++------- pkg/imgutil/filtering_test.go | 382 +++++++++++++++++++++++++++++++++ 6 files changed, 541 insertions(+), 102 deletions(-) create mode 100644 pkg/imgutil/filtering_test.go diff --git a/cmd/nerdctl/image_list_test.go b/cmd/nerdctl/image_list_test.go index ba855cc2303..e91a9043f54 100644 --- a/cmd/nerdctl/image_list_test.go +++ b/cmd/nerdctl/image_list_test.go @@ -79,6 +79,7 @@ func TestImages(t *testing.T) { func TestImagesFilter(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) t.Parallel() base := testutil.NewBase(t) tempName := testutil.Identifier(base.T) @@ -121,6 +122,7 @@ LABEL version=0.1`, testutil.CommonImage) func TestImagesFilterDangling(t *testing.T) { testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) base.Cmd("images", "prune", "--all").AssertOK() diff --git a/docs/command-reference.md b/docs/command-reference.md index caffd51e457..9106aa76397 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -746,7 +746,7 @@ Flags: - :nerd_face: `--format=wide`: Wide table - :nerd_face: `--format=json`: Alias of `--format='{{json .}}'` - :whale: `--digests`: Show digests (compatible with Docker, unlike ID) -- :whale: `-f, --filter`: Filter the images. For now, only 'before=' and 'since=' is supported. +- :whale: `-f, --filter`: Filter the images. - :whale: `--filter=before=`: Images created before given image (exclusive) - :whale: `--filter=since=`: Images created after given image (exclusive) - :whale: `--filter=label=`: Matches images based on the presence of a label alone or a label and a value diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index a7e6f46c6a1..2b10a63d54c 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -80,36 +80,29 @@ func List(ctx context.Context, client *containerd.Client, filters, nameAndRefFil return nil, err } - if f.Dangling != nil { - imageList = imgutil.FilterDangling(imageList, *f.Dangling) + filters := []imgutil.Filter{} + if f.Dangling != nil && *f.Dangling { + filters = append(filters, imgutil.FilterDanglingImages()) + } else if f.Dangling != nil { + filters = append(filters, imgutil.FilterTaggedImages()) } - imageList, err = imgutil.FilterByLabel(ctx, client, imageList, f.Labels) - if err != nil { - return nil, err + if len(f.Labels) > 0 { + filters = append(filters, imgutil.FilterByLabel(ctx, client, f.Labels)) } - imageList, err = imgutil.FilterByReference(imageList, f.Reference) - if err != nil { - return nil, err + if len(f.Reference) > 0 { + filters = append(filters, imgutil.FilterByReference(f.Reference)) } - var beforeImages []images.Image - if len(f.Before) > 0 { - beforeImages, err = imageStore.List(ctx, f.Before...) - if err != nil { - return nil, err - } - } - var sinceImages []images.Image - if len(f.Since) > 0 { - sinceImages, err = imageStore.List(ctx, f.Since...) - if err != nil { - return nil, err - } + if len(f.Before) > 0 || len(f.Since) > 0 { + filters = append(filters, imgutil.FilterByCreatedAt(ctx, client, f.Before, f.Since)) } - imageList = imgutil.FilterImages(imageList, beforeImages, sinceImages) + imageList, err = imgutil.ApplyFilters(imageList, filters...) + if err != nil { + return []images.Image{}, err + } } sort.Slice(imageList, func(i, j int) bool { diff --git a/pkg/cmd/image/prune.go b/pkg/cmd/image/prune.go index b2888c8ea71..159d2d6c8b1 100644 --- a/pkg/cmd/image/prune.go +++ b/pkg/cmd/image/prune.go @@ -64,7 +64,10 @@ func Prune(ctx context.Context, client *containerd.Client, options types.ImagePr filteredImages = append(filteredImages, image) } } else { - filteredImages = imgutil.FilterDangling(imageList, true) + filteredImages, err = imgutil.FilterDanglingImages()(imageList) + if err != nil { + return err + } } delOpts := []images.DeleteOpt{images.SynchronousDelete()} diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index 6942b84353c..fa35a909970 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -27,13 +27,12 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" - "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) // Filter types supported to filter images. -var ( +const ( FilterBeforeType = "before" FilterSinceType = "since" FilterLabelType = "label" @@ -50,6 +49,8 @@ type Filters struct { Dangling *bool } +type Filter func([]images.Image) ([]images.Image, error) + // ParseFilters parse filter strings. func ParseFilters(filters []string) (*Filters, error) { f := &Filters{Labels: make(map[string]string)} @@ -105,103 +106,161 @@ func ParseFilters(filters []string) (*Filters, error) { return f, nil } -// FilterImages returns images in `labelImages` that are created -// before MAX(beforeImages.CreatedAt) and after MIN(sinceImages.CreatedAt). -func FilterImages(labelImages []images.Image, beforeImages []images.Image, sinceImages []images.Image) []images.Image { - var filteredImages []images.Image - maxTime := time.Now() - minTime := time.Date(1970, time.Month(1), 1, 0, 0, 0, 0, time.UTC) - if len(beforeImages) > 0 { - maxTime = beforeImages[0].CreatedAt - for _, value := range beforeImages { - if value.CreatedAt.After(maxTime) { - maxTime = value.CreatedAt - } - } - } - if len(sinceImages) > 0 { - minTime = sinceImages[0].CreatedAt - for _, value := range sinceImages { - if value.CreatedAt.Before(minTime) { - minTime = value.CreatedAt - } - } - } - for _, image := range labelImages { - if image.CreatedAt.After(minTime) && image.CreatedAt.Before(maxTime) { - filteredImages = append(filteredImages, image) +// ApplyFilters applies each filter function in the order provided +// and returns the resulting filtered image list. +func ApplyFilters(imageList []images.Image, filters ...Filter) ([]images.Image, error) { + var err error + for _, filter := range filters { + imageList, err = filter(imageList) + if err != nil { + return []images.Image{}, err } } - return filteredImages + return imageList, nil } -// FilterByReference filters images using references given in `filters`. -func FilterByReference(imageList []images.Image, filters []string) ([]images.Image, error) { - var filteredImageList []images.Image - log.L.Debug(filters) - for _, image := range imageList { - log.L.Debug(image.Name) - var matches int - for _, f := range filters { - var ref distributionref.Reference - var err error - ref, err = distributionref.ParseAnyReference(image.Name) +// FilterByCreatedAt filters an image list to images created before MAX(before..CreatedAt) +// and after MIN(since..CreatedAt). +func FilterByCreatedAt(ctx context.Context, client *containerd.Client, before []string, since []string) Filter { + return func(imageList []images.Image) ([]images.Image, error) { + var ( + minTime = time.Date(1970, time.Month(1), 1, 0, 0, 0, 0, time.UTC) + maxTime = time.Now() + ) + + imageStore := client.ImageService() + if len(before) > 0 { + beforeImages, err := imageStore.List(ctx, before...) if err != nil { - return nil, fmt.Errorf("unable to parse image name: %s while filtering by reference because of %s", image.Name, err.Error()) + return []images.Image{}, err } + maxTime = beforeImages[0].CreatedAt + for _, image := range beforeImages { + if image.CreatedAt.After(maxTime) { + maxTime = image.CreatedAt + } + } + } - familiarMatch, err := distributionref.FamiliarMatch(f, ref) + if len(since) > 0 { + sinceImages, err := imageStore.List(ctx, since...) if err != nil { - return nil, err + return []images.Image{}, err } - regexpMatch, err := regexp.MatchString(f, image.Name) + minTime = sinceImages[0].CreatedAt + for _, image := range sinceImages { + if image.CreatedAt.Before(minTime) { + minTime = image.CreatedAt + } + } + } + + return filter(imageList, func(i images.Image) (bool, error) { + return imageCreatedBetween(i, minTime, maxTime), nil + }) + } +} + +// FilterByLabel filters an image list based on labels applied to the image's config specification for the platform. +// Any matching label will include the image in the list. +func FilterByLabel(ctx context.Context, client *containerd.Client, labels map[string]string) Filter { + return func(imageList []images.Image) ([]images.Image, error) { + return filter(imageList, func(i images.Image) (bool, error) { + clientImage := containerd.NewImage(client, i) + imageCfg, _, err := ReadImageConfig(ctx, clientImage) if err != nil { - return nil, err + return false, err } - if familiarMatch || regexpMatch { + return matchesAllLabels(imageCfg.Config.Labels, labels), nil + }) + } +} + +// FilterByReference filters an image list based on +// matching the provided reference patterns +func FilterByReference(referencePatterns []string) Filter { + return func(imageList []images.Image) ([]images.Image, error) { + return filter(imageList, func(i images.Image) (bool, error) { + return matchesReferences(i, referencePatterns) + }) + } +} + +// FilterDanglingImages filters an image list for dangling (untagged) images. +func FilterDanglingImages() Filter { + return func(imageList []images.Image) ([]images.Image, error) { + return filter(imageList, func(i images.Image) (bool, error) { + return isDangling(i), nil + }) + } +} + +// FilterTaggedImages filters an image list for tagged images. +func FilterTaggedImages() Filter { + return func(imageList []images.Image) ([]images.Image, error) { + return filter(imageList, func(i images.Image) (bool, error) { + return !isDangling(i), nil + }) + } +} + +func filter[T any](items []T, f func(item T) (bool, error)) ([]T, error) { + filteredItems := make([]T, 0, len(items)) + for _, item := range items { + ok, err := f(item) + if err != nil { + return []T{}, err + } else if ok { + filteredItems = append(filteredItems, item) + } + } + return filteredItems, nil +} + +func imageCreatedBetween(image images.Image, min time.Time, max time.Time) bool { + return image.CreatedAt.After(min) && image.CreatedAt.Before(max) +} + +func matchesAllLabels(imageCfgLabels map[string]string, filterLabels map[string]string) bool { + var matches int + for lk, lv := range filterLabels { + if val, ok := imageCfgLabels[lk]; ok { + if val == lv || lv == "" { matches++ } } - if matches == len(filters) { - filteredImageList = append(filteredImageList, image) - } } - return filteredImageList, nil + return matches == len(filterLabels) } -// FilterDangling filters dangling images (or keeps if `dangling` == false). -func FilterDangling(imageList []images.Image, dangling bool) []images.Image { - var filtered []images.Image - for _, image := range imageList { - _, tag := ParseRepoTag(image.Name) +func matchesReferences(image images.Image, referencePatterns []string) (bool, error) { + var matches int - if dangling && tag == "" { - filtered = append(filtered, image) + reference, err := distributionref.ParseAnyReference(image.Name) + if err != nil { + return false, err + } + + for _, pattern := range referencePatterns { + familiarMatch, err := distributionref.FamiliarMatch(pattern, reference) + if err != nil { + return false, err } - if !dangling && tag != "" { - filtered = append(filtered, image) + + regexpMatch, err := regexp.MatchString(pattern, image.Name) + if err != nil { + return false, err } - } - return filtered -} -// FilterByLabel filters images based on labels given in `filters`. -func FilterByLabel(ctx context.Context, client *containerd.Client, imageList []images.Image, filters map[string]string) ([]images.Image, error) { - for lk, lv := range filters { - var imageLabels []images.Image - for _, img := range imageList { - ci := containerd.NewImage(client, img) - cfg, _, err := ReadImageConfig(ctx, ci) - if err != nil { - return nil, err - } - if val, ok := cfg.Config.Labels[lk]; ok { - if val == lv || lv == "" { - imageLabels = append(imageLabels, img) - } - } + if familiarMatch || regexpMatch { + matches++ } - imageList = imageLabels } - return imageList, nil + + return matches == len(referencePatterns), nil +} + +func isDangling(image images.Image) bool { + _, tag := ParseRepoTag(image.Name) + return tag == "" } diff --git a/pkg/imgutil/filtering_test.go b/pkg/imgutil/filtering_test.go new file mode 100644 index 00000000000..9ef4746ed41 --- /dev/null +++ b/pkg/imgutil/filtering_test.go @@ -0,0 +1,382 @@ +/* + 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 imgutil + +import ( + "testing" + "time" + + "github.com/containerd/containerd/v2/core/images" + "gotest.tools/v3/assert" +) + +func TestApplyFilters(t *testing.T) { + tests := []struct { + name string + images []images.Image + filters []Filter + expectedImages []images.Image + expectedErr error + }{ + { + name: "EmptyList", + images: []images.Image{}, + filters: []Filter{ + FilterDanglingImages(), + }, + expectedImages: []images.Image{}, + }, + { + name: "ApplyNoFilters", + images: []images.Image{ + { + Name: "", + }, + { + Name: "docker.io/library/hello-world:latest", + }, + }, + filters: []Filter{}, + expectedImages: []images.Image{ + { + Name: "", + }, + { + Name: "docker.io/library/hello-world:latest", + }, + }, + }, + { + name: "ApplySingleFilter", + images: []images.Image{ + { + Name: "", + }, + { + Name: "docker.io/library/hello-world:latest", + }, + }, + filters: []Filter{ + FilterDanglingImages(), + }, + expectedImages: []images.Image{ + { + Name: "", + }, + }, + }, + { + name: "ApplyMultipleFilters", + images: []images.Image{ + { + Name: "", + }, + { + Name: "alpine:3.19", + }, + { + Name: "docker.io/library/hello-world:latest", + }, + { + Name: "public.ecr.aws/docker/library/hello-world:latest", + }, + }, + filters: []Filter{ + FilterTaggedImages(), + FilterByReference([]string{"hello-world"}), + }, + expectedImages: []images.Image{ + { + Name: "docker.io/library/hello-world:latest", + }, + { + Name: "public.ecr.aws/docker/library/hello-world:latest", + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actualImages, err := ApplyFilters(test.images, test.filters...) + if test.expectedErr == nil { + assert.NilError(t, err) + } else { + assert.ErrorIs(t, err, test.expectedErr) + } + assert.Equal(t, len(actualImages), len(test.expectedImages)) + assert.DeepEqual(t, actualImages, test.expectedImages) + }) + } +} + +func TestFilterByReference(t *testing.T) { + tests := []struct { + name string + referencePatterns []string + images []images.Image + expectedImages []images.Image + expectedErr error + }{ + { + name: "EmptyList", + images: []images.Image{}, + expectedImages: []images.Image{}, + }, + { + name: "MatchByReference", + images: []images.Image{ + { + Name: "foo:latest", + }, + { + Name: "docker.io/library/hello-world:latest", + }, + { + Name: "public.ecr.aws/docker/library/hello-world:latest", + }, + }, + referencePatterns: []string{"hello-world"}, + expectedImages: []images.Image{ + { + Name: "docker.io/library/hello-world:latest", + }, + { + Name: "public.ecr.aws/docker/library/hello-world:latest", + }, + }, + }, + { + name: "NoMatchExists", + images: []images.Image{ + { + Name: "foo:latest", + }, + { + Name: "docker.io/library/hello-world:latest", + }, + { + Name: "public.ecr.aws/docker/library/hello-world:latest", + }, + }, + referencePatterns: []string{"foobar"}, + expectedImages: []images.Image{}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actualImages, err := FilterByReference(test.referencePatterns)(test.images) + if test.expectedErr == nil { + assert.NilError(t, err) + } else { + assert.ErrorIs(t, err, test.expectedErr) + } + assert.Equal(t, len(actualImages), len(test.expectedImages)) + assert.DeepEqual(t, actualImages, test.expectedImages) + }) + } +} + +func TestFilterDanglingImages(t *testing.T) { + tests := []struct { + name string + dangling bool + images []images.Image + expectedImages []images.Image + }{ + { + name: "EmptyList", + dangling: true, + images: []images.Image{}, + expectedImages: []images.Image{}, + }, + { + name: "IsDangling", + dangling: true, + images: []images.Image{ + { + Name: "", + Labels: map[string]string{"ref": "dangling1"}, + }, + { + Name: "docker.io/library/hello-world:latest", + }, + { + Name: "", + Labels: map[string]string{"ref": "dangling2"}, + }, + }, + expectedImages: []images.Image{ + { + Name: "", + Labels: map[string]string{"ref": "dangling1"}, + }, + { + Name: "", + Labels: map[string]string{"ref": "dangling2"}, + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actualImages, err := FilterDanglingImages()(test.images) + assert.NilError(t, err) + assert.Equal(t, len(actualImages), len(test.expectedImages)) + assert.DeepEqual(t, actualImages, test.expectedImages) + }) + } +} + +func TestFilterTaggedImages(t *testing.T) { + tests := []struct { + name string + dangling bool + images []images.Image + expectedImages []images.Image + }{ + { + name: "EmptyList", + dangling: true, + images: []images.Image{}, + expectedImages: []images.Image{}, + }, + { + name: "IsTagged", + dangling: true, + images: []images.Image{ + { + Name: "", + Labels: map[string]string{"ref": "dangling1"}, + }, + { + Name: "docker.io/library/hello-world:latest", + }, + { + Name: "", + Labels: map[string]string{"ref": "dangling2"}, + }, + }, + expectedImages: []images.Image{ + { + Name: "docker.io/library/hello-world:latest", + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actualImages, err := FilterTaggedImages()(test.images) + assert.NilError(t, err) + assert.Equal(t, len(actualImages), len(test.expectedImages)) + assert.DeepEqual(t, actualImages, test.expectedImages) + }) + } +} + +func TestImageCreatedBetween(t *testing.T) { + tests := []struct { + name string + image images.Image + lhs time.Time + rhs time.Time + fallsBetween bool + }{ + { + name: "BetweenImage", + image: images.Image{ + CreatedAt: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), + }, + lhs: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC), + rhs: time.Now(), + fallsBetween: true, + }, + { + name: "ExclusiveLeft", + image: images.Image{ + CreatedAt: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC), + }, + lhs: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC), + rhs: time.Now(), + fallsBetween: false, + }, + { + name: "ExclusiveRight", + image: images.Image{ + CreatedAt: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), + }, + lhs: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC), + rhs: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), + fallsBetween: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, imageCreatedBetween(test.image, test.lhs, test.rhs), test.fallsBetween) + }) + } +} + +func TestMatchesAnyLabel(t *testing.T) { + tests := []struct { + name string + imageLabels map[string]string + labelsToMatch map[string]string + matches bool + }{ + { + name: "ImageHasNoLabels", + imageLabels: map[string]string{}, + labelsToMatch: map[string]string{"foo": "bar"}, + matches: false, + }, + { + name: "SingleMatchingLabel", + imageLabels: map[string]string{"org": "com.containerd.nerdctl"}, + labelsToMatch: map[string]string{"org": "com.containerd.nerdctl"}, + matches: true, + }, + { + name: "KeyOnlyMatchingLabel", + imageLabels: map[string]string{"org": "com.containerd.nerdctl"}, + labelsToMatch: map[string]string{"org": ""}, + matches: true, + }, + { + name: "KeyValueDoesNotMatch", + imageLabels: map[string]string{"org": "com.containerd.nerdctl"}, + labelsToMatch: map[string]string{"org": "com.containerd.containerd"}, + matches: false, + }, + { + name: "AllMatchingLabel", + imageLabels: map[string]string{"org": "com.containerd.nerdctl", "foo": "bar"}, + labelsToMatch: map[string]string{"org": "com.containerd.containerd", "foo": "bar"}, + matches: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, matchesAllLabels(test.imageLabels, test.labelsToMatch), test.matches) + }) + } +} From 7c9751e257f9ea88600e7df9638b8305ee804193 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Sat, 17 Aug 2024 04:30:05 +0000 Subject: [PATCH 0654/1066] Add image prune --filter support Signed-off-by: Austin Vazquez --- cmd/nerdctl/image_prune.go | 10 +++ cmd/nerdctl/image_prune_test.go | 55 +++++++++++++ docs/command-reference.md | 5 +- pkg/api/types/image_types.go | 2 + pkg/cmd/image/prune.go | 50 ++++++----- pkg/imgutil/filtering.go | 71 ++++++++++++++++ pkg/imgutil/filtering_test.go | 142 ++++++++++++++++++++++++++++---- pkg/imgutil/imgutil.go | 49 +++++++++++ 8 files changed, 339 insertions(+), 45 deletions(-) diff --git a/cmd/nerdctl/image_prune.go b/cmd/nerdctl/image_prune.go index 56dd8797f1a..4508efaaa10 100644 --- a/cmd/nerdctl/image_prune.go +++ b/cmd/nerdctl/image_prune.go @@ -38,6 +38,7 @@ func newImagePruneCommand() *cobra.Command { } imagePruneCommand.Flags().BoolP("all", "a", false, "Remove all unused images, not just dangling ones") + imagePruneCommand.Flags().StringSlice("filter", []string{}, "Filter output based on conditions provided") imagePruneCommand.Flags().BoolP("force", "f", false, "Do not prompt for confirmation") return imagePruneCommand } @@ -52,6 +53,14 @@ func processImagePruneOptions(cmd *cobra.Command) (types.ImagePruneOptions, erro return types.ImagePruneOptions{}, err } + var filters []string + if cmd.Flags().Changed("filter") { + filters, err = cmd.Flags().GetStringSlice("filter") + if err != nil { + return types.ImagePruneOptions{}, err + } + } + force, err := cmd.Flags().GetBool("force") if err != nil { return types.ImagePruneOptions{}, err @@ -61,6 +70,7 @@ func processImagePruneOptions(cmd *cobra.Command) (types.ImagePruneOptions, erro Stdout: cmd.OutOrStdout(), GOptions: globalOptions, All: all, + Filters: filters, Force: force, }, err } diff --git a/cmd/nerdctl/image_prune_test.go b/cmd/nerdctl/image_prune_test.go index e2babfbde24..0f9f423a4d7 100644 --- a/cmd/nerdctl/image_prune_test.go +++ b/cmd/nerdctl/image_prune_test.go @@ -19,6 +19,7 @@ package main import ( "fmt" "testing" + "time" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -71,3 +72,57 @@ func TestImagePruneAll(t *testing.T) { base.Cmd("image", "prune", "--force", "--all").AssertOutContains(imageName) base.Cmd("images").AssertOutNotContains(imageName) } + +func TestImagePruneFilterLabel(t *testing.T) { + testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) + + base := testutil.NewBase(t) + imageName := testutil.Identifier(t) + t.Cleanup(func() { base.Cmd("rmi", "--force", imageName) }) + + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-test-image-prune-filter-label"] +LABEL foo=bar +LABEL version=0.1`, testutil.CommonImage) + + buildCtx := createBuildContext(t, dockerfile) + + base.Cmd("build", "-t", imageName, buildCtx).AssertOK() + base.Cmd("images", "--all").AssertOutContains(imageName) + + base.Cmd("image", "prune", "--force", "--all", "--filter", "label=foo=baz").AssertOK() + base.Cmd("images", "--all").AssertOutContains(imageName) + + base.Cmd("image", "prune", "--force", "--all", "--filter", "label=foo=bar").AssertOK() + base.Cmd("images", "--all").AssertOutNotContains(imageName) +} + +func TestImagePruneFilterUntil(t *testing.T) { + testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) + + // Docker image's created timestamp is set based on base image creation time. + testutil.DockerIncompatible(t) + + base := testutil.NewBase(t) + imageName := testutil.Identifier(t) + t.Cleanup(func() { base.Cmd("rmi", "--force", imageName) }) + + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-test-image-prune-filter-until"]`, testutil.CommonImage) + + buildCtx := createBuildContext(t, dockerfile) + + base.Cmd("build", "-t", imageName, buildCtx).AssertOK() + base.Cmd("images", "--all").AssertOutContains(imageName) + + base.Cmd("image", "prune", "--force", "--all", "--filter", "until=12h").AssertOK() + base.Cmd("images", "--all").AssertOutContains(imageName) + + // Pause to ensure enough time has passed for the image to be cleaned on next prune. + time.Sleep(3 * time.Second) + + base.Cmd("image", "prune", "--force", "--all", "--filter", "until=10ms").AssertOK() + base.Cmd("images", "--all").AssertOutNotContains(imageName) +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 9106aa76397..4508b65f8c8 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -886,10 +886,11 @@ Usage: `nerdctl image prune [OPTIONS]` Flags: - :whale: `-a, --all`: Remove all unused images, not just dangling ones +- :whale: `-f, --filter`: Filter the images. + - :whale: `--filter=until=`: Images created before given date formatted timestamps or Go duration strings. Currently does not support Unix timestamps. + - :whale: `--filter=label=`: Matches images based on the presence of a label alone or a label and a value - :whale: `-f, --force`: Do not prompt for confirmation -Unimplemented `docker image prune` flags: `--filter` - ### :nerd_face: nerdctl image convert Convert an image format. diff --git a/pkg/api/types/image_types.go b/pkg/api/types/image_types.go index 40015e8a24c..30e0d65c31c 100644 --- a/pkg/api/types/image_types.go +++ b/pkg/api/types/image_types.go @@ -236,6 +236,8 @@ type ImagePruneOptions struct { GOptions GlobalCommandOptions // All Remove all unused images, not just dangling ones. All bool + // Filters output based on conditions provided for the --filter argument + Filters []string // Force will not prompt for confirmation. Force bool } diff --git a/pkg/cmd/image/prune.go b/pkg/cmd/image/prune.go index 159d2d6c8b1..da29fbdb486 100644 --- a/pkg/cmd/image/prune.go +++ b/pkg/cmd/image/prune.go @@ -34,45 +34,43 @@ import ( // Prune will remove all dangling images. If all is specified, will also remove all images not referenced by any container. func Prune(ctx context.Context, client *containerd.Client, options types.ImagePruneOptions) error { var ( - imageStore = client.ImageService() - contentStore = client.ContentStore() - containerStore = client.ContainerService() + imageStore = client.ImageService() + contentStore = client.ContentStore() ) - imageList, err := imageStore.List(ctx) - if err != nil { - return err - } - - var filteredImages []images.Image + var ( + imagesToBeRemoved []images.Image + err error + ) - if options.All { - containerList, err := containerStore.List(ctx) + filters := []imgutil.Filter{} + if len(options.Filters) > 0 { + parsedFilters, err := imgutil.ParseFilters(options.Filters) if err != nil { return err } - usedImages := make(map[string]struct{}) - for _, container := range containerList { - usedImages[container.Image] = struct{}{} + if len(parsedFilters.Labels) > 0 { + filters = append(filters, imgutil.FilterByLabel(ctx, client, parsedFilters.Labels)) } - - for _, image := range imageList { - if _, ok := usedImages[image.Name]; ok { - continue - } - - filteredImages = append(filteredImages, image) + if len(parsedFilters.Until) > 0 { + filters = append(filters, imgutil.FilterUntil(parsedFilters.Until)) } + } + + if options.All { + // Remove all unused images; not just dangling ones + imagesToBeRemoved, err = imgutil.GetUnusedImages(ctx, client, filters...) } else { - filteredImages, err = imgutil.FilterDanglingImages()(imageList) - if err != nil { - return err - } + // Remove dangling images only + imagesToBeRemoved, err = imgutil.GetDanglingImages(ctx, client, filters...) + } + if err != nil { + return err } delOpts := []images.DeleteOpt{images.SynchronousDelete()} removedImages := make(map[string][]digest.Digest) - for _, image := range filteredImages { + for _, image := range imagesToBeRemoved { digests, err := image.RootFS(ctx, contentStore, platforms.DefaultStrict()) if err != nil { log.G(ctx).WithError(err).Warnf("failed to enumerate rootfs") diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index fa35a909970..05d178a4fe5 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -18,6 +18,7 @@ package imgutil import ( "context" + "errors" "fmt" "regexp" "strings" @@ -35,15 +36,23 @@ import ( const ( FilterBeforeType = "before" FilterSinceType = "since" + FilterUntilType = "until" FilterLabelType = "label" FilterReferenceType = "reference" FilterDanglingType = "dangling" ) +var ( + errMultipleUntilFilters = errors.New("more than one until filter provided") + errNoUntilTimestamp = errors.New("no until timestamp provided") + errUnparsableUntilTimestamp = errors.New("unable to parse until timestamp") +) + // Filters contains all types of filters to filter images. type Filters struct { Before []string Since []string + Until string Labels map[string]string Reference []string Dangling *bool @@ -85,6 +94,13 @@ func ParseFilters(filters []string) (*Filters, error) { } f.Since = append(f.Since, fmt.Sprintf("name==%s", canonicalRef.String())) f.Since = append(f.Since, fmt.Sprintf("name==%s", tempFilterToken[1])) + } else if tempFilterToken[0] == FilterUntilType { + if len(tempFilterToken[0]) == 0 { + return nil, errNoUntilTimestamp + } else if len(f.Until) > 0 { + return nil, errMultipleUntilFilters + } + f.Until = tempFilterToken[1] } else if tempFilterToken[0] == FilterLabelType { // To support filtering labels by keys. f.Labels[tempFilterToken[1]] = "" @@ -161,6 +177,57 @@ func FilterByCreatedAt(ctx context.Context, client *containerd.Client, before [] } } +// FilterUntil filters images created before the provided timestamp. +func FilterUntil(until string) Filter { + return func(imageList []images.Image) ([]images.Image, error) { + if len(until) == 0 { + return []images.Image{}, errNoUntilTimestamp + } + + var ( + parsedTime time.Time + err error + ) + + type parseUntilFunc func(string) (time.Time, error) + parsingFuncs := []parseUntilFunc{ + func(until string) (time.Time, error) { + return time.Parse(time.RFC3339, until) + }, + func(until string) (time.Time, error) { + return time.Parse(time.RFC3339Nano, until) + }, + func(until string) (time.Time, error) { + return time.Parse(time.DateOnly, until) + }, + func(until string) (time.Time, error) { + // Go duration strings + d, err := time.ParseDuration(until) + if err != nil { + return time.Time{}, err + } + return time.Now().Add(-d), nil + }, + } + + for _, parse := range parsingFuncs { + parsedTime, err = parse(until) + if err != nil { + continue + } + break + } + + if err != nil { + return []images.Image{}, errUnparsableUntilTimestamp + } + + return filter(imageList, func(i images.Image) (bool, error) { + return imageCreatedBefore(i, parsedTime), nil + }) + } +} + // FilterByLabel filters an image list based on labels applied to the image's config specification for the platform. // Any matching label will include the image in the list. func FilterByLabel(ctx context.Context, client *containerd.Client, labels map[string]string) Filter { @@ -221,6 +288,10 @@ func imageCreatedBetween(image images.Image, min time.Time, max time.Time) bool return image.CreatedAt.After(min) && image.CreatedAt.Before(max) } +func imageCreatedBefore(image images.Image, max time.Time) bool { + return image.CreatedAt.Before(max) +} + func matchesAllLabels(imageCfgLabels map[string]string, filterLabels map[string]string) bool { var matches int for lk, lv := range filterLabels { diff --git a/pkg/imgutil/filtering_test.go b/pkg/imgutil/filtering_test.go index 9ef4746ed41..70125ee6012 100644 --- a/pkg/imgutil/filtering_test.go +++ b/pkg/imgutil/filtering_test.go @@ -108,6 +108,23 @@ func TestApplyFilters(t *testing.T) { }, }, }, + { + name: "ReturnErrorAndEmptyListOnFilterError", + images: []images.Image{ + { + Name: ":", + }, + { + Name: "docker.io/library/hello-world:latest", + }, + }, + filters: []Filter{ + FilterDanglingImages(), + FilterUntil(""), + }, + expectedImages: []images.Image{}, + expectedErr: errNoUntilTimestamp, + }, } for _, test := range tests { @@ -124,6 +141,74 @@ func TestApplyFilters(t *testing.T) { } } +func TestFilterUntil(t *testing.T) { + now := time.Now().UTC() + + tests := []struct { + name string + until string + images []images.Image + expectedImages []images.Image + expectedErr error + }{ + { + name: "EmptyTimestampReturnsError", + until: "", + images: []images.Image{}, + expectedImages: []images.Image{}, + expectedErr: errNoUntilTimestamp, + }, + { + name: "UnparseableTimestampReturnsError", + until: "-2006-01-02T15:04:05Z07:00", + images: []images.Image{}, + expectedImages: []images.Image{}, + expectedErr: errUnparsableUntilTimestamp, + }, + { + name: "ImagesOlderThan3Hours(Go duration)", + until: "3h", + images: []images.Image{ + { + Name: "image:yesterday", + CreatedAt: now.Add(-24 * time.Hour), + }, + { + Name: "image:today", + CreatedAt: now.Add(-12 * time.Hour), + }, + { + Name: "image:latest", + CreatedAt: now, + }, + }, + expectedImages: []images.Image{ + { + Name: "image:yesterday", + CreatedAt: now.Add(-24 * time.Hour), + }, + { + Name: "image:today", + CreatedAt: now.Add(-12 * time.Hour), + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actualImages, err := FilterUntil(test.until)(test.images) + if test.expectedErr == nil { + assert.NilError(t, err) + } else { + assert.ErrorIs(t, err, test.expectedErr) + } + assert.Equal(t, len(actualImages), len(test.expectedImages)) + assert.DeepEqual(t, actualImages, test.expectedImages) + }) + } +} + func TestFilterByReference(t *testing.T) { tests := []struct { name string @@ -292,6 +377,11 @@ func TestFilterTaggedImages(t *testing.T) { } func TestImageCreatedBetween(t *testing.T) { + var ( + unixEpoch = time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC) + y2k = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC) + now = time.Now() + ) tests := []struct { name string image images.Image @@ -300,30 +390,48 @@ func TestImageCreatedBetween(t *testing.T) { fallsBetween bool }{ { - name: "BetweenImage", + name: "PreviousImage", + image: images.Image{ + CreatedAt: unixEpoch, + }, + lhs: y2k, + rhs: now, + fallsBetween: false, + }, + { + name: "AfterImage", + image: images.Image{ + CreatedAt: now, + }, + lhs: unixEpoch, + rhs: y2k, + fallsBetween: false, + }, + { + name: "InBetweenTimeImage", image: images.Image{ - CreatedAt: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), + CreatedAt: y2k, }, - lhs: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC), - rhs: time.Now(), + lhs: unixEpoch, + rhs: now, fallsBetween: true, }, { name: "ExclusiveLeft", image: images.Image{ - CreatedAt: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC), + CreatedAt: unixEpoch, }, - lhs: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC), - rhs: time.Now(), + lhs: unixEpoch, + rhs: now, fallsBetween: false, }, { name: "ExclusiveRight", image: images.Image{ - CreatedAt: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), + CreatedAt: now, }, - lhs: time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC), - rhs: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), + lhs: unixEpoch, + rhs: now, fallsBetween: false, }, } @@ -350,26 +458,26 @@ func TestMatchesAnyLabel(t *testing.T) { }, { name: "SingleMatchingLabel", - imageLabels: map[string]string{"org": "com.containerd.nerdctl"}, - labelsToMatch: map[string]string{"org": "com.containerd.nerdctl"}, + imageLabels: map[string]string{"org": "com.example.nerdctl"}, + labelsToMatch: map[string]string{"org": "com.example.nerdctl"}, matches: true, }, { name: "KeyOnlyMatchingLabel", - imageLabels: map[string]string{"org": "com.containerd.nerdctl"}, + imageLabels: map[string]string{"org": "com.example.nerdctl"}, labelsToMatch: map[string]string{"org": ""}, matches: true, }, { name: "KeyValueDoesNotMatch", - imageLabels: map[string]string{"org": "com.containerd.nerdctl"}, - labelsToMatch: map[string]string{"org": "com.containerd.containerd"}, + imageLabels: map[string]string{"org": "com.example.nerdctl"}, + labelsToMatch: map[string]string{"org": "com.example.containerd"}, matches: false, }, { name: "AllMatchingLabel", - imageLabels: map[string]string{"org": "com.containerd.nerdctl", "foo": "bar"}, - labelsToMatch: map[string]string{"org": "com.containerd.containerd", "foo": "bar"}, + imageLabels: map[string]string{"org": "com.example.nerdctl", "foo": "bar"}, + labelsToMatch: map[string]string{"org": "com.example.containerd", "foo": "bar"}, matches: false, }, } diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 5406e83858d..3b042c9fb63 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -423,3 +423,52 @@ func UnpackedImageSize(ctx context.Context, s snapshots.Snapshotter, img contain return total.Size, err } + +// GetUnusedImages returns the list of all images which are not referenced by a container. +func GetUnusedImages(ctx context.Context, client *containerd.Client, filters ...Filter) ([]images.Image, error) { + var ( + imageStore = client.ImageService() + containerStore = client.ContainerService() + ) + + containers, err := containerStore.List(ctx) + if err != nil { + return []images.Image{}, err + } + + usedImages := make(map[string]struct{}) + for _, container := range containers { + usedImages[container.Image] = struct{}{} + } + + allImages, err := imageStore.List(ctx) + if err != nil { + return []images.Image{}, err + } + + unusedImages := make([]images.Image, 0, len(allImages)) + for _, image := range allImages { + if _, ok := usedImages[image.Name]; ok { + continue + } + unusedImages = append(unusedImages, image) + } + + return ApplyFilters(unusedImages, filters...) +} + +// GetDanglingImages returns the list of all images which are not tagged. +func GetDanglingImages(ctx context.Context, client *containerd.Client, filters ...Filter) ([]images.Image, error) { + var ( + imageStore = client.ImageService() + ) + + allImages, err := imageStore.List(ctx) + if err != nil { + return []images.Image{}, err + } + + filters = append([]Filter{FilterDanglingImages()}, filters...) + + return ApplyFilters(allImages, filters...) +} From fd0f9547e2718c32d45c6bd0f4f768cc7eeea910 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 17 Aug 2024 11:13:56 -0700 Subject: [PATCH 0655/1066] Add lint job for canary and minor shell script cleanup Signed-off-by: apostasie --- .github/workflows/test-canary.yml | 55 ++++----- .github/workflows/test.yml | 2 +- hack/build-integration-canary.sh | 187 +++++++++++++++++------------- hack/scripts/lib.sh | 3 +- 4 files changed, 139 insertions(+), 108 deletions(-) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 05a975f37ae..e106c94ce7a 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -15,6 +15,27 @@ env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: + lint: + runs-on: "ubuntu-24.04" + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4.1.7 + with: + fetch-depth: 1 + - name: Set GO env + run: | + . ./hack/build-integration-canary.sh + canary::golang::latest + - uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + check-latest: true + cache: true + - name: golangci-lint + uses: golangci/golangci-lint-action@v6.1.0 + with: + args: --verbose + linux: runs-on: "ubuntu-24.04" timeout-minutes: 40 @@ -24,7 +45,8 @@ jobs: fetch-depth: 1 - name: "Prepare integration test environment" run: | - ./hack/build-integration-canary.sh + . ./hack/build-integration-canary.sh + canary::build::integration - name: "Remove snap loopback devices (conflicts with our loopback devices in TestRunDevice)" run: | sudo systemctl disable --now snapd.service snapd.socket @@ -53,40 +75,21 @@ jobs: run: shell: bash steps: + - uses: actions/checkout@v4.1.7 + with: + fetch-depth: 1 - name: Set GO env run: | - # Enable extended globbing features to use advanced pattern matching - shopt -s extglob - # Get latest containerd args=(curl --proto '=https' --tlsv1.2 -fsSL -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28") [ "${GITHUB_TOKEN:-}" == "" ] && { >&2 printf "GITHUB_TOKEN is not set - you might face rate limitations with the Github API\n" } || args+=(-H "Authorization: Bearer $GITHUB_TOKEN") ctd_v="$("${args[@]}" https://api.github.com/repos/containerd/containerd/tags | jq -rc .[0].name)" - echo "CONTAINERD_VERSION=${ctd_v:1}" >> $GITHUB_ENV - - # Get latest golang version and split it in components - norm=() - while read -r line; do - line_trimmed="${line//+([[:space:]])/}" - norm+=("$line_trimmed") - done < \ - <(sed -E 's/^go([0-9]+)[.]([0-9]+)([.]([0-9]+))?(([a-z]+)([0-9]+))?/\1.\2\n\4\n\6\n\7/i' \ - <(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version) \ - ) + echo "CONTAINERD_VERSION=${ctd_v:1}" >> "$GITHUB_ENV" - # Serialize version, making sure we have a patch version, and separate possible rcX into .rc-X - [ "${norm[1]}" != "" ] || norm[1]="0" - norm[1]=".${norm[1]}" - [ "${norm[2]}" == "" ] || norm[2]="-${norm[2]}" - [ "${norm[3]}" == "" ] || norm[3]=".${norm[3]}" - # Save it - IFS= - echo "GO_VERSION=${norm[*]}" >> $GITHUB_ENV - - uses: actions/checkout@v4.1.7 - with: - fetch-depth: 1 + . ./hack/build-integration-canary.sh + canary::golang::latest - uses: actions/setup-go@v5 with: go-version: ${{ env.GO_VERSION }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 10da7bca6f0..b4c372c3b29 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -222,7 +222,7 @@ jobs: if echo "${ROOTLESSKIT_VERSION}" | grep -q v1; then WORKAROUND_ISSUE_622=1 fi - echo "WORKAROUND_ISSUE_622=${WORKAROUND_ISSUE_622}" >>$GITHUB_ENV + echo "WORKAROUND_ISSUE_622=${WORKAROUND_ISSUE_622}" >> "$GITHUB_ENV" - name: "Test (network driver=slirp4netns, port driver=builtin)" uses: nick-fields/retry@v3 with: diff --git a/hack/build-integration-canary.sh b/hack/build-integration-canary.sh index 4a75a0d427b..4718e3adde1 100755 --- a/hack/build-integration-canary.sh +++ b/hack/build-integration-canary.sh @@ -215,91 +215,118 @@ assets::get(){ # Script ###################### -docker_args=(docker build -t test-integration --target test-integration) - -for dep in "${dependencies[@]}"; do - shortname="${dep##*/}" - [ "$shortname" != "plugins" ] || shortname="cni-plugins" - [ "$shortname" != "fuse-overlayfs-snapshotter" ] || shortname="containerd-fuse-overlayfs" - for bl in "${blacklist[@]}"; do - if [ "$bl" == "$shortname" ]; then - log::warning "Dependency $shortname is blacklisted and will be left to its currently pinned version" - break - fi - done - [ "$bl" != "$shortname" ] || continue - - shortsafename="$(printf "%s" "$shortname" | tr '[:lower:]' '[:upper:]' | tr '-' '_')" - - exclusion="${shortsafename}_EXCLUDE" - latest::release "$dep" "${!exclusion:-}" - - # XXX containerd does not display "v" in its released versions - [ "${higher_readable:0:1}" == v ] || higher_readable="v$higher_readable" - - checksum="${shortsafename}_CHECKSUM" - if [ "${!checksum:-}" != "" ]; then - # Checksum file - checksum_file=./Dockerfile.d/SHA256SUMS.d/"${shortname}-${higher_readable}" - if [ ! -e "$checksum_file" ]; then - # Get assets - try first os/arch - fallback on gnu style arch otherwise - assets=() - - # Most well behaved go projects will tag with a go os and arch - candidate="$(assets::get "${!checksum:-}" "amd64")" - # Then non go projects tend to use gnu style - [ "$candidate" != "" ] || candidate="$(assets::get "" "x86_64")" - # And then some projects which are linux only do not specify the OS - [ "$candidate" != "" ] || candidate="$(assets::get "" "amd64")" - [ "$candidate" == "" ] || assets+=("$candidate") - - candidate="$(assets::get "${!checksum:-}" "arm64")" - [ "$candidate" != "" ] || candidate="$(assets::get "" "aarch64")" - [ "$candidate" != "" ] || candidate="$(assets::get "" "arm64")" - [ "$candidate" == "" ] || assets+=("$candidate") - # Fallback to source if there is nothing else - - [ "${#assets[@]}" != 0 ] || candidate="$(assets::get "" "source")" - [ "$candidate" == "" ] || assets+=("$candidate") - - # XXX very special... - if [ "$shortsafename" == "STARGZ_SNAPSHOTTER" ]; then - assets+=("https://raw.githubusercontent.com/containerd/stargz-snapshotter/${higher_readable}/script/config/etc/systemd/system/stargz-snapshotter.service") +canary::build::integration(){ + docker_args=(docker build -t test-integration --target test-integration) + + for dep in "${dependencies[@]}"; do + shortname="${dep##*/}" + [ "$shortname" != "plugins" ] || shortname="cni-plugins" + [ "$shortname" != "fuse-overlayfs-snapshotter" ] || shortname="containerd-fuse-overlayfs" + for bl in "${blacklist[@]}"; do + if [ "$bl" == "$shortname" ]; then + log::warning "Dependency $shortname is blacklisted and will be left to its currently pinned version" + break fi - - # Write the checksum for what we found - if [ "${#assets[@]}" == 0 ]; then - log::error "No asset found for this checksum-able dependency. Dropping off." - exit 1 + done + [ "$bl" != "$shortname" ] || continue + + shortsafename="$(printf "%s" "$shortname" | tr '[:lower:]' '[:upper:]' | tr '-' '_')" + + exclusion="${shortsafename}_EXCLUDE" + latest::release "$dep" "${!exclusion:-}" + + # XXX containerd does not display "v" in its released versions + [ "${higher_readable:0:1}" == v ] || higher_readable="v$higher_readable" + + checksum="${shortsafename}_CHECKSUM" + if [ "${!checksum:-}" != "" ]; then + # Checksum file + checksum_file=./Dockerfile.d/SHA256SUMS.d/"${shortname}-${higher_readable}" + if [ ! -e "$checksum_file" ]; then + # Get assets - try first os/arch - fallback on gnu style arch otherwise + assets=() + + # Most well behaved go projects will tag with a go os and arch + candidate="$(assets::get "${!checksum:-}" "amd64")" + # Then non go projects tend to use gnu style + [ "$candidate" != "" ] || candidate="$(assets::get "" "x86_64")" + # And then some projects which are linux only do not specify the OS + [ "$candidate" != "" ] || candidate="$(assets::get "" "amd64")" + [ "$candidate" == "" ] || assets+=("$candidate") + + candidate="$(assets::get "${!checksum:-}" "arm64")" + [ "$candidate" != "" ] || candidate="$(assets::get "" "aarch64")" + [ "$candidate" != "" ] || candidate="$(assets::get "" "arm64")" + [ "$candidate" == "" ] || assets+=("$candidate") + # Fallback to source if there is nothing else + + [ "${#assets[@]}" != 0 ] || candidate="$(assets::get "" "source")" + [ "$candidate" == "" ] || assets+=("$candidate") + + # XXX very special... + if [ "$shortsafename" == "STARGZ_SNAPSHOTTER" ]; then + assets+=("https://raw.githubusercontent.com/containerd/stargz-snapshotter/${higher_readable}/script/config/etc/systemd/system/stargz-snapshotter.service") + fi + + # Write the checksum for what we found + if [ "${#assets[@]}" == 0 ]; then + log::error "No asset found for this checksum-able dependency. Dropping off." + exit 1 + fi + http::checksum "${assets[@]}" > "$checksum_file" fi - http::checksum "${assets[@]}" > "$checksum_file" fi - fi - while read -r line; do - # Extract value after "=" from a possible dockerfile `ARG XXX_VERSION` - old_version=$(echo "$line" | grep "ARG ${shortsafename}_VERSION=") || true - old_version="${old_version##*=}" - [ "$old_version" != "" ] || continue - # If the Dockerfile version does NOT start with a v, adapt to that - [ "${old_version:0:1}" == "v" ] || higher_readable="${higher_readable:1}" - - if [ "$old_version" != "$higher_readable" ]; then - log::warning "Dependency ${shortsafename} is going to use an updated version $higher_readable (currently: $old_version)" - fi - done < ./Dockerfile + while read -r line; do + # Extract value after "=" from a possible dockerfile `ARG XXX_VERSION` + old_version=$(echo "$line" | grep "ARG ${shortsafename}_VERSION=") || true + old_version="${old_version##*=}" + [ "$old_version" != "" ] || continue + # If the Dockerfile version does NOT start with a v, adapt to that + [ "${old_version:0:1}" == "v" ] || higher_readable="${higher_readable:1}" - docker_args+=(--build-arg "${shortsafename}_VERSION=$higher_readable") -done + if [ "$old_version" != "$higher_readable" ]; then + log::warning "Dependency ${shortsafename} is going to use an updated version $higher_readable (currently: $old_version)" + fi + done < ./Dockerfile + + docker_args+=(--build-arg "${shortsafename}_VERSION=$higher_readable") + done -GO_VERSION="$(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version)" -GO_VERSION="${GO_VERSION##*go}" -# If a release candidate, docker hub may not have the corresponding image yet. -# So, soften the version to just "rc", as they provide that as an alias to the latest available rc on their side -# See https://github.com/containerd/nerdctl/issues/3223 -! grep -Eq "rc[0-9]+$" <<<"$GO_VERSION" || GO_VERSION="${GO_VERSION%rc[0-9]*}-rc" -docker_args+=(--build-arg "GO_VERSION=$GO_VERSION") + GO_VERSION="$(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version)" + GO_VERSION="${GO_VERSION##*go}" + # If a release candidate, docker hub may not have the corresponding image yet. + # So, soften the version to just "rc", as they provide that as an alias to the latest available rc on their side + # See https://github.com/containerd/nerdctl/issues/3223 + ! grep -Eq "rc[0-9]+$" <<<"$GO_VERSION" || GO_VERSION="${GO_VERSION%rc[0-9]*}-rc" + docker_args+=(--build-arg "GO_VERSION=$GO_VERSION") + + log::debug "${docker_args[*]} ." + "${docker_args[@]}" "." +} + -log::debug "${docker_args[*]} ." -"${docker_args[@]}" "." +canary::golang::latest(){ + # Enable extended globbing features to use advanced pattern matching + shopt -s extglob + + # Get latest golang version and split it in components + norm=() + while read -r line; do + line_trimmed="${line//+([[:space:]])/}" + norm+=("$line_trimmed") + done < \ + <(sed -E 's/^go([0-9]+)[.]([0-9]+)([.]([0-9]+))?(([a-z]+)([0-9]+))?/\1.\2\n\4\n\6\n\7/i' \ + <(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version) \ + ) + + # Serialize version, making sure we have a patch version, and separate possible rcX into .rc-X + [ "${norm[1]}" != "" ] || norm[1]="0" + norm[1]=".${norm[1]}" + [ "${norm[2]}" == "" ] || norm[2]="-${norm[2]}" + [ "${norm[3]}" == "" ] || norm[3]=".${norm[3]}" + # Save it + IFS= + echo "GO_VERSION=${norm[*]}" >> "$GITHUB_ENV" +} \ No newline at end of file diff --git a/hack/scripts/lib.sh b/hack/scripts/lib.sh index de0fa173bae..c29b056ea70 100755 --- a/hack/scripts/lib.sh +++ b/hack/scripts/lib.sh @@ -182,6 +182,8 @@ http::checksum(){ local temp temp="$(fs::mktemp "http-checksum")" + host::require shasum + for url in "${urls[@]}"; do http::get "$temp/${url##*/}" "$url" done @@ -233,4 +235,3 @@ log::init host::require jq host::require tar host::require curl -host::require shasum From 183b4395c5dbb88a386d337e551cd93e0f533b76 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 17 Aug 2024 11:26:41 -0700 Subject: [PATCH 0656/1066] Fix SA4032 (see https://staticcheck.dev/docs/checks#SA4032) Signed-off-by: apostasie --- cmd/nerdctl/compose_exec_linux_test.go | 7 +++---- cmd/nerdctl/container_create_linux_test.go | 4 ---- cmd/nerdctl/container_run_linux_test.go | 7 ------- cmd/nerdctl/image_convert_linux_test.go | 4 ---- 4 files changed, 3 insertions(+), 19 deletions(-) diff --git a/cmd/nerdctl/compose_exec_linux_test.go b/cmd/nerdctl/compose_exec_linux_test.go index 7805cb22dca..7a1ea165a54 100644 --- a/cmd/nerdctl/compose_exec_linux_test.go +++ b/cmd/nerdctl/compose_exec_linux_test.go @@ -20,7 +20,6 @@ import ( "errors" "fmt" "net" - "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/container_create_linux_test.go b/cmd/nerdctl/container_create_linux_test.go index fa4e65525ab..601326462b2 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" "strings" "testing" @@ -154,9 +153,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_run_linux_test.go b/cmd/nerdctl/container_run_linux_test.go index 87194131181..93e9de95d8f 100644 --- a/cmd/nerdctl/container_run_linux_test.go +++ b/cmd/nerdctl/container_run_linux_test.go @@ -26,7 +26,6 @@ import ( "net/http" "os" "path/filepath" - "runtime" "strconv" "strings" "syscall" @@ -400,9 +399,6 @@ func TestRunSigProxy(t *testing.T) { } func TestRunWithFluentdLogDriver(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) @@ -432,9 +428,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/image_convert_linux_test.go b/cmd/nerdctl/image_convert_linux_test.go index e3557f91fae..8022035d0c7 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" "gotest.tools/v3/icmd" @@ -29,9 +28,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) From 068866eef2b98e64e17780755592cb7d776073aa Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 17 Aug 2024 11:34:38 -0700 Subject: [PATCH 0657/1066] Fix S1009 (see https://staticcheck.dev/docs/checks#S1009) Signed-off-by: apostasie --- pkg/composer/run.go | 10 +++++----- pkg/containerutil/container_network_manager.go | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/composer/run.go b/pkg/composer/run.go index 87dbe5be9ec..82e3a347b52 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -129,7 +129,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 := format.ParseVolume(v) if err != nil { @@ -138,15 +138,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 { @@ -163,7 +163,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/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index b19169eb692..54fa8f7f2ae 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -198,7 +198,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:'") } From 787b4ac6b65f475bdf9985036b16771bc7876337 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 17 Aug 2024 11:36:57 -0700 Subject: [PATCH 0658/1066] Fix govet: printf: non-constant format string Signed-off-by: apostasie --- pkg/logging/cri_logger_test.go | 2 +- pkg/logging/json_logger_test.go | 2 +- pkg/testutil/testutil.go | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/logging/cri_logger_test.go b/pkg/logging/cri_logger_test.go index c8207d3c341..f497b436a44 100644 --- a/pkg/logging/cri_logger_test.go +++ b/pkg/logging/cri_logger_test.go @@ -90,7 +90,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/json_logger_test.go b/pkg/logging/json_logger_test.go index 76014d761df..53e6e434867 100644 --- a/pkg/logging/json_logger_test.go +++ b/pkg/logging/json_logger_test.go @@ -160,7 +160,7 @@ func TestReadJSONLogs(t *testing.T) { err = viewLogsJSONFileDirect(tc.logViewOptions, file.Name(), 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/testutil/testutil.go b/pkg/testutil/testutil.go index e1d4b1128d3..4d93fc4c915 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -18,6 +18,7 @@ package testutil import ( "encoding/json" + "errors" "flag" "fmt" "io" @@ -496,7 +497,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 errors.New(msg) } return nil } From 553ee688742c54169a25e6c091da3e06f9fe81df Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 18 Aug 2024 01:50:57 +0900 Subject: [PATCH 0659/1066] update golangci-lint (1.60.1) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b4c372c3b29..a1b2439ccbc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v6.1.0 with: - version: v1.59.1 + version: v1.60.1 args: --verbose - name: yamllint-lint run: make lint-yaml From ddcf41c2c992e84ae300765d6a3f8879b43692ce Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 18 Aug 2024 01:50:03 +0900 Subject: [PATCH 0660/1066] update Debian (12) Signed-off-by: Akihiro Suda --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 43bedeaeb64..2c42e2a6fc6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,12 +54,11 @@ ARG SOCI_SNAPSHOTTER_VERSION=0.6.1 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.4.0 AS xx -FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bullseye AS build-base-debian +FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm AS build-base-debian COPY --from=xx / / ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update -qq && apt-get install -qq --no-install-recommends \ git \ - pkg-config \ dpkg-dev ARG TARGETARCH # libbtrfs: for containerd @@ -69,7 +68,8 @@ RUN xx-apt-get update -qq && xx-apt-get install -qq --no-install-recommends \ gcc \ libc6-dev \ libbtrfs-dev \ - libseccomp-dev + libseccomp-dev \ + pkg-config FROM build-base-debian AS build-containerd ARG TARGETARCH From 9efda2271debe5f9f06933ee327aea32edeeb56d Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 18 Aug 2024 01:43:44 +0900 Subject: [PATCH 0661/1066] update Go (1.23) Signed-off-by: Akihiro Suda --- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 4 ++-- Dockerfile | 2 +- hack/build-integration-kube.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a26668f6338..d46f8827757 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4.1.7 - uses: actions/setup-go@v5 with: - go-version: 1.22.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 a1b2439ccbc..e9b3b9792a1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ on: - '**.md' env: - GO_VERSION: 1.22.x + GO_VERSION: 1.23.x jobs: lint: @@ -236,7 +236,7 @@ jobs: 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.7 with: diff --git a/Dockerfile b/Dockerfile index 2c42e2a6fc6..e5d07e81d67 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,7 +44,7 @@ ARG TINI_VERSION=v0.19.0 ARG BUILDG_VERSION=v0.4.1 # Test deps -ARG GO_VERSION=1.22 +ARG GO_VERSION=1.23 ARG UBUNTU_VERSION=24.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.12.0 diff --git a/hack/build-integration-kube.sh b/hack/build-integration-kube.sh index 0f867530e2c..52ae61ca25a 100755 --- a/hack/build-integration-kube.sh +++ b/hack/build-integration-kube.sh @@ -21,7 +21,7 @@ readonly root # shellcheck source=/dev/null . "$root/scripts/lib.sh" -GO_VERSION=1.22 +GO_VERSION=1.23 KIND_VERSION=v0.23.0 [ "$(uname -m)" == "aarch64" ] && GOARCH=arm64 || GOARCH=amd64 From 6f7a56f2efd48a36592387a47a76564d937b9e25 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 18 Aug 2024 01:44:36 +0900 Subject: [PATCH 0662/1066] update kind (0.24.0) Signed-off-by: Akihiro Suda --- hack/build-integration-kube.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/build-integration-kube.sh b/hack/build-integration-kube.sh index 52ae61ca25a..0fa32457b21 100755 --- a/hack/build-integration-kube.sh +++ b/hack/build-integration-kube.sh @@ -22,7 +22,7 @@ readonly root . "$root/scripts/lib.sh" GO_VERSION=1.23 -KIND_VERSION=v0.23.0 +KIND_VERSION=v0.24.0 [ "$(uname -m)" == "aarch64" ] && GOARCH=arm64 || GOARCH=amd64 From 17a0749e8d2df02588dd8b960ac1d650c8170ba9 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 18 Aug 2024 01:46:36 +0900 Subject: [PATCH 0663/1066] update BuildKit (0.15.2) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.0 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.2 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.2 diff --git a/Dockerfile b/Dockerfile index e5d07e81d67..e790b0571b7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.13 ARG CNI_PLUGINS_VERSION=v1.5.1 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.15.0 +ARG BUILDKIT_VERSION=v0.15.2 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.0 deleted file mode 100644 index bda954324e8..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.0 +++ /dev/null @@ -1,2 +0,0 @@ -803de21f1656b2f0398e09204abcff2943c17b6b5951fe5ccfc8300012fcb838 buildkit-v0.15.0.linux-amd64.tar.gz -dfa15ef3f194afc0f588de1e78053cdcd553e7de2f9692efe964c9aa7e9d621e buildkit-v0.15.0.linux-arm64.tar.gz 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 From 3cb2cd1f50cf7d68273eb77384f4004952d31e91 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 18 Aug 2024 01:48:54 +0900 Subject: [PATCH 0664/1066] update soci-snapshotter (0.7.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e790b0571b7..67c12a66804 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,7 +49,7 @@ ARG UBUNTU_VERSION=24.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.12.0 ARG NYDUS_VERSION=v2.2.5 -ARG SOCI_SNAPSHOTTER_VERSION=0.6.1 +ARG SOCI_SNAPSHOTTER_VERSION=0.7.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.4.0 AS xx From f5a2962cb5814fc65062953090afd61b123b5dc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 17 Aug 2024 19:33:16 +0000 Subject: [PATCH 0665/1066] build(deps): bump github.com/rootless-containers/rootlesskit/v2 Bumps [github.com/rootless-containers/rootlesskit/v2](https://github.com/rootless-containers/rootlesskit) from 2.2.0 to 2.3.1. - [Release notes](https://github.com/rootless-containers/rootlesskit/releases) - [Commits](https://github.com/rootless-containers/rootlesskit/compare/v2.2.0...v2.3.1) --- updated-dependencies: - dependency-name: github.com/rootless-containers/rootlesskit/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b246e798363..7744059f9e1 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,7 @@ require ( github.com/opencontainers/runtime-spec v1.2.0 github.com/pelletier/go-toml/v2 v2.2.2 github.com/rootless-containers/bypass4netns v0.4.1 - github.com/rootless-containers/rootlesskit/v2 v2.2.0 + github.com/rootless-containers/rootlesskit/v2 v2.3.1 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/vishvananda/netlink v1.2.1-beta.2 diff --git a/go.sum b/go.sum index 6bc3377fd06..f57a0c77233 100644 --- a/go.sum +++ b/go.sum @@ -269,8 +269,8 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rootless-containers/bypass4netns v0.4.1 h1:zyYM1uSG7/prAphD2vlJvx/MEKK91EjD2XaefGx5PKA= github.com/rootless-containers/bypass4netns v0.4.1/go.mod h1:slu3ygwy1x6ey78oBTNs7lpymyEimLBYoXOG76b+Q+Y= -github.com/rootless-containers/rootlesskit/v2 v2.2.0 h1:qTA3QyfsZSKmvKDL7m5lCl55OmJZXmKf381dSb5Ig9E= -github.com/rootless-containers/rootlesskit/v2 v2.2.0/go.mod h1:AyUlpgPnMv085smZXp5mt4D9q4mNjbHOcZwaVobRzyU= +github.com/rootless-containers/rootlesskit/v2 v2.3.1 h1:wdYtdKxWFvVLby9ThMP6O6/v2q/GmOXbkRi+4m9nPW0= +github.com/rootless-containers/rootlesskit/v2 v2.3.1/go.mod h1:tdtfS9ak4bGmwJRmcjsAzcHN5rJ3c5dB7yhSV10KTbk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= From 613f7c6ebd1758f6538187ce3a22aed0e6d71a5c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Sun, 18 Aug 2024 04:32:01 +0900 Subject: [PATCH 0666/1066] update RootlessKit (2.3.1) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 6 +++--- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.1.0 | 6 ------ Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.1 | 6 ++++++ 4 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.1.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e9b3b9792a1..3743c44441c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -170,15 +170,15 @@ jobs: target: test-integration-rootless - ubuntu: 22.04 containerd: v1.7.19 - rootlesskit: v2.1.0 + rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 24.04 containerd: v2.0.0-rc.3 - rootlesskit: v2.1.0 + rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 24.04 containerd: v1.7.19 - rootlesskit: v2.1.0 + rootlesskit: v2.3.1 target: test-integration-rootless-port-slirp4netns env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" diff --git a/Dockerfile b/Dockerfile index 67c12a66804..452b17a9f82 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption ARG IMGCRYPT_VERSION=v1.1.11 # Extra deps: Rootless -ARG ROOTLESSKIT_VERSION=v2.1.0 +ARG ROOTLESSKIT_VERSION=v2.3.1 ARG SLIRP4NETNS_VERSION=v1.3.1 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.4.1 diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.1.0 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.1.0 deleted file mode 100644 index c60be289879..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.1.0 +++ /dev/null @@ -1,6 +0,0 @@ -b3a9b14b66f54351a2b9f8c0917062bfeab2dc89e9e7cb15f4cf0684a4a7281f rootlesskit-aarch64.tar.gz -6fd0be2aa10d7533e41f4013ee8f7e2779c16c6091a02d150d7998da16b6292a rootlesskit-armv7l.tar.gz -43c6fa763d61c3cb49216821009b1b7e6dcd5ba97a57ef8c2762a7ffbd317556 rootlesskit-ppc64le.tar.gz -914cdfb02a207a68b038a64871849dc0586242dd2cd3775de58e6a7c661f3c60 rootlesskit-riscv64.tar.gz -185c86ef5758ded11c685d725642f2bcb6fc27dbb450ed2fbd857347fb5d301b rootlesskit-s390x.tar.gz -1e4609a3d0ca67c4fc99fe9121870cf5ca46a438f43b151e9b54456d166f4b10 rootlesskit-x86_64.tar.gz 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 From bd27d52e3979cfbba2a30473b1bfe9a15dcda086 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 20 Aug 2024 10:07:49 -0700 Subject: [PATCH 0667/1066] Workaround goimports-reviser bug Signed-off-by: apostasie --- Makefile | 2 +- hack/lint-imports.sh | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100755 hack/lint-imports.sh diff --git a/Makefile b/Makefile index 08ace13220d..cc4093818a5 100644 --- a/Makefile +++ b/Makefile @@ -73,7 +73,7 @@ lint-go: cd $(MAKEFILE_DIR) && golangci-lint run $(VERBOSE_FLAG_LONG) ./... lint-imports: - cd $(MAKEFILE_DIR) && goimports-reviser -list-diff -company-prefixes "github.com/containerd" ./... + cd $(MAKEFILE_DIR) && ./hack/lint-imports.sh lint-fix-imports: cd $(MAKEFILE_DIR) && goimports-reviser -company-prefixes "github.com/containerd" ./... diff --git a/hack/lint-imports.sh b/hack/lint-imports.sh new file mode 100755 index 00000000000..d37df1a09bf --- /dev/null +++ b/hack/lint-imports.sh @@ -0,0 +1,33 @@ +#!/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. + +# FIXME: goimports-reviser is currently broken when it comes to ./... +# Specifically, it will ignore arguments, and will return exit 0 regardless +# This here is a workaround, until they fix it upstream: https://github.com/incu6us/goimports-reviser/pull/157 + +# shellcheck disable=SC2034,SC2015 +set -o errexit -o errtrace -o functrace -o nounset -o pipefail + +ex=0 + +while read -r file; do + goimports-reviser -list-diff -set-exit-status -output stdout -company-prefixes "github.com/containerd" "$file" || { + ex=$? + >&2 printf "Imports are not listed properly in %s. Consider calling make lint-fix-imports.\n" "$file" + } +done < <(find ./ -type f -name '*.go') + +exit "$ex" From d2dace20211643b28a8ad379314e2758bfb6d7e9 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 20 Aug 2024 10:12:50 -0700 Subject: [PATCH 0668/1066] Fix import order Signed-off-by: apostasie --- pkg/imgutil/filtering_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/imgutil/filtering_test.go b/pkg/imgutil/filtering_test.go index 70125ee6012..7d82cb2ce60 100644 --- a/pkg/imgutil/filtering_test.go +++ b/pkg/imgutil/filtering_test.go @@ -20,8 +20,9 @@ import ( "testing" "time" - "github.com/containerd/containerd/v2/core/images" "gotest.tools/v3/assert" + + "github.com/containerd/containerd/v2/core/images" ) func TestApplyFilters(t *testing.T) { From 8352492b4762e4a13c205f7267540e3aec5a3c03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:14:48 +0000 Subject: [PATCH 0669/1066] build(deps): bump tonistiigi/xx from 1.4.0 to 1.5.0 Bumps tonistiigi/xx from 1.4.0 to 1.5.0. --- updated-dependencies: - dependency-name: tonistiigi/xx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 452b17a9f82..966a1d1ade4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,7 +51,7 @@ ARG GOTESTSUM_VERSION=v1.12.0 ARG NYDUS_VERSION=v2.2.5 ARG SOCI_SNAPSHOTTER_VERSION=0.7.0 -FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.4.0 AS xx +FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0 AS xx FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm AS build-base-debian From 034f2e73088b0d7c55bdf469d05567b53b83d1e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:45:48 +0000 Subject: [PATCH 0670/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.12.5 to 0.12.6 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.12.5 to 0.12.6. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.5...v0.12.6) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7744059f9e1..cc851da6b00 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ go 1.22.0 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/Microsoft/go-winio v0.6.2 - github.com/Microsoft/hcsshim v0.12.5 + github.com/Microsoft/hcsshim v0.12.6 github.com/compose-spec/compose-go/v2 v2.1.6 github.com/containerd/accelerated-container-image v1.2.0 github.com/containerd/cgroups/v3 v3.0.3 diff --git a/go.sum b/go.sum index f57a0c77233..86bf558069c 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= 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.12.5 h1:bpTInLlDy/nDRWFVcefDZZ1+U8tS+rz3MxjKgu9boo0= -github.com/Microsoft/hcsshim v0.12.5/go.mod h1:tIUGego4G1EN5Hb6KC90aDYiUI2dqLSTTOCjVNpOgZ8= +github.com/Microsoft/hcsshim v0.12.6 h1:qEnZjoHXv+4/s0LmKZWE0/AiZmMWEIkFfWBSf1a0wlU= +github.com/Microsoft/hcsshim v0.12.6/go.mod h1:ZABCLVcvLMjIkzr9rUGcQ1QA0p0P3Ps+d3N1g2DsFfk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= From 1201665eb4a608a1236576379ac68450a1d7a934 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Sat, 17 Aug 2024 06:44:33 +0000 Subject: [PATCH 0671/1066] Add builder OCI layout build context Signed-off-by: Austin Vazquez --- cmd/nerdctl/builder_build_linux_test.go | 84 +++++++++++++++++++++++++ docs/command-reference.md | 2 +- pkg/cmd/builder/build.go | 69 ++++++++++++++++++++ pkg/cmd/builder/build_test.go | 39 ++++++++++++ pkg/testutil/testutil.go | 24 ++++++- 5 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 cmd/nerdctl/builder_build_linux_test.go diff --git a/cmd/nerdctl/builder_build_linux_test.go b/cmd/nerdctl/builder_build_linux_test.go new file mode 100644 index 00000000000..3e3fc7334ee --- /dev/null +++ b/cmd/nerdctl/builder_build_linux_test.go @@ -0,0 +1,84 @@ +/* + 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" + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestBuildContextWithOCILayout(t *testing.T) { + testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) + + var dockerBuilderArgs []string + if testutil.IsDocker() { + // Default docker driver does not support OCI exporter. + // Reference: https://docs.docker.com/build/exporters/oci-docker/ + builderName := testutil.SetupDockerContainerBuilder(t) + dockerBuilderArgs = []string{"buildx", "--builder", builderName} + } + + base := testutil.NewBase(t) + imageName := testutil.Identifier(t) + ociLayout := "parent" + parentImageName := fmt.Sprintf("%s-%s", imageName, ociLayout) + + teardown := func() { + base.Cmd("rmi", parentImageName, imageName).Run() + } + t.Cleanup(teardown) + teardown() + + dockerfile := fmt.Sprintf(`FROM %s +LABEL layer=oci-layout-parent +CMD ["echo", "test-nerdctl-build-context-oci-layout-parent"]`, testutil.CommonImage) + buildCtx := createBuildContext(t, dockerfile) + + tarPath := fmt.Sprintf("%s/%s.tar", buildCtx, ociLayout) + + // Create OCI archive from parent image. + base.Cmd("build", buildCtx, "--tag", parentImageName).AssertOK() + base.Cmd("image", "save", "--output", tarPath, parentImageName).AssertOK() + + // Unpack OCI archive into OCI layout directory. + ociLayoutDir := t.TempDir() + err := extractTarFile(ociLayoutDir, tarPath) + assert.NilError(t, err) + + dockerfile = fmt.Sprintf(`FROM %s +CMD ["echo", "test-nerdctl-build-context-oci-layout"]`, ociLayout) + buildCtx = createBuildContext(t, dockerfile) + + var buildArgs = []string{} + if testutil.IsDocker() { + buildArgs = dockerBuilderArgs + } + + buildArgs = append(buildArgs, "build", buildCtx, fmt.Sprintf("--build-context=%s=oci-layout://%s", ociLayout, ociLayoutDir), "--tag", imageName) + if testutil.IsDocker() { + // Need to load the container image from the builder to be able to run it. + buildArgs = append(buildArgs, "--load") + } + + base.Cmd(buildArgs...).AssertOK() + base.Cmd("run", "--rm", imageName).AssertOutContains("test-nerdctl-build-context-oci-layout") +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 4508b65f8c8..ba782efba9a 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -708,7 +708,7 @@ Flags: - :nerd_face: `--ipfs`: Build image with pulling base images from IPFS. See [`ipfs.md`](./ipfs.md) for details. - :whale: `--label`: Set metadata for an image - :whale: `--network=(default|host|none)`: Set the networking mode for the RUN instructions during build.(compatible with `buildctl build`) -- :whale: --build-context: Set additional contexts for build (e.g. dir2=/path/to/dir2, myorg/myapp=docker-image://path/to/myorg/myapp) +- :whale: `--build-context`: Set additional contexts for build (e.g. dir2=/path/to/dir2, myorg/myapp=docker-image://path/to/myorg/myapp) Unimplemented `docker build` flags: `--add-host`, `--squash` diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 03d87848fe1..5325929f2b7 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -29,6 +29,7 @@ import ( "strings" distributionref "github.com/distribution/reference" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" @@ -300,6 +301,16 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option continue } + if isOCILayout := strings.HasPrefix(v, "oci-layout://"); isOCILayout { + args, err := parseBuildContextFromOCILayout(k, v) + if err != nil { + return "", nil, false, "", nil, nil, err + } + + buildctlArgs = append(buildctlArgs, args...) + continue + } + path, err := filepath.Abs(v) if err != nil { return "", nil, false, "", nil, nil, err @@ -534,3 +545,61 @@ func parseContextNames(values []string) (map[string]string, error) { } return result, nil } + +var ( + ErrOCILayoutPrefixNotFound = errors.New("OCI layout prefix not found") + ErrOCILayoutEmptyDigest = errors.New("OCI layout cannot have empty digest") +) + +func parseBuildContextFromOCILayout(name, path string) ([]string, error) { + path, found := strings.CutPrefix(path, "oci-layout://") + if !found { + return []string{}, ErrOCILayoutPrefixNotFound + } + + abspath, err := filepath.Abs(path) + if err != nil { + return []string{}, err + } + + ociIndex, err := readOCIIndexFromPath(abspath) + if err != nil { + return []string{}, err + } + + var digest string + for _, manifest := range ociIndex.Manifests { + if images.IsManifestType(manifest.MediaType) { + digest = manifest.Digest.String() + } + } + + if digest == "" { + return []string{}, ErrOCILayoutEmptyDigest + } + + return []string{ + fmt.Sprintf("--oci-layout=parent-image-key=%s", abspath), + fmt.Sprintf("--opt=context:%s=oci-layout:parent-image-key@%s", name, digest), + }, nil +} + +func readOCIIndexFromPath(path string) (*ocispec.Index, error) { + ociIndexJSONFile, err := os.Open(filepath.Join(path, "index.json")) + if err != nil { + return nil, err + } + defer ociIndexJSONFile.Close() + + rawBytes, err := io.ReadAll(ociIndexJSONFile) + if err != nil { + return nil, err + } + + var ociIndex *ocispec.Index + err = json.Unmarshal(rawBytes, &ociIndex) + if err != nil { + return nil, err + } + return ociIndex, nil +} diff --git a/pkg/cmd/builder/build_test.go b/pkg/cmd/builder/build_test.go index f7fb00e539f..954738cdbc6 100644 --- a/pkg/cmd/builder/build_test.go +++ b/pkg/cmd/builder/build_test.go @@ -187,3 +187,42 @@ func TestIsBuildPlatformDefault(t *testing.T) { }) } } + +func TestParseBuildctlArgsForOCILayout(t *testing.T) { + tests := []struct { + name string + ociLayoutName string + ociLayoutPath string + expectedArgs []string + errorIsNil bool + expectedErr string + }{ + { + name: "PrefixNotFoundError", + ociLayoutName: "unit-test", + ociLayoutPath: "/tmp/oci-layout/", + expectedArgs: []string{}, + expectedErr: ErrOCILayoutPrefixNotFound.Error(), + }, + { + name: "DirectoryNotFoundError", + ociLayoutName: "unit-test", + ociLayoutPath: "oci-layout:///tmp/oci-layout", + expectedArgs: []string{}, + expectedErr: "open /tmp/oci-layout/index.json: no such file or directory", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + args, err := parseBuildContextFromOCILayout(test.ociLayoutName, test.ociLayoutPath) + if test.errorIsNil { + assert.NilError(t, err) + } else { + assert.Error(t, err, test.expectedErr) + } + assert.Equal(t, len(args), len(test.expectedArgs)) + assert.DeepEqual(t, args, test.expectedArgs) + }) + } +} diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 4d93fc4c915..cbc476e8767 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -575,8 +575,12 @@ func GetDaemonIsKillable() bool { return flagTestKillDaemon } +func IsDocker() bool { + return GetTarget() == Docker +} + func DockerIncompatible(t testing.TB) { - if GetTarget() == Docker { + if IsDocker() { t.Skip("test is incompatible with Docker") } } @@ -789,3 +793,21 @@ func KubectlHelper(base *Base, args ...string) *Cmd { Base: base, } } + +// SetupDockerContinerBuilder creates a Docker builder using the docker-container driver +// and adds cleanup steps to test cleanup. The builder name is returned as output. +// +// If not docker, this function returns an empty string as the builder name. +func SetupDockerContainerBuilder(t *testing.T) string { + var name string + if IsDocker() { + name = fmt.Sprintf("%s-container", Identifier(t)) + base := NewBase(t) + base.Cmd("buildx", "create", "--name", name, "--driver=docker-container").AssertOK() + t.Cleanup(func() { + base.Cmd("buildx", "stop", name).AssertOK() + base.Cmd("buildx", "rm", "--force", name).AssertOK() + }) + } + return name +} From a1bd4760eada6e5ef590221a1da204ae7b009ad4 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 18 Aug 2024 11:06:38 -0700 Subject: [PATCH 0672/1066] ParentMain/nsenter: do not fail if getwd errors Signed-off-by: apostasie --- pkg/rootlessutil/parent_linux.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/pkg/rootlessutil/parent_linux.go b/pkg/rootlessutil/parent_linux.go index 38ace232d91..f6a519ab29d 100644 --- a/pkg/rootlessutil/parent_linux.go +++ b/pkg/rootlessutil/parent_linux.go @@ -84,11 +84,6 @@ func ParentMain(hostGatewayIP string) error { detachNetNSMode := detachedNetNSPath != "" log.L.Debugf("RootlessKit detach-netns mode: %v", detachNetNSMode) - wd, err := os.Getwd() - if err != nil { - return err - } - // FIXME: remove dependency on `nsenter` binary arg0, err := exec.LookPath("nsenter") if err != nil { @@ -96,13 +91,24 @@ func ParentMain(hostGatewayIP string) error { } // args are compatible with both util-linux nsenter and busybox nsenter args := []string{ - "-r/", // root dir (busybox nsenter wants this to be explicitly specified), - "-w" + wd, // work dir - "--preserve-credentials", + "-r/", // root dir (busybox nsenter wants this to be explicitly specified), + } + + // Only append wd if we do have a working dir + // - https://github.com/rootless-containers/usernetes/pull/327 + // - https://github.com/containerd/nerdctl/issues/3328 + wd, err := os.Getwd() + if err != nil { + log.L.WithError(err).Warn("unable to determine working directory") + } else { + args = append(args, "-w"+wd) + } + + args = append(args, "--preserve-credentials", "-m", "-U", "-t", strconv.Itoa(childPid), "-F", // no fork - } + ) if !detachNetNSMode { args = append(args, "-n") } From 572d368d47b8e88a9fb54353e9bec4b95b1f123b Mon Sep 17 00:00:00 2001 From: xyz-li Date: Sun, 18 Aug 2024 11:44:51 +0800 Subject: [PATCH 0673/1066] fix: filter container state without option "-a" Signed-off-by: xyz-li --- cmd/nerdctl/container_list.go | 2 +- cmd/nerdctl/container_list_linux_test.go | 27 ++++++++++++++++++++++++ docs/command-reference.md | 4 ++-- pkg/cmd/container/list.go | 3 ++- pkg/cmd/container/list_util.go | 3 +++ 5 files changed, 35 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container_list.go index e66e7a6584e..f4f43be161a 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container_list.go @@ -53,7 +53,7 @@ func newPsCommand() *cobra.Command { psCommand.RegisterFlagCompletionFunc("format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"json", "table", "wide"}, cobra.ShellCompDirectiveNoFileComp }) - psCommand.Flags().StringSliceP("filter", "f", nil, "Filter matches containers based on given conditions") + psCommand.Flags().StringSliceP("filter", "f", nil, "Filter matches containers based on given conditions. When specifying the condition 'status', it filters all containers") return psCommand } diff --git a/cmd/nerdctl/container_list_linux_test.go b/cmd/nerdctl/container_list_linux_test.go index ab6c3173e42..a4475e5c0c1 100644 --- a/cmd/nerdctl/container_list_linux_test.go +++ b/cmd/nerdctl/container_list_linux_test.go @@ -576,6 +576,33 @@ func TestContainerListWithFilter(t *testing.T) { } return nil }) + + // filter container state without option "-a". + base.Cmd("ps", "--filter", "status=exited").AssertOutWithFunc(func(stdout string) error { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + if len(lines) < 2 { + return fmt.Errorf("expected at least 2 lines, got %d", len(lines)) + } + + tab := tabutil.NewReader("CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES") + err := tab.ParseHeader(lines[0]) + if err != nil { + return fmt.Errorf("failed to parse header: %v", err) + } + containerNames := map[string]struct{}{ + testContainerC.name: {}, + } + for idx, line := range lines { + if idx == 0 { + continue + } + containerName, _ := tab.ReadRow(line, "NAMES") + if _, ok := containerNames[containerName]; !ok { + return fmt.Errorf("unexpected container %s found", containerName) + } + } + return nil + }) } func TestContainerListCheckCreatedTime(t *testing.T) { diff --git a/docs/command-reference.md b/docs/command-reference.md index caffd51e457..bb1f736c6e1 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -460,7 +460,7 @@ Flags: - :nerd_face: `--format=json`: Alias of `--format='{{json .}}'` - :whale: `-n, --last`: Show n last created containers (includes all states) - :whale: `-l, --latest`: Show the latest created container (includes all states) -- :whale: `-f, --filter`: Filter containers based on given conditions +- :whale: `-f, --filter`: Filter containers based on given conditions. When specifying the condition 'status', it filters all containers - :whale: `--filter id=`: Container's ID. Both full ID and truncated ID are supported - :whale: `--filter name=`: Container's name @@ -470,7 +470,7 @@ Flags: `--all` - :whale: `--filter status=`: One of `created, running, paused, stopped, exited, pausing, unknown`. Note that `restarting, removing, dead` are - not supported and will be ignored + not supported and will be ignored. When specifying this condition, it filters all containers. - :whale: `--filter before/since=`: Filter containers created before or after a given ID or name - :whale: `--filter volume=`: Filter by a given mounted volume or bind diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index 2914e49e739..b5887dcd789 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -77,9 +77,10 @@ func filterContainers(ctx context.Context, client *containerd.Client, filters [] } } - if all { + if all || filterCtx.all { return containers, nil } + var upContainers []containerd.Container for _, c := range containers { cStatus := formatter.ContainerStatus(ctx, c) diff --git a/pkg/cmd/container/list_util.go b/pkg/cmd/container/list_util.go index da8992c4064..c6e0da8e2eb 100644 --- a/pkg/cmd/container/list_util.go +++ b/pkg/cmd/container/list_util.go @@ -48,6 +48,8 @@ type containerFilterContext struct { labelFilterFuncs []func(map[string]string) bool volumeFilterFuncs []func([]*containerutil.ContainerVolume) bool networkFilterFuncs []func([]string) bool + + all bool } func (cl *containerFilterContext) MatchesFilters(ctx context.Context) []containerd.Container { @@ -264,6 +266,7 @@ func (cl *containerFilterContext) matchesStatusFilter(status containerd.Status) if len(cl.statusFilterFuncs) == 0 { return true } + cl.all = true for _, statusFilterFunc := range cl.statusFilterFuncs { if !statusFilterFunc(status.Status) { continue From 0e8b3d45cd7a97b820c8d0359befdf12a90ae7da Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 21 Aug 2024 14:08:20 -0700 Subject: [PATCH 0674/1066] Implement windows filename restrictions Signed-off-by: apostasie --- pkg/identifiers/validate.go | 5 ++++ pkg/identifiers/validate_other.go | 23 ++++++++++++++++ pkg/identifiers/validate_windows.go | 41 +++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 pkg/identifiers/validate_other.go create mode 100644 pkg/identifiers/validate_windows.go diff --git a/pkg/identifiers/validate.go b/pkg/identifiers/validate.go index c5276c8b17d..bb6e62c5aaa 100644 --- a/pkg/identifiers/validate.go +++ b/pkg/identifiers/validate.go @@ -41,5 +41,10 @@ func ValidateDockerCompat(s string) error { if !AllowedIdentifierPattern.MatchString(s) { return fmt.Errorf("identifier %q must match pattern %q: %w", s, AllowedIdentfierChars, errdefs.ErrInvalidArgument) } + + if err := validatePlatformSpecific(s); err != nil { + return err + } + return nil } diff --git a/pkg/identifiers/validate_other.go b/pkg/identifiers/validate_other.go new file mode 100644 index 00000000000..642c6ac3ae6 --- /dev/null +++ b/pkg/identifiers/validate_other.go @@ -0,0 +1,23 @@ +//go:build !windows + +/* + 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 identifiers + +func validatePlatformSpecific(identifier string) error { + return nil +} diff --git a/pkg/identifiers/validate_windows.go b/pkg/identifiers/validate_windows.go new file mode 100644 index 00000000000..64141ed3529 --- /dev/null +++ b/pkg/identifiers/validate_windows.go @@ -0,0 +1,41 @@ +/* + 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 identifiers + +import ( + "fmt" + "regexp" + + "github.com/containerd/errdefs" +) + +// See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file + +// Note that ¹²³ is technically not required here since they are out of the regexp for regular validation +var windowsDisallowed = regexp.MustCompile(`^(con|prn|nul|aux|com[1-9¹²³]|lpt[1-9¹²³])([.].*)?`) + +func validatePlatformSpecific(identifier string) error { + if windowsDisallowed.MatchString(identifier) { + return fmt.Errorf("identifier %q must not match reserved windows pattern %q: %w", identifier, windowsDisallowed, errdefs.ErrInvalidArgument) + } + + if identifier[len(identifier)-1:] == "." { + return fmt.Errorf("windows does not allow identifiers ending with a dot or space (%q)", identifier) + } + + return nil +} From 031aa1d47db08b5b34b06aa8d7963a9194709b9d Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 21 Aug 2024 11:00:00 -0700 Subject: [PATCH 0675/1066] K8s minor cleanup (rename and -f on delete) Signed-off-by: apostasie --- .github/workflows/test-kube.yml | 10 ++-- cmd/nerdctl/container_commit_linux_test.go | 4 +- ...ube.sh => build-integration-kubernetes.sh} | 0 pkg/testutil/testutil.go | 52 +++++++++---------- 4 files changed, 33 insertions(+), 33 deletions(-) rename hack/{build-integration-kube.sh => build-integration-kubernetes.sh} (100%) diff --git a/.github/workflows/test-kube.yml b/.github/workflows/test-kube.yml index 593cc5b4511..c8696a38b32 100644 --- a/.github/workflows/test-kube.yml +++ b/.github/workflows/test-kube.yml @@ -1,5 +1,5 @@ -# This pipeline purpose is solely meant to run a subset of our test suites against a kube cluster -name: kube +# This pipeline purpose is solely meant to run a subset of our test suites against a kubernetes cluster +name: kubernetes on: push: @@ -21,7 +21,7 @@ jobs: - uses: actions/checkout@v4.1.7 with: fetch-depth: 1 - - name: "Run Kube integration tests" + - name: "Run Kubernetes integration tests" run: | - ./hack/build-integration-kube.sh - sudo ./_output/nerdctl exec nerdctl-test-control-plane bash -c -- 'export TMPDIR="$HOME"/tmp; mkdir -p "$TMPDIR"; cd /nerdctl-source; /usr/local/go/bin/go test ./cmd/nerdctl/ -test.only-kube' + ./hack/build-integration-kubernetes.sh + sudo ./_output/nerdctl exec nerdctl-test-control-plane bash -c -- 'export TMPDIR="$HOME"/tmp; mkdir -p "$TMPDIR"; cd /nerdctl-source; /usr/local/go/bin/go test ./cmd/nerdctl/ -test.only-kubernetes' diff --git a/cmd/nerdctl/container_commit_linux_test.go b/cmd/nerdctl/container_commit_linux_test.go index a26c3b1eff6..a18f57a5150 100644 --- a/cmd/nerdctl/container_commit_linux_test.go +++ b/cmd/nerdctl/container_commit_linux_test.go @@ -28,7 +28,7 @@ import ( func TestKubeCommitPush(t *testing.T) { t.Parallel() - base := testutil.NewBaseForKube(t) + base := testutil.NewBaseForKubernetes(t) tID := testutil.Identifier(t) var containerID string @@ -49,7 +49,7 @@ func TestKubeCommitPush(t *testing.T) { } tearDown := func() { - testutil.KubectlHelper(base, "delete", "pod", tID).Run() + testutil.KubectlHelper(base, "delete", "pod", "-f", tID).Run() } tearDown() diff --git a/hack/build-integration-kube.sh b/hack/build-integration-kubernetes.sh similarity index 100% rename from hack/build-integration-kube.sh rename to hack/build-integration-kubernetes.sh diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 4d93fc4c915..717a2949221 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -48,16 +48,16 @@ import ( ) type Base struct { - T testing.TB - Target Target - DaemonIsKillable bool - EnableIPv6 bool - IPv6Compatible bool - EnableKube bool - KubeCompatible bool - Binary string - Args []string - Env []string + T testing.TB + Target Target + DaemonIsKillable bool + EnableIPv6 bool + IPv6Compatible bool + EnableKubernetes bool + KubernetesCompatible bool + Binary string + Args []string + Env []string } // WithStdin sets the standard input of Cmd to the specified reader @@ -550,7 +550,7 @@ func M(m *testing.M) { flag.StringVar(&flagTestTarget, "test.target", Nerdctl, "target to test") flag.BoolVar(&flagTestKillDaemon, "test.allow-kill-daemon", false, "enable tests that kill the daemon") flag.BoolVar(&flagTestIPv6, "test.only-ipv6", false, "enable tests on IPv6") - flag.BoolVar(&flagTestKube, "test.only-kube", false, "enable tests on Kube") + flag.BoolVar(&flagTestKube, "test.only-kubernetes", false, "enable tests on Kubernetes") flag.Parse() fmt.Fprintf(os.Stderr, "test target: %q\n", flagTestTarget) os.Exit(m.Run()) @@ -567,7 +567,7 @@ func GetEnableIPv6() bool { return flagTestIPv6 } -func GetEnableKube() bool { +func GetEnableKubernetes() bool { return flagTestKube } @@ -697,7 +697,7 @@ func NewBaseWithIPv6Compatible(t *testing.T) *Base { return newBase(t, Namespace, true, false) } -func NewBaseForKube(t *testing.T) *Base { +func NewBaseForKubernetes(t *testing.T) *Base { base := newBase(t, "k8s.io", false, true) // NOTE: kubectl namespaces are not the same as containerd namespaces. // We still want kube test objects segregated in their own Kube API namespace. @@ -709,26 +709,26 @@ func NewBase(t *testing.T) *Base { return newBase(t, Namespace, false, false) } -func newBase(t *testing.T, ns string, ipv6Compatible bool, kubeCompatible bool) *Base { +func newBase(t *testing.T, ns string, ipv6Compatible bool, kubernetesCompatible bool) *Base { base := &Base{ - T: t, - Target: GetTarget(), - DaemonIsKillable: GetDaemonIsKillable(), - EnableIPv6: GetEnableIPv6(), - IPv6Compatible: ipv6Compatible, - EnableKube: GetEnableKube(), - KubeCompatible: kubeCompatible, - Env: os.Environ(), + T: t, + Target: GetTarget(), + DaemonIsKillable: GetDaemonIsKillable(), + EnableIPv6: GetEnableIPv6(), + IPv6Compatible: ipv6Compatible, + EnableKubernetes: GetEnableKubernetes(), + KubernetesCompatible: kubernetesCompatible, + Env: os.Environ(), } if base.EnableIPv6 && !base.IPv6Compatible { t.Skip("runner skips non-IPv6 compatible tests in the IPv6 environment") } else if !base.EnableIPv6 && base.IPv6Compatible { t.Skip("runner skips IPv6 compatible tests in the non-IPv6 environment") } - if base.EnableKube && !base.KubeCompatible { - t.Skip("runner skips non-kube compatible tests in the kube environment") - } else if !base.EnableKube && base.KubeCompatible { - t.Skip("runner skips kube compatible tests in the non-kube environment") + if base.EnableKubernetes && !base.KubernetesCompatible { + t.Skip("runner skips non-Kubernetes compatible tests in the Kubernetes environment") + } else if !base.EnableKubernetes && base.KubernetesCompatible { + t.Skip("runner skips Kubernetes compatible tests in the non-Kubernetes environment") } var err error switch base.Target { From 71c1558b42af63c951eff07edd0eefbdd281b847 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 22 Aug 2024 00:10:29 -0700 Subject: [PATCH 0676/1066] Fix panic on malformed add-host argument Signed-off-by: apostasie --- pkg/cmd/container/create.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 71c93b50272..d1ed52e371e 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -290,7 +290,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa parts := strings.SplitN(host, ":", 2) // If the IP Address is a string called "host-gateway", replace this value with the IP address stored // in the daemon level HostGateway IP config variable. - if parts[1] == dockeropts.HostGatewayName { + if len(parts) == 2 && parts[1] == dockeropts.HostGatewayName { if options.GOptions.HostGatewayIP == "" { return nil, nil, fmt.Errorf("unable to derive the IP value for host-gateway") } From f5e247f8cc67c6405384c08cf634f1f451b61b66 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 22 Aug 2024 00:11:07 -0700 Subject: [PATCH 0677/1066] Fix rename failure with network host/none Signed-off-by: apostasie --- pkg/cmd/container/rename.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/container/rename.go b/pkg/cmd/container/rename.go index 7211678988e..a9af9b6248a 100644 --- a/pkg/cmd/container/rename.go +++ b/pkg/cmd/container/rename.go @@ -22,6 +22,7 @@ import ( "runtime" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -78,7 +79,8 @@ func renameContainer(ctx context.Context, container containerd.Container, newNam } if runtime.GOOS == "linux" { if err := hostst.Update(ns, container.ID(), newName); err != nil { - return err + log.G(ctx).WithError(err).Warn("failed to update host networking definitions " + + "- if your container is using network 'none', this is expected - otherwise, please report this as a bug") } } labels := map[string]string{ From a4abf1e25cc580e9fbf4abecc31c5b336edbf6c1 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 22 Aug 2024 00:13:16 -0700 Subject: [PATCH 0678/1066] Use host hostname with network host Signed-off-by: apostasie --- pkg/containerutil/container_network_manager.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 54fa8f7f2ae..1b1c0e03c6b 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -32,6 +32,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -449,12 +450,17 @@ func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containe // `/etc/hostname` does not exist on FreeBSD if runtime.GOOS == "linux" && m.netOpts.UTSNamespace != UtsNamespaceHost { - // If no hostname is set, default to first 12 characters of the container ID. hostname := m.netOpts.Hostname if hostname == "" { - hostname = containerID - if len(hostname) > 12 { - hostname = hostname[0:12] + // Hostname by default should be the host hostname + hostname, err = os.Hostname() + if err != nil { + log.L.WithError(err).Warn("could not get hostname") + // If no hostname is set, default to first 12 characters of the container ID. + hostname = containerID + if len(hostname) > 12 { + hostname = hostname[0:12] + } } } m.netOpts.Hostname = hostname From c57dc6ffd5aa4c16c7b87c082dfb63fd29b1f3f2 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 22 Aug 2024 00:14:07 -0700 Subject: [PATCH 0679/1066] Rename variable for readability Signed-off-by: apostasie --- pkg/dnsutil/hostsstore/hostsstore.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/dnsutil/hostsstore/hostsstore.go b/pkg/dnsutil/hostsstore/hostsstore.go index cb4458db94a..63ce4e9beec 100644 --- a/pkg/dnsutil/hostsstore/hostsstore.go +++ b/pkg/dnsutil/hostsstore/hostsstore.go @@ -89,10 +89,10 @@ func DeallocHostsFile(dataStore, ns, id string) error { func NewStore(dataStore string) (Store, error) { store := &store{ - dataStore: dataStore, - hostsD: filepath.Join(dataStore, hostsDirBasename), + dataStore: dataStore, + hostsDirectory: filepath.Join(dataStore, hostsDirBasename), } - return store, os.MkdirAll(store.hostsD, 0700) + return store, os.MkdirAll(store.hostsDirectory, 0700) } type Meta struct { @@ -113,8 +113,8 @@ type Store interface { type store struct { // dataStore is /var/lib/nerdctl/ dataStore string - // hostsD is /var/lib/nerdctl//etchosts - hostsD string + // hostsDirectory is /var/lib/nerdctl//etchosts + hostsDirectory string } func (x *store) Acquire(meta Meta) error { @@ -127,20 +127,20 @@ func (x *store) Acquire(meta Meta) error { if err != nil { return err } - metaPath := filepath.Join(x.hostsD, meta.Namespace, meta.ID, metaJSON) + metaPath := filepath.Join(x.hostsDirectory, meta.Namespace, meta.ID, metaJSON) if err := os.WriteFile(metaPath, metaB, 0644); err != nil { return err } - return newUpdater(meta.ID, x.hostsD).update() + return newUpdater(meta.ID, x.hostsDirectory).update() } - return lockutil.WithDirLock(x.hostsD, fn) + return lockutil.WithDirLock(x.hostsDirectory, fn) } // Release is triggered by Poststop hooks. // It is called after the containerd task is deleted but before the delete operation returns. func (x *store) Release(ns, id string) error { fn := func() error { - metaPath := filepath.Join(x.hostsD, ns, id, metaJSON) + metaPath := filepath.Join(x.hostsDirectory, ns, id, metaJSON) if _, err := os.Stat(metaPath); errors.Is(err, os.ErrNotExist) { return nil } @@ -151,14 +151,14 @@ func (x *store) Release(ns, id string) error { if err := os.RemoveAll(metaPath); err != nil { return err } - return newUpdater(id, x.hostsD).update() + return newUpdater(id, x.hostsDirectory).update() } - return lockutil.WithDirLock(x.hostsD, fn) + return lockutil.WithDirLock(x.hostsDirectory, fn) } func (x *store) Update(ns, id, newName string) error { fn := func() error { - metaPath := filepath.Join(x.hostsD, ns, id, metaJSON) + metaPath := filepath.Join(x.hostsDirectory, ns, id, metaJSON) metaB, err := os.ReadFile(metaPath) if err != nil { return err @@ -175,7 +175,7 @@ func (x *store) Update(ns, id, newName string) error { if err := os.WriteFile(metaPath, metaB, 0644); err != nil { return err } - return newUpdater(meta.ID, x.hostsD).update() + return newUpdater(meta.ID, x.hostsDirectory).update() } - return lockutil.WithDirLock(x.hostsD, fn) + return lockutil.WithDirLock(x.hostsDirectory, fn) } From 132276c4b98e6f904d1fa4121729e604a406d3b8 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 22 Aug 2024 00:15:18 -0700 Subject: [PATCH 0680/1066] Fix --add-host not working with network host Signed-off-by: apostasie --- cmd/nerdctl/container_run.go | 9 +-- pkg/cmd/container/create.go | 5 +- pkg/cmd/container/remove.go | 40 +++++----- .../container_network_manager.go | 75 ++++++++++++++++++- 4 files changed, 91 insertions(+), 38 deletions(-) diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 08401a0366e..1a8b46c1646 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -377,13 +377,8 @@ func runAction(cmd *cobra.Command, args []string) error { id := c.ID() if createOpt.Rm && !createOpt.Detach { defer func() { - // NOTE: OCI hooks (which are used for CNI network setup/teardown on Linux) - // are not currently supported on Windows, so we must explicitly call - // network setup/cleanup from the main nerdctl executable. - if runtime.GOOS == "windows" { - if err := netManager.CleanupNetworking(ctx, c); err != nil { - log.L.Warnf("failed to clean up container networking: %s", err) - } + if err := netManager.CleanupNetworking(ctx, c); err != nil { + log.L.Warnf("failed to clean up container networking: %s", err) } if err := container.RemoveContainer(ctx, c, createOpt.GOptions, true, true, client); err != nil { log.L.WithError(err).Warnf("failed to remove container %s", id) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index d1ed52e371e..87b85bf3145 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -316,10 +316,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa c, containerErr := client.NewContainer(ctx, id, cOpts...) var netSetupErr error - // NOTE: on non-Windows platforms, network setup is performed by OCI hooks. - // Seeing as though Windows does not currently support OCI hooks, we must explicitly - // perform network setup/teardown in the main nerdctl executable. - if containerErr == nil && runtime.GOOS == "windows" { + if containerErr == nil { netSetupErr = netManager.SetupNetworking(ctx, id) if netSetupErr != nil { log.G(ctx).WithError(netSetupErr).Warnf("networking setup error has occurred") diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 78caa7e41cb..93bd16c0255 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -22,7 +22,6 @@ import ( "errors" "fmt" "os" - "runtime" "syscall" containerd "github.com/containerd/containerd/v2/client" @@ -168,31 +167,26 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions delOpts = append(delOpts, containerd.WithSnapshotCleanup) } - // NOTE: on non-Windows platforms, network cleanup is performed by OCI hooks. - // Seeing as though Windows does not currently support OCI hooks, we must explicitly - // perform the network cleanup from the main nerdctl executable. - if runtime.GOOS == "windows" { - spec, err := c.Spec(ctx) - if err != nil { - retErr = err - return - } + spec, err := c.Spec(ctx) + if err != nil { + retErr = err + return + } - netOpts, err := containerutil.NetworkOptionsFromSpec(spec) - if err != nil { - retErr = fmt.Errorf("failed to load container networking options from specs: %s", err) - return - } + netOpts, err := containerutil.NetworkOptionsFromSpec(spec) + if err != nil { + retErr = fmt.Errorf("failed to load container networking options from specs: %s", err) + return + } - networkManager, err := containerutil.NewNetworkingOptionsManager(globalOptions, netOpts, client) - if err != nil { - retErr = fmt.Errorf("failed to instantiate network options manager: %s", err) - return - } + networkManager, err := containerutil.NewNetworkingOptionsManager(globalOptions, netOpts, client) + if err != nil { + retErr = fmt.Errorf("failed to instantiate network options manager: %s", err) + return + } - if err := networkManager.CleanupNetworking(ctx, c); err != nil { - log.G(ctx).WithError(err).Warnf("failed to clean up container networking: %q", id) - } + if err := networkManager.CleanupNetworking(ctx, c); err != nil { + log.G(ctx).WithError(err).Warnf("failed to clean up container networking: %q", id) } // Delete the container now. If it fails, try again without snapshot cleanup diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 1b1c0e03c6b..fa303ad3e9c 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -366,15 +366,82 @@ func (m *hostNetworkManager) VerifyNetworkOptions(_ context.Context) error { } // SetupNetworking Performs setup actions required for the container with the given ID. -func (m *hostNetworkManager) SetupNetworking(_ context.Context, _ string) error { - // NOTE: there are no setup steps required for host networking. +func (m *hostNetworkManager) SetupNetworking(ctx context.Context, containerID string) error { + // Retrieve the container + container, err := m.client.ContainerService().Get(ctx, containerID) + if err != nil { + return err + } + + // Get the dataStore + dataStore, err := clientutil.DataStore(m.globalOptions.DataRoot, m.globalOptions.Address) + if err != nil { + return err + } + + // Get the hostsStore + hs, err := hostsstore.NewStore(dataStore) + if err != nil { + return err + } + + // Get extra-hosts + extraHostsJSON := container.Labels[labels.ExtraHosts] + var extraHosts []string + if err = json.Unmarshal([]byte(extraHostsJSON), &extraHosts); err != nil { + return err + } + + hosts := make(map[string]string) + for _, host := range extraHosts { + if v := strings.SplitN(host, ":", 2); len(v) == 2 { + hosts[v[0]] = v[1] + } + } + + // Prep the meta + hsMeta := hostsstore.Meta{ + Namespace: container.Labels[labels.Namespace], + ID: container.ID, + Hostname: container.Labels[labels.Hostname], + ExtraHosts: hosts, + Name: container.Labels[labels.Name], + } + + // Save the meta information + if err = hs.Acquire(hsMeta); err != nil { + return err + } + return nil } // CleanupNetworking Performs any required cleanup actions for the given container. // Should only be called to revert any setup steps performed in SetupNetworking. -func (m *hostNetworkManager) CleanupNetworking(_ context.Context, _ containerd.Container) error { - // NOTE: there are no setup steps required for host networking. +func (m *hostNetworkManager) CleanupNetworking(ctx context.Context, container containerd.Container) error { + // Get the dataStore + dataStore, err := clientutil.DataStore(m.globalOptions.DataRoot, m.globalOptions.Address) + if err != nil { + return err + } + + // Get the hostsStore + hs, err := hostsstore.NewStore(dataStore) + if err != nil { + return err + } + + // Get labels + lbls, err := container.Labels(ctx) + if err != nil { + return err + } + + // Release + if err = hs.Release(lbls[labels.Namespace], container.ID()); err != nil { + return err + } + return nil } From f7b71e9cfba4ca639fc550ab46fdfbebfba8cad7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 22 Aug 2024 00:16:07 -0700 Subject: [PATCH 0681/1066] Add regression tests for network host Signed-off-by: apostasie --- .../container_run_network_linux_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index 9615529146c..2321df8927b 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "net" + "os" "regexp" "runtime" "strings" @@ -423,6 +424,24 @@ func TestRunDNS(t *testing.T) { cmd.AssertOutContains("options attempts:10\n") } +func TestRunNetworkHostHostname(t *testing.T) { + base := testutil.NewBase(t) + + hostname, err := os.Hostname() + assert.NilError(t, err) + hostname = hostname + "\n" + base.Cmd("run", "--rm", "--network", "host", testutil.CommonImage, "hostname").AssertOutExactly(hostname) + base.Cmd("run", "--rm", "--network", "host", testutil.CommonImage, "sh", "-euxc", "echo $HOSTNAME").AssertOutExactly(hostname) + base.Cmd("run", "--rm", "--network", "host", "--hostname", "override", testutil.CommonImage, "hostname").AssertOutExactly("override\n") + base.Cmd("run", "--rm", "--network", "host", "--hostname", "override", testutil.CommonImage, "sh", "-euxc", "echo $HOSTNAME").AssertOutExactly("override\n") +} + +func TestRunNetworkHost2613(t *testing.T) { + base := testutil.NewBase(t) + + base.Cmd("run", "--rm", "--add-host", "foo:1.2.3.4", testutil.CommonImage, "getent", "hosts", "foo").AssertOutExactly("1.2.3.4 foo foo\n") +} + func TestSharedNetworkStack(t *testing.T) { if runtime.GOOS != "linux" { t.Skip("--network=container: only supports linux now") From 67449bca65da0cec084db286296ae51d5bc0495b Mon Sep 17 00:00:00 2001 From: curlwget Date: Thu, 22 Aug 2024 17:14:27 +0800 Subject: [PATCH 0682/1066] chore: fix some function names Signed-off-by: curlwget --- cmd/nerdctl/compose_ps.go | 2 +- pkg/netutil/netutil_unix.go | 2 +- pkg/testutil/testutil.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose_ps.go index 08b2040dce7..b58f3cfc0ff 100644 --- a/cmd/nerdctl/compose_ps.go +++ b/cmd/nerdctl/compose_ps.go @@ -262,7 +262,7 @@ func composeContainerPrintableTab(ctx context.Context, container containerd.Cont }, nil } -// composeContainerPrintableTab constructs composeContainerPrintable with fields +// composeContainerPrintableJSON constructs composeContainerPrintable with fields // only for json output and compatible docker output. func composeContainerPrintableJSON(ctx context.Context, container containerd.Container) (composeContainerPrintable, error) { info, err := container.Info(ctx, containerd.WithoutRefreshedMetadata) diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index 9571ab28a7e..df62145f632 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -310,7 +310,7 @@ func firewallPluginGEQ110(firewallPath string) (bool, error) { return ver.GreaterThan(ver110) || ver.Equal(ver110), nil } -// guesssFirewallPluginVersion guess the version of the CNI firewall plugin (not the version of the implemented CNI spec). +// guessFirewallPluginVersion guess the version of the CNI firewall plugin (not the version of the implemented CNI spec). // // stderr is like "CNI firewall plugin v1.1.0\n", or "CNI firewall plugin version unknown\n" func guessFirewallPluginVersion(stderr string) (*semver.Version, error) { diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index cbc476e8767..6b6ea140bf6 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -794,7 +794,7 @@ func KubectlHelper(base *Base, args ...string) *Cmd { } } -// SetupDockerContinerBuilder creates a Docker builder using the docker-container driver +// SetupDockerContainerBuilder creates a Docker builder using the docker-container driver // and adds cleanup steps to test cleanup. The builder name is returned as output. // // If not docker, this function returns an empty string as the builder name. From 439086fb1b29a022286474744fd6f4be732653b6 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Mon, 19 Aug 2024 17:14:53 +0000 Subject: [PATCH 0683/1066] Fix image prune filter until test rmi cleanup not running. Signed-off-by: Austin Vazquez --- cmd/nerdctl/image_prune_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/image_prune_test.go b/cmd/nerdctl/image_prune_test.go index 0f9f423a4d7..d0772b8a33f 100644 --- a/cmd/nerdctl/image_prune_test.go +++ b/cmd/nerdctl/image_prune_test.go @@ -107,7 +107,12 @@ func TestImagePruneFilterUntil(t *testing.T) { base := testutil.NewBase(t) imageName := testutil.Identifier(t) - t.Cleanup(func() { base.Cmd("rmi", "--force", imageName) }) + teardown := func() { + // Image should have been pruned; but cleanup on failure. + base.Cmd("rmi", "--force", imageName).Run() + } + t.Cleanup(teardown) + teardown() dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune-filter-until"]`, testutil.CommonImage) From 6362afc1693bf6d5076fab9608ff120e33ea6b3d Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Sat, 17 Aug 2024 18:22:00 +0000 Subject: [PATCH 0684/1066] Remove Docker incompat from image prune and build tests Signed-off-by: Austin Vazquez --- cmd/nerdctl/builder_build_test.go | 1 - cmd/nerdctl/image_prune_test.go | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index f187fe6441b..774bf02d5b2 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -462,7 +462,6 @@ RUN ["cat", "/hello_from_dir2.txt"]`, testutil.CommonImage, filename) // https://github.com/docker/buildx/pull/1482 func TestBuildSourceDateEpoch(t *testing.T) { testutil.RequiresBuild(t) - testutil.DockerIncompatible(t) // Needs buildx v0.10 (https://github.com/docker/buildx/pull/1489) base := testutil.NewBase(t) imageName := testutil.Identifier(t) defer base.Cmd("rmi", imageName).AssertOK() diff --git a/cmd/nerdctl/image_prune_test.go b/cmd/nerdctl/image_prune_test.go index d0772b8a33f..17d7ec038a9 100644 --- a/cmd/nerdctl/image_prune_test.go +++ b/cmd/nerdctl/image_prune_test.go @@ -102,10 +102,10 @@ func TestImagePruneFilterUntil(t *testing.T) { testutil.RequiresBuild(t) testutil.RegisterBuildCacheCleanup(t) - // Docker image's created timestamp is set based on base image creation time. - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) + // For deterministically testing the filter, set the image's created timestamp to 2 hours in the past. + base.Env = append(base.Env, fmt.Sprintf("SOURCE_DATE_EPOCH=%d", time.Now().Add(-2*time.Hour).Unix())) + imageName := testutil.Identifier(t) teardown := func() { // Image should have been pruned; but cleanup on failure. From 0cd936b50df602274655f965e786e0748e360a07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 22:05:29 +0000 Subject: [PATCH 0685/1066] build(deps): bump github.com/vishvananda/netlink Bumps [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink) from 1.2.1-beta.2 to 1.2.1. - [Release notes](https://github.com/vishvananda/netlink/releases) - [Commits](https://github.com/vishvananda/netlink/compare/v1.2.1-beta.2...v1.2.1) --- updated-dependencies: - dependency-name: github.com/vishvananda/netlink dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index cc851da6b00..bfd3731ee42 100644 --- a/go.mod +++ b/go.mod @@ -61,7 +61,7 @@ require ( github.com/rootless-containers/rootlesskit/v2 v2.3.1 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 - github.com/vishvananda/netlink v1.2.1-beta.2 + github.com/vishvananda/netlink v1.2.1 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 diff --git a/go.sum b/go.sum index 86bf558069c..be94fe65418 100644 --- a/go.sum +++ b/go.sum @@ -304,9 +304,8 @@ github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiY github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= -github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= -github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netlink v1.2.1 h1:pfLv/qlJUwOTPvtWREA7c3PI4u81YkqZw1DYhI2HmLA= +github.com/vishvananda/netlink v1.2.1/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -375,16 +374,16 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= From 2327cc851de434ba8abf88dd82bcfe968be6ff9c Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 21 Aug 2024 15:08:56 -0700 Subject: [PATCH 0686/1066] Fix docker hub lag on golang versions breaking canary Signed-off-by: apostasie --- hack/build-integration-canary.sh | 76 ++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/hack/build-integration-canary.sh b/hack/build-integration-canary.sh index 4718e3adde1..32fdfb3d249 100755 --- a/hack/build-integration-canary.sh +++ b/hack/build-integration-canary.sh @@ -293,40 +293,58 @@ canary::build::integration(){ docker_args+=(--build-arg "${shortsafename}_VERSION=$higher_readable") done - - GO_VERSION="$(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version)" - GO_VERSION="${GO_VERSION##*go}" - # If a release candidate, docker hub may not have the corresponding image yet. - # So, soften the version to just "rc", as they provide that as an alias to the latest available rc on their side - # See https://github.com/containerd/nerdctl/issues/3223 - ! grep -Eq "rc[0-9]+$" <<<"$GO_VERSION" || GO_VERSION="${GO_VERSION%rc[0-9]*}-rc" - docker_args+=(--build-arg "GO_VERSION=$GO_VERSION") + hub_available_go_version="$(canary::golang::hublatest)" + if [ "$hub_available_go_version" != "" ]; then + docker_args+=(--build-arg "GO_VERSION=$hub_available_go_version") + fi log::debug "${docker_args[*]} ." "${docker_args[@]}" "." } +# Hub usually has a delay before available golang version show-up. This method will find the latest available one. +# See +# - https://github.com/containerd/nerdctl/issues/3224 +# - https://github.com/containerd/nerdctl/issues/3306 +canary::golang::hublatest(){ + local hub_tags + local go_version + local available_version="" + local index + + hub_tags="$(http::get /dev/stdout "https://registry-1.docker.io/v2/library/golang/tags/list" -H "Authorization: Bearer $(http::get /dev/stdout "https://auth.docker.io/token?service=registry.docker.io&scope=repository%3Alibrary%2Fgolang%3Apull" | jq -rc .access_token)")" + + index=0 + while [ "$available_version" == "" ] && [ "$index" -lt 5 ]; do + go_version="$(http::get /dev/stdout "https://go.dev/dl/?mode=json&include=all" | jq -rc .[$index].version)" + go_version="${go_version##*go}" + available_version="$(printf "%s" "$hub_tags" | jq -rc ".tags[] | select(.==\"$go_version\")")" + ((index++)) + done || true + + printf "%s" "$available_version" +} canary::golang::latest(){ - # Enable extended globbing features to use advanced pattern matching - shopt -s extglob + # Enable extended globbing features to use advanced pattern matching + shopt -s extglob - # Get latest golang version and split it in components - norm=() - while read -r line; do - line_trimmed="${line//+([[:space:]])/}" - norm+=("$line_trimmed") - done < \ - <(sed -E 's/^go([0-9]+)[.]([0-9]+)([.]([0-9]+))?(([a-z]+)([0-9]+))?/\1.\2\n\4\n\6\n\7/i' \ - <(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version) \ - ) - - # Serialize version, making sure we have a patch version, and separate possible rcX into .rc-X - [ "${norm[1]}" != "" ] || norm[1]="0" - norm[1]=".${norm[1]}" - [ "${norm[2]}" == "" ] || norm[2]="-${norm[2]}" - [ "${norm[3]}" == "" ] || norm[3]=".${norm[3]}" - # Save it - IFS= - echo "GO_VERSION=${norm[*]}" >> "$GITHUB_ENV" -} \ No newline at end of file + # Get latest golang version and split it in components + norm=() + while read -r line; do + line_trimmed="${line//+([[:space:]])/}" + norm+=("$line_trimmed") + done < \ + <(sed -E 's/^go([0-9]+)[.]([0-9]+)([.]([0-9]+))?(([a-z]+)([0-9]+))?/\1.\2\n\4\n\6\n\7/i' \ + <(curl -fsSL "https://go.dev/dl/?mode=json&include=all" | jq -rc .[0].version) \ + ) + + # Serialize version, making sure we have a patch version, and separate possible rcX into .rc-X + [ "${norm[1]}" != "" ] || norm[1]="0" + norm[1]=".${norm[1]}" + [ "${norm[2]}" == "" ] || norm[2]="-${norm[2]}" + [ "${norm[3]}" == "" ] || norm[3]=".${norm[3]}" + # Save it + IFS= + echo "GO_VERSION=${norm[*]}" >> "$GITHUB_ENV" +} From fc31dcd28a15dc073e3ee70d6dbf8dd402d35396 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 22 Aug 2024 21:22:43 -0700 Subject: [PATCH 0687/1066] Ignore Signed-off-by: apostasie --- pkg/cmd/container/create.go | 6 ------ pkg/ocihook/ocihook.go | 11 +---------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 71c93b50272..c83f572759b 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -509,12 +509,6 @@ func withNerdctlOCIHook(cmd string, args []string) (oci.SpecOpts, error) { Args: crArgs, Env: os.Environ(), }) - scArgs := append(args, "startContainer") - s.Hooks.CreateRuntime = append(s.Hooks.StartContainer, specs.Hook{ - Path: cmd, - Args: scArgs, - Env: os.Environ(), - }) argsCopy := append([]string(nil), args...) psArgs := append(argsCopy, "postStop") s.Hooks.Poststop = append(s.Hooks.Poststop, specs.Hook{ diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index f59ced29ec2..07251e85acd 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -99,8 +99,6 @@ func Run(stdin io.Reader, stderr io.Writer, event, dataStore, cniPath, cniNetcon switch event { case "createRuntime": return onCreateRuntime(opts) - case "startContainer": - return onStartContainer(opts) case "postStop": return onPostStop(opts) default: @@ -486,18 +484,11 @@ func applyNetworkSettings(opts *handlerOpts) error { func onCreateRuntime(opts *handlerOpts) error { loadAppArmor() - if opts.cni != nil { - return applyNetworkSettings(opts) - } - return nil -} - -func onStartContainer(opts *handlerOpts) error { name := opts.state.Annotations[labels.Name] ns := opts.state.Annotations[labels.Namespace] namst, err := namestore.New(opts.dataStore, ns) if err != nil { - log.L.WithError(err).Error("failed opening the namestore in onStartContainer") + log.L.WithError(err).Error("failed opening the namestore in onCreateRuntime") } else if err := namst.Acquire(name, opts.state.ID); err != nil { log.L.WithError(err).Error("failed re-acquiring name - see https://github.com/containerd/nerdctl/issues/2992") } From 5f30141f22cf9326d98f3f20d42b1ed44caeff99 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 21 Aug 2024 19:50:07 -0700 Subject: [PATCH 0688/1066] Rollback rename in case of error Signed-off-by: apostasie --- pkg/cmd/container/rename.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/pkg/cmd/container/rename.go b/pkg/cmd/container/rename.go index a9af9b6248a..6c967243b79 100644 --- a/pkg/cmd/container/rename.go +++ b/pkg/cmd/container/rename.go @@ -68,25 +68,40 @@ func Rename(ctx context.Context, client *containerd.Client, containerID, newCont } func renameContainer(ctx context.Context, container containerd.Container, newName, ns string, - namst namestore.NameStore, hostst hostsstore.Store) error { + namst namestore.NameStore, hostst hostsstore.Store) (err error) { l, err := container.Labels(ctx) if err != nil { return err } name := l[labels.Name] - if err := namst.Rename(name, container.ID(), newName); err != nil { + + id := container.ID() + + defer func() { + // If we errored, rollback whatever we can + if err != nil { + lbls := map[string]string{ + labels.Name: name, + } + namst.Rename(newName, id, name) + hostst.Update(ns, id, name) + container.SetLabels(ctx, lbls) + } + }() + + if err = namst.Rename(name, id, newName); err != nil { return err } if runtime.GOOS == "linux" { - if err := hostst.Update(ns, container.ID(), newName); err != nil { + if err = hostst.Update(ns, id, newName); err != nil { log.G(ctx).WithError(err).Warn("failed to update host networking definitions " + "- if your container is using network 'none', this is expected - otherwise, please report this as a bug") } } - labels := map[string]string{ + lbls := map[string]string{ labels.Name: newName, } - if _, err = container.SetLabels(ctx, labels); err != nil { + if _, err = container.SetLabels(ctx, lbls); err != nil { return err } return nil From 571799fb2421a1588cd173301410d3c49a9847a7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 23 Aug 2024 13:57:15 -0700 Subject: [PATCH 0689/1066] stop: do not error on created containers (fix #3353) Signed-off-by: apostasie --- pkg/containerutil/containerutil.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 310955630e1..3e1af0cb9e6 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -37,6 +37,7 @@ import ( "github.com/containerd/containerd/v2/core/runtime/restart" "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/consoleutil" @@ -371,6 +372,13 @@ func Stop(ctx context.Context, container containerd.Container, timeout *time.Dur task, err := container.Task(ctx, cio.Load) if err != nil { + // NOTE: NotFound doesn't mean that container hasn't started. + // In docker/CRI-containerd plugin, the task will be deleted + // when it exits. So, the status will be "created" for this + // case. + if errdefs.IsNotFound(err) { + return nil + } return err } From 31debef4a09dbb34ccf566d17fcc45a5aad44168 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:21:53 +0000 Subject: [PATCH 0690/1066] build(deps): bump github.com/containerd/containerd/api Bumps the containerd group with 1 update: [github.com/containerd/containerd/api](https://github.com/containerd/containerd). Updates `github.com/containerd/containerd/api` from 1.8.0-rc.2 to 1.8.0-rc.3 - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/api/v1.8.0-rc.2...api/v1.8.0-rc.3) --- updated-dependencies: - dependency-name: github.com/containerd/containerd/api dependency-type: direct:production update-type: version-update:semver-patch dependency-group: containerd ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bfd3731ee42..602f9c5c75c 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/containerd/accelerated-container-image v1.2.0 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd/api v1.8.0-rc.2 + github.com/containerd/containerd/api v1.8.0-rc.3 github.com/containerd/containerd/v2 v2.0.0-rc.3 github.com/containerd/continuity v0.4.3 github.com/containerd/errdefs v0.1.0 diff --git a/go.sum b/go.sum index be94fe65418..c56629351f8 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGD github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= 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/api v1.8.0-rc.2 h1:EnWLDKWWbIRzuy71L20P3VF/DhxSaDEocsovKPdW5Oo= -github.com/containerd/containerd/api v1.8.0-rc.2/go.mod h1:VgMSK19YOLolP4a1/b5vlVkTo8MzMoLPZnvD1PNWeGg= +github.com/containerd/containerd/api v1.8.0-rc.3 h1:q9MyeXmuAGEyKmUGYvvFftNX1RQhfTLsAvYK+SQHQso= +github.com/containerd/containerd/api v1.8.0-rc.3/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/v2 v2.0.0-rc.3 h1:rRISeKYnunLx8Byw8FQ/a62mTMtcr6ESGptS4+MwLaQ= github.com/containerd/containerd/v2 v2.0.0-rc.3/go.mod h1:UBHR1DgWRQcEOINFkR94m0VC0MgKd3qg9LVPnudv9vs= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= From 93586e60c263b9456b44e8bdf8ae6100f4c889c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:22:06 +0000 Subject: [PATCH 0691/1066] build(deps): bump github.com/pelletier/go-toml/v2 from 2.2.2 to 2.2.3 Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.2.2 to 2.2.3. - [Release notes](https://github.com/pelletier/go-toml/releases) - [Changelog](https://github.com/pelletier/go-toml/blob/v2/.goreleaser.yaml) - [Commits](https://github.com/pelletier/go-toml/compare/v2.2.2...v2.2.3) --- updated-dependencies: - dependency-name: github.com/pelletier/go-toml/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index bfd3731ee42..8b391343387 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/runtime-spec v1.2.0 - github.com/pelletier/go-toml/v2 v2.2.2 + github.com/pelletier/go-toml/v2 v2.2.3 github.com/rootless-containers/bypass4netns v0.4.1 github.com/rootless-containers/rootlesskit/v2 v2.3.1 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index be94fe65418..af584d96a52 100644 --- a/go.sum +++ b/go.sum @@ -253,8 +253,8 @@ github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go. github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= -github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -285,16 +285,14 @@ github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLy 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= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= From 42adca9fc11ad399755baa6f9c7acf96ee9c4b7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:22:11 +0000 Subject: [PATCH 0692/1066] build(deps): bump github.com/vishvananda/netlink from 1.2.1 to 1.3.0 Bumps [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink) from 1.2.1 to 1.3.0. - [Release notes](https://github.com/vishvananda/netlink/releases) - [Commits](https://github.com/vishvananda/netlink/compare/v1.2.1...v1.3.0) --- updated-dependencies: - dependency-name: github.com/vishvananda/netlink dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bfd3731ee42..25232bd034d 100644 --- a/go.mod +++ b/go.mod @@ -61,7 +61,7 @@ require ( github.com/rootless-containers/rootlesskit/v2 v2.3.1 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 - github.com/vishvananda/netlink v1.2.1 + github.com/vishvananda/netlink v1.3.0 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 diff --git a/go.sum b/go.sum index be94fe65418..169090a93ea 100644 --- a/go.sum +++ b/go.sum @@ -304,8 +304,8 @@ github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiY github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= -github.com/vishvananda/netlink v1.2.1 h1:pfLv/qlJUwOTPvtWREA7c3PI4u81YkqZw1DYhI2HmLA= -github.com/vishvananda/netlink v1.2.1/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= +github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= +github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= From f9b56614c6498f7de43facd513385673460dd932 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 24 Aug 2024 01:17:40 +0000 Subject: [PATCH 0693/1066] build(deps): bump github.com/containerd/accelerated-container-image Bumps [github.com/containerd/accelerated-container-image](https://github.com/containerd/accelerated-container-image) from 1.2.0 to 1.2.1. - [Release notes](https://github.com/containerd/accelerated-container-image/releases) - [Commits](https://github.com/containerd/accelerated-container-image/compare/v1.2.0...v1.2.1) --- updated-dependencies: - dependency-name: github.com/containerd/accelerated-container-image dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 602f9c5c75c..eeb48ac9259 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.6 github.com/compose-spec/compose-go/v2 v2.1.6 - github.com/containerd/accelerated-container-image v1.2.0 + github.com/containerd/accelerated-container-image v1.2.1 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0-rc.3 diff --git a/go.sum b/go.sum index c56629351f8..af917f5b4b3 100644 --- a/go.sum +++ b/go.sum @@ -25,8 +25,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/v2 v2.1.6 h1:d0Cs0DffmOwmSzs0YPHwKCskknGq2jfGg4uGowlEpps= github.com/compose-spec/compose-go/v2 v2.1.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= -github.com/containerd/accelerated-container-image v1.2.0 h1:txvvjckuXjIqsKpaPfDwGcGmjwH+TJDrvUuOswEBCTg= -github.com/containerd/accelerated-container-image v1.2.0/go.mod h1:BbY0iTEYD6XZV84E99yjUbs46EGI0CVQrjqb/Wgx9nE= +github.com/containerd/accelerated-container-image v1.2.1 h1:ODV7nD5o5VmHIZT1OzadRQxOBLnQWnvSEouG6hFh6hA= +github.com/containerd/accelerated-container-image v1.2.1/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= From f353afb643c2421762915dff568c330de7336b57 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 23 Aug 2024 14:01:46 -0700 Subject: [PATCH 0694/1066] Allow containers to re-acquire their own name (fix #3354) Signed-off-by: apostasie --- pkg/namestore/namestore.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/namestore/namestore.go b/pkg/namestore/namestore.go index 227a08a494c..5243a8f958a 100644 --- a/pkg/namestore/namestore.go +++ b/pkg/namestore/namestore.go @@ -56,7 +56,11 @@ func (x *nameStore) Acquire(name, id string) error { } fn := func() error { fileName := filepath.Join(x.dir, name) - if b, err := os.ReadFile(fileName); err == nil { + // If containerd was bounced, previously running containers that would get restarted will go again through + // onCreateRuntime (unlike in a "normal" stop/start flow). + // As such, we need to allow reacquiring by the same id + // See: https://github.com/containerd/nerdctl/issues/3354 + if b, err := os.ReadFile(fileName); err == nil && string(b) != id { return fmt.Errorf("name %q is already used by ID %q", name, string(b)) } return os.WriteFile(fileName, []byte(id), 0600) From 971040e76577dc8fc08b386b04bbc6d6b35f002a Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 23 Aug 2024 22:02:13 -0700 Subject: [PATCH 0695/1066] Release any existing ip lease onCreateRuntime (workaround #3355) Signed-off-by: apostasie --- pkg/ocihook/ocihook.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 07251e85acd..f8afc6c7c18 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -443,6 +443,18 @@ func applyNetworkSettings(opts *handlerOpts) error { ExtraHosts: opts.extraHosts, Name: opts.state.Annotations[labels.Name], } + + // When containerd gets bounced, containers that were previously running and that are restarted will go again + // through onCreateRuntime (*unlike* in a normal stop/start flow). + // As such, a container may very well have an ip already. The bridge plugin would thus refuse to loan a new one + // and error out, thus making the onCreateRuntime hook fail. In turn, runc (or containerd) will mis-interpret this, + // and subsequently call onPostStop (although the container will not get deleted), and we will release the name... + // leading to a bricked system where multiple containers may share the same name. + // Thus, we do pre-emptively clean things up - error is not checked, as in the majority of cases, that would + // legitimately error (and that does not matter) + // See https://github.com/containerd/nerdctl/issues/3355 + _ = opts.cni.Remove(ctx, opts.fullID, "", namespaceOpts...) + cniRes, err := opts.cni.Setup(ctx, opts.fullID, nsPath, namespaceOpts...) if err != nil { return fmt.Errorf("failed to call cni.Setup: %w", err) From 31989a2d27bebf6422fef7a66c078ab39605b5d9 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 23 Aug 2024 22:23:56 -0700 Subject: [PATCH 0696/1066] Add reg. test for 'stop created' Signed-off-by: apostasie --- cmd/nerdctl/container_stop_linux_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/cmd/nerdctl/container_stop_linux_test.go b/cmd/nerdctl/container_stop_linux_test.go index bdc17e00821..fedd791fabd 100644 --- a/cmd/nerdctl/container_stop_linux_test.go +++ b/cmd/nerdctl/container_stop_linux_test.go @@ -135,3 +135,25 @@ func TestStopCleanupForwards(t *testing.T) { base.Cmd("stop", testContainerName).AssertOK() assert.Equal(t, iptablesutil.ForwardExists(t, ipt, chain, containerIP, hostPort), false) } + +// Regression test for https://github.com/containerd/nerdctl/issues/3353 +func TestStopCreated(t *testing.T) { + t.Parallel() + + base := testutil.NewBase(t) + tID := testutil.Identifier(t) + + tearDown := func() { + base.Cmd("rm", "-f", tID).Run() + } + + setup := func() { + base.Cmd("create", "--name", tID, testutil.CommonImage).AssertOK() + } + + t.Cleanup(tearDown) + tearDown() + setup() + + base.Cmd("stop", tID).AssertOK() +} From fe6779611ff83fdd17c4275ac72e0bfd7168ccbe Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 26 Aug 2024 13:36:00 -0700 Subject: [PATCH 0697/1066] Allow Canary to fail the build Signed-off-by: apostasie --- .github/workflows/test-canary.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index e106c94ce7a..420e819e489 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -65,7 +65,6 @@ jobs: - name: "Run unit tests" run: go test -v ./pkg/... - name: "Run integration tests" - continue-on-error: true run: docker run -t --rm --privileged test-integration windows: @@ -113,5 +112,4 @@ jobs: ctrdVersion: ${{ env.CONTAINERD_VERSION }} run: powershell hack/configure-windows-ci.ps1 - name: "Run integration tests" - continue-on-error: true run: go test -v ./cmd/... From bc247660867f85ef17b7b430643ada3052311fe7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 26 Aug 2024 14:52:20 -0700 Subject: [PATCH 0698/1066] Add lint-imports to the default lint task Signed-off-by: apostasie --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cc4093818a5..685aa439169 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ clean: find . -name \#\* -delete rm -rf $(CURDIR)/_output/* $(MAKEFILE_DIR)/vendor -lint: lint-go lint-yaml lint-shell +lint: lint-go lint-imports lint-yaml lint-shell lint-go: cd $(MAKEFILE_DIR) && golangci-lint run $(VERBOSE_FLAG_LONG) ./... From 7eb1523e029b1a994392190239d379f365d493c0 Mon Sep 17 00:00:00 2001 From: Bastien Roy-Mazoyer Date: Mon, 26 Aug 2024 17:25:14 -0400 Subject: [PATCH 0699/1066] Changing bufio.Scanner to bufio.Reader to support large message From the Issue #3343 As stated in the bufio Documentation, when using the bufio.Scanner, if the buffer exceed the max size of the token, the Scanner fail silently with an I/O error. In the case of a container started with nerdctl, the main process using stdout/stderr hang forever when sending text bigger than 64kb (bufio.MaxScanTokenSize) without any newline character. (Discovered from a JSON string dumped in the logs). bufio documentation state to switch to a Reader instead when you do not have control over the size of the message. Small test that is failing with the current master but working with this fix. @apostasie recommend to check the other place in the code for the bufio.Scanner usage but I am not really a GO expert Will trim any \n if it is not EOF else, will send the data no matter and exit in case of error Signed-off-by: Bastien Roy-Mazoyer --- pkg/logging/logging.go | 22 ++++--- pkg/logging/logging_test.go | 115 ++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 pkg/logging/logging_test.go diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index 1baa4a97499..0a42cbb21be 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -26,6 +26,7 @@ import ( "os" "path/filepath" "sort" + "strings" "sync" "time" @@ -170,16 +171,23 @@ func loggingProcessAdapter(ctx context.Context, driver Driver, dataStore string, processLogFunc := func(reader io.Reader, dataChan chan string) { defer wg.Done() defer close(dataChan) - scanner := bufio.NewScanner(reader) - for scanner.Scan() { - if scanner.Err() != nil { - log.L.Errorf("failed to read log: %v", scanner.Err()) - return + r := bufio.NewReader(reader) + + var err error + + for err == nil { + var s string + s, err = r.ReadString('\n') + + if len(s) > 0 { + dataChan <- strings.TrimSuffix(s, "\n") + } + + if err != nil && err != io.EOF { + log.L.WithError(err).Error("failed to read log") } - dataChan <- scanner.Text() } } - go processLogFunc(stdoutR, stdout) go processLogFunc(stderrR, stderr) go func() { diff --git a/pkg/logging/logging_test.go b/pkg/logging/logging_test.go new file mode 100644 index 00000000000..4cec4c868cc --- /dev/null +++ b/pkg/logging/logging_test.go @@ -0,0 +1,115 @@ +/* + 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 logging + +import ( + "bufio" + "bytes" + "context" + "math/rand" + "strings" + "testing" + "time" + + "github.com/containerd/containerd/v2/core/runtime/v2/logging" +) + +type MockDriver struct { + processed bool + receivedStdout []string + receivedStderr []string +} + +func (m *MockDriver) Init(dataStore, ns, id string) error { + return nil +} + +func (m *MockDriver) PreProcess(dataStore string, config *logging.Config) error { + return nil +} + +func (m *MockDriver) Process(stdout <-chan string, stderr <-chan string) error { + for line := range stdout { + m.receivedStdout = append(m.receivedStdout, line) + } + for line := range stderr { + m.receivedStderr = append(m.receivedStderr, line) + } + m.processed = true + return nil +} + +func (m *MockDriver) PostProcess() error { + return nil +} + +func TestLoggingProcessAdapter(t *testing.T) { + // Will process a normal String to stdout and a bigger one to stderr + normalString := generateRandomString(1024) + + // Generate 64KB of random text of bufio MaxScanTokenSize + // https://github.com/containerd/nerdctl/issues/3343 + hugeString := generateRandomString(bufio.MaxScanTokenSize) + + // Prepare mock driver and logging config + driver := &MockDriver{} + stdoutBuffer := bytes.NewBufferString(normalString) + stderrBuffer := bytes.NewBufferString(hugeString) + config := &logging.Config{ + Stdout: stdoutBuffer, + Stderr: stderrBuffer, + } + + // Execute the logging process adapter + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := loggingProcessAdapter(ctx, driver, "testDataStore", config) + if err != nil { + t.Fatal(err) + } + + // let bufio read the buffer + time.Sleep(50 * time.Millisecond) + + // Verify that the driver methods were called + if !driver.processed { + t.Fatal("process should be processed") + } + + // Verify that the driver received the expected data + stdout := strings.Join(driver.receivedStdout, "\n") + stderr := strings.Join(driver.receivedStderr, "\n") + + if stdout != normalString { + t.Fatalf("stdout is %s, expected %s", stdout, normalString) + } + + if stderr != hugeString { + t.Fatalf("stderr is %s, expected %s", stderr, hugeString) + } +} + +// generateRandomString creates a random string of the given size. +func generateRandomString(size int) string { + characters := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + var sb strings.Builder + for i := 0; i < size; i++ { + sb.WriteByte(characters[rand.Intn(len(characters))]) + } + return sb.String() +} From f85bba8f45479c0f94a88e913cfce340604b70a2 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 24 Aug 2024 13:15:35 -0700 Subject: [PATCH 0700/1066] Hardening lifecycle state store Signed-off-by: apostasie --- pkg/ocihook/ocihook.go | 7 +++---- pkg/ocihook/state/state.go | 11 ++++++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index f8afc6c7c18..e37f4083a51 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -514,10 +514,9 @@ func onCreateRuntime(opts *handlerOpts) error { // Set StartedAt lf := state.NewLifecycleState(opts.state.Annotations[labels.StateDir]) return lf.WithLock(func() error { - err := lf.Load() - if err != nil { - return err - } + // Errors are voluntarily ignored here, as they should not be fatal. + // The lifecycle struct is also already warning about the issue. + _ = lf.Load() lf.StartedAt = time.Now() return lf.Save() }) diff --git a/pkg/ocihook/state/state.go b/pkg/ocihook/state/state.go index 0c0295cdd83..f3f240218fd 100644 --- a/pkg/ocihook/state/state.go +++ b/pkg/ocihook/state/state.go @@ -24,6 +24,8 @@ import ( "path/filepath" "time" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/lockutil" ) @@ -71,6 +73,8 @@ func (lf *LifecycleState) Load() error { } else { err = json.Unmarshal(data, lf) if err != nil { + // Logging an error, as Load errors are generally ignored downstream + log.L.Error("unable to unmarshall lifecycle data") return fmt.Errorf("unable to unmarshall lifecycle data: %w", err) } } @@ -78,11 +82,16 @@ func (lf *LifecycleState) Load() error { } func (lf *LifecycleState) Save() error { + // Write atomically (write, then move) to avoid incomplete writes from happening data, err := json.Marshal(lf) if err != nil { return fmt.Errorf("unable to marshall lifecycle data: %w", err) } - err = os.WriteFile(filepath.Join(lf.stateDir, lifecycleFile), data, 0600) + err = os.WriteFile(filepath.Join(lf.stateDir, "."+lifecycleFile), data, 0600) + if err != nil { + return fmt.Errorf("unable to write lifecycle file: %w", err) + } + err = os.Rename(filepath.Join(lf.stateDir, "."+lifecycleFile), filepath.Join(lf.stateDir, lifecycleFile)) if err != nil { return fmt.Errorf("unable to write lifecycle file: %w", err) } From 6296bb35e28db9e35e37346292939ea898d787a0 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 24 Aug 2024 16:49:03 -0700 Subject: [PATCH 0701/1066] Namestore hardening, workaround #3351 Signed-off-by: apostasie --- pkg/namestore/namestore.go | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/pkg/namestore/namestore.go b/pkg/namestore/namestore.go index 5243a8f958a..a6b57968c82 100644 --- a/pkg/namestore/namestore.go +++ b/pkg/namestore/namestore.go @@ -22,6 +22,8 @@ import ( "path/filepath" "strings" + "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/lockutil" ) @@ -56,12 +58,21 @@ func (x *nameStore) Acquire(name, id string) error { } fn := func() error { fileName := filepath.Join(x.dir, name) - // If containerd was bounced, previously running containers that would get restarted will go again through - // onCreateRuntime (unlike in a "normal" stop/start flow). - // As such, we need to allow reacquiring by the same id - // See: https://github.com/containerd/nerdctl/issues/3354 - if b, err := os.ReadFile(fileName); err == nil && string(b) != id { - return fmt.Errorf("name %q is already used by ID %q", name, string(b)) + if b, err := os.ReadFile(fileName); err == nil { + if strings.TrimSpace(string(b)) == "" { + // currently acquired for an empty id - this obviously should never happen + // this is recoverable, and we are not hard erroring, but still indicative that something was wrong + // https://github.com/containerd/nerdctl/issues/3351 + log.L.Errorf("current name %q is reserved for a an empty id - please report this is as a bug", name) + } else if string(b) != id { + // if acquired by a different container, we error out here + return fmt.Errorf("name %q is already used by ID %q", name, string(b)) + } + // Otherwise, this is just re-acquiring after a restart + // For example, if containerd was bounced, previously running containers that would get restarted will go + // again through onCreateRuntime (unlike in a "normal" stop/start flow). + // As such, we are allowing reacquiring by the same id + // See: https://github.com/containerd/nerdctl/issues/3354 } return os.WriteFile(fileName, []byte(id), 0600) } From b954c7a3e7739a7492d631f23c34292e7748c017 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 24 Aug 2024 20:59:24 -0700 Subject: [PATCH 0702/1066] Prevent presumably bogus reentrancy onPostStop when onCreateRuntime errored Signed-off-by: apostasie --- pkg/ocihook/ocihook.go | 25 +++++++++++++++++++------ pkg/ocihook/state/state.go | 5 +++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index e37f4083a51..922e6ff8c96 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -505,24 +505,37 @@ func onCreateRuntime(opts *handlerOpts) error { log.L.WithError(err).Error("failed re-acquiring name - see https://github.com/containerd/nerdctl/issues/2992") } + var netError error if opts.cni != nil { - if err = applyNetworkSettings(opts); err != nil { - return err - } + netError = applyNetworkSettings(opts) } - // Set StartedAt lf := state.NewLifecycleState(opts.state.Annotations[labels.StateDir]) - return lf.WithLock(func() error { + + return errors.Join(netError, lf.WithLock(func() error { // Errors are voluntarily ignored here, as they should not be fatal. // The lifecycle struct is also already warning about the issue. _ = lf.Load() lf.StartedAt = time.Now() + lf.CreateError = netError != nil return lf.Save() - }) + })) } func onPostStop(opts *handlerOpts) error { + // See https://github.com/containerd/nerdctl/issues/3357 + // Check if we actually errored during runtimeCreate + // If that is the case, CreateError is set, and we are in postStop while the container will NOT be deleted (see ticket). + // In that case, do NOT treat this as a deletion, as the container is still there. + // Reset CreateError, and return. + lf := state.NewLifecycleState(opts.state.Annotations[labels.StateDir]) + if lf.WithLock(lf.Load) == nil { + if lf.CreateError { + lf.CreateError = false + return lf.WithLock(lf.Save) + } + } + ctx := context.Background() ns := opts.state.Annotations[labels.Namespace] if opts.cni != nil { diff --git a/pkg/ocihook/state/state.go b/pkg/ocihook/state/state.go index f3f240218fd..312bf973556 100644 --- a/pkg/ocihook/state/state.go +++ b/pkg/ocihook/state/state.go @@ -51,8 +51,9 @@ func NewLifecycleState(stateDir string) *LifecycleState { } type LifecycleState struct { - stateDir string - StartedAt time.Time `json:"started_at"` + stateDir string + StartedAt time.Time `json:"started_at"` + CreateError bool `json:"create_error"` } func (lf *LifecycleState) WithLock(fun func() error) error { From fee2b0170b4ecbb257eb6ba547abb2b8d0c88efb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 22:22:47 +0000 Subject: [PATCH 0703/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.1.2+incompatible to 27.2.0+incompatible - [Commits](https://github.com/docker/cli/compare/v27.1.2...v27.2.0) Updates `github.com/docker/docker` from 27.1.2+incompatible to 27.2.0+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.1.2...v27.2.0) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index dfe99f89a55..9a2d9bc46f7 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.1 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.1.2+incompatible - github.com/docker/docker v27.1.2+incompatible + github.com/docker/cli v27.2.0+incompatible + github.com/docker/docker v27.2.0+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index fcc326737f3..4f36536d1be 100644 --- a/go.sum +++ b/go.sum @@ -88,10 +88,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.1.2+incompatible h1:nYviRv5Y+YAKx3dFrTvS1ErkyVVunKOhoweCTE1BsnI= -github.com/docker/cli v27.1.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.1.2+incompatible h1:AhGzR1xaQIy53qCkxARaFluI00WPGtXn0AJuoQsVYTY= -github.com/docker/docker v27.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.2.0+incompatible h1:yHD1QEB1/0vr5eBNpu8tncu8gWxg8EydFPOSKHzXSMM= +github.com/docker/cli v27.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= +github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 7192451f472e7076fa97765f6690fd97b9733747 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 22:22:55 +0000 Subject: [PATCH 0704/1066] build(deps): bump github.com/coreos/go-iptables from 0.7.0 to 0.8.0 Bumps [github.com/coreos/go-iptables](https://github.com/coreos/go-iptables) from 0.7.0 to 0.8.0. - [Release notes](https://github.com/coreos/go-iptables/releases) - [Commits](https://github.com/coreos/go-iptables/compare/v0.7.0...v0.8.0) --- updated-dependencies: - dependency-name: github.com/coreos/go-iptables dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dfe99f89a55..763358f61b3 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/containerd/typeurl/v2 v2.2.0 github.com/containernetworking/cni v1.2.3 github.com/containernetworking/plugins v1.5.1 - github.com/coreos/go-iptables v0.7.0 + github.com/coreos/go-iptables v0.8.0 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.1 github.com/distribution/reference v0.6.0 diff --git a/go.sum b/go.sum index fcc326737f3..609dc093a0d 100644 --- a/go.sum +++ b/go.sum @@ -71,8 +71,8 @@ github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+ github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sirVuPM= github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U= -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-iptables v0.8.0 h1:MPc2P89IhuVpLI7ETL/2tx3XZ61VeICZjYqDEgNsPRc= +github.com/coreos/go-iptables v0.8.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= From 19fb8b600040a3d9e96d178b273f583a9bd769da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 22:23:02 +0000 Subject: [PATCH 0705/1066] build(deps): bump github.com/Masterminds/semver/v3 from 3.2.1 to 3.3.0 Bumps [github.com/Masterminds/semver/v3](https://github.com/Masterminds/semver) from 3.2.1 to 3.3.0. - [Release notes](https://github.com/Masterminds/semver/releases) - [Changelog](https://github.com/Masterminds/semver/blob/master/CHANGELOG.md) - [Commits](https://github.com/Masterminds/semver/compare/v3.2.1...v3.3.0) --- updated-dependencies: - dependency-name: github.com/Masterminds/semver/v3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dfe99f89a55..7f5a051642b 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ go 1.22.0 // We should still move back to upstream in the future, and remove our copy. require ( - github.com/Masterminds/semver/v3 v3.2.1 + github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.6 github.com/compose-spec/compose-go/v2 v2.1.6 diff --git a/go.sum b/go.sum index fcc326737f3..da4df9393d8 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg6 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 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/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= 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.12.6 h1:qEnZjoHXv+4/s0LmKZWE0/AiZmMWEIkFfWBSf1a0wlU= From 68be0cefe1476d009169d20b9586282430afc231 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 27 Aug 2024 19:47:04 -0700 Subject: [PATCH 0706/1066] Disable flaky #827 test Signed-off-by: apostasie --- cmd/nerdctl/container_commit_linux_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cmd/nerdctl/container_commit_linux_test.go b/cmd/nerdctl/container_commit_linux_test.go index a18f57a5150..a2cc557c4d7 100644 --- a/cmd/nerdctl/container_commit_linux_test.go +++ b/cmd/nerdctl/container_commit_linux_test.go @@ -25,9 +25,18 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil" ) +/* +This test below is meant to assert that https://github.com/containerd/nerdctl/issues/827 is NOT fixed. +Obviously, once we fix the issue, it should be replaced by something that assert it works. +Unfortunately, this is flaky. +It will regularly succeed or fail, making random PR fail the Kube check. +*/ + func TestKubeCommitPush(t *testing.T) { t.Parallel() + t.Skip("Test that confirm that #827 is still broken is too flaky") + base := testutil.NewBaseForKubernetes(t) tID := testutil.Identifier(t) @@ -62,6 +71,7 @@ func TestKubeCommitPush(t *testing.T) { "change the expectation to 'success'.") base.Cmd("commit", containerID, "registry.example.com/my-app:v1").AssertOK() + // See note above. base.Cmd("push", "registry.example.com/my-app:v1").Assert(icmd.Expected{ ExitCode: 1, Err: "failed to create a tmp single-platform image", From abb17d722272bda1aa6a82d53852602b1f73dfe6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:16:55 +0000 Subject: [PATCH 0707/1066] build(deps): bump github.com/containerd/containerd/v2 Bumps [github.com/containerd/containerd/v2](https://github.com/containerd/containerd) from 2.0.0-rc.3 to 2.0.0-rc.4. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v2.0.0-rc.3...v2.0.0-rc.4) --- updated-dependencies: - dependency-name: github.com/containerd/containerd/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index cb105db9bc1..aebb89b9bf8 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0-rc.3 - github.com/containerd/containerd/v2 v2.0.0-rc.3 + github.com/containerd/containerd/v2 v2.0.0-rc.4 github.com/containerd/continuity v0.4.3 github.com/containerd/errdefs v0.1.0 github.com/containerd/fifo v1.1.0 diff --git a/go.sum b/go.sum index 52f99f159ca..0afe83322b8 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,8 @@ github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd/api v1.8.0-rc.3 h1:q9MyeXmuAGEyKmUGYvvFftNX1RQhfTLsAvYK+SQHQso= github.com/containerd/containerd/api v1.8.0-rc.3/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= -github.com/containerd/containerd/v2 v2.0.0-rc.3 h1:rRISeKYnunLx8Byw8FQ/a62mTMtcr6ESGptS4+MwLaQ= -github.com/containerd/containerd/v2 v2.0.0-rc.3/go.mod h1:UBHR1DgWRQcEOINFkR94m0VC0MgKd3qg9LVPnudv9vs= +github.com/containerd/containerd/v2 v2.0.0-rc.4 h1:Bvto4h5i2VZkQ+L5SrGupg5ilQ+zkVPILdjf9RWMego= +github.com/containerd/containerd/v2 v2.0.0-rc.4/go.mod h1:p35nJi4Pl9ibzuoVOPc3MputVh6Gbp9xoDg9VHz6/YI= 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= @@ -263,8 +263,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rootless-containers/bypass4netns v0.4.1 h1:zyYM1uSG7/prAphD2vlJvx/MEKK91EjD2XaefGx5PKA= From 95a3d6973e209bfbc874598ff58ba6d7894499aa Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 28 Aug 2024 15:25:13 -0700 Subject: [PATCH 0708/1066] Move testing to container v2 rc4 Signed-off-by: apostasie --- .github/workflows/test.yml | 6 +++--- Dockerfile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b269a3f3584..cddf04e6d69 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -69,10 +69,10 @@ jobs: containerd: v1.7.19 runner: "ubuntu-22.04" - ubuntu: 24.04 - containerd: v2.0.0-rc.3 + containerd: v2.0.0-rc.4 runner: "ubuntu-24.04" - ubuntu: 24.04 - containerd: v2.0.0-rc.3 + containerd: v2.0.0-rc.4 runner: github-arm64-2c-8gb env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" @@ -179,7 +179,7 @@ jobs: rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 24.04 - containerd: v2.0.0-rc.3 + containerd: v2.0.0-rc.4 rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 24.04 diff --git a/Dockerfile b/Dockerfile index 966a1d1ade4..89c6f58d6e6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v2.0.0-rc.3 +ARG CONTAINERD_VERSION=v2.0.0-rc.4 ARG RUNC_VERSION=v1.1.13 ARG CNI_PLUGINS_VERSION=v1.5.1 From 7f0dec8e43cba364f7640aef1e60062185e91fa8 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 31 Aug 2024 10:00:54 -0700 Subject: [PATCH 0709/1066] Fix nsenter working dir for child Signed-off-by: apostasie --- pkg/rootlessutil/parent_linux.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/rootlessutil/parent_linux.go b/pkg/rootlessutil/parent_linux.go index f6a519ab29d..d90b9b77dee 100644 --- a/pkg/rootlessutil/parent_linux.go +++ b/pkg/rootlessutil/parent_linux.go @@ -102,6 +102,7 @@ func ParentMain(hostGatewayIP string) error { log.L.WithError(err).Warn("unable to determine working directory") } else { args = append(args, "-w"+wd) + os.Setenv("PWD", wd) } args = append(args, "--preserve-credentials", From 5b9cf17d60c44445d14299cb50c1136085308677 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sat, 31 Aug 2024 16:11:12 -0700 Subject: [PATCH 0710/1066] Do not load build output if dest is specified Signed-off-by: apostasie --- pkg/cmd/builder/build.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 5325929f2b7..f0af327676d 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -228,7 +228,9 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option output = fmt.Sprintf("type=local,dest=%s", output) } if strings.Contains(output, "type=docker") || strings.Contains(output, "type=oci") { - needsLoading = true + if !strings.Contains(output, "dest=") { + needsLoading = true + } } } if tags = strutil.DedupeStrSlice(options.Tag); len(tags) > 0 { From 76a828dd3e90964c8928f5ef7742932136b816d2 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 15:19:07 -0700 Subject: [PATCH 0711/1066] Adapt testing so that subpackages are not parallelized Signed-off-by: apostasie --- .github/workflows/test-canary.yml | 3 ++- .github/workflows/test-kube.yml | 3 ++- .github/workflows/test.yml | 9 ++++--- Dockerfile | 15 ++++++------ Dockerfile.d/test-integration-rootless.sh | 5 +++- cmd/nerdctl/container_run_mount_linux_test.go | 1 + docs/testing.md | 24 +++++++++++++++---- pkg/testutil/testutil.go | 3 +++ 8 files changed, 45 insertions(+), 18 deletions(-) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 420e819e489..0a21c29d523 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -112,4 +112,5 @@ jobs: ctrdVersion: ${{ env.CONTAINERD_VERSION }} run: powershell hack/configure-windows-ci.ps1 - name: "Run integration tests" - run: go test -v ./cmd/... + # See https://github.com/containerd/nerdctl/blob/main/docs/testing.md#about-parallelization + run: go test -p 1 -v ./cmd/nerdctl/... diff --git a/.github/workflows/test-kube.yml b/.github/workflows/test-kube.yml index c8696a38b32..2d00b532603 100644 --- a/.github/workflows/test-kube.yml +++ b/.github/workflows/test-kube.yml @@ -22,6 +22,7 @@ jobs: with: fetch-depth: 1 - name: "Run Kubernetes integration tests" + # See https://github.com/containerd/nerdctl/blob/main/docs/testing.md#about-parallelization run: | ./hack/build-integration-kubernetes.sh - sudo ./_output/nerdctl exec nerdctl-test-control-plane bash -c -- 'export TMPDIR="$HOME"/tmp; mkdir -p "$TMPDIR"; cd /nerdctl-source; /usr/local/go/bin/go test ./cmd/nerdctl/ -test.only-kubernetes' + sudo ./_output/nerdctl exec nerdctl-test-control-plane bash -c -- 'export TMPDIR="$HOME"/tmp; mkdir -p "$TMPDIR"; cd /nerdctl-source; /usr/local/go/bin/go test -p 1 ./cmd/nerdctl/... -test.only-kubernetes' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cddf04e6d69..3567d43436c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -290,14 +290,16 @@ jobs: timeout_minutes: 30 max_attempts: 2 retry_on: error - command: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon + # See https://github.com/containerd/nerdctl/blob/main/docs/testing.md#about-parallelization + command: go test -p 1 -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon - name: "Ensure that the IPv6 integration test suite is compatible with Docker" uses: nick-fields/retry@v3 with: timeout_minutes: 30 max_attempts: 2 retry_on: error - command: go test -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon -test.only-ipv6 + # See https://github.com/containerd/nerdctl/blob/main/docs/testing.md#about-parallelization + command: go test -p 1 -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon -test.only-ipv6 test-integration-windows: runs-on: windows-2022 @@ -330,7 +332,8 @@ jobs: run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" - run: go test -v ./cmd/... + # See https://github.com/containerd/nerdctl/blob/main/docs/testing.md#about-parallelization + run: go test -p 1 -v ./cmd/nerdctl/... test-integration-freebsd: name: FreeBSD diff --git a/Dockerfile b/Dockerfile index 89c6f58d6e6..dce181d775d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -318,8 +318,8 @@ RUN curl -o nydus-static.tgz -fsSL --proto '=https' --tlsv1.2 "https://github.co tar xzf nydus-static.tgz && \ mv nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/bin/ && \ rm nydus-static.tgz -CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/v2/cmd/nerdctl/...", \ - "--", "-timeout=60m", "-args", "-test.allow-kill-daemon"] +CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=./cmd/nerdctl/...", \ + "--", "-timeout=60m", "-p", "1", "-args", "-test.allow-kill-daemon"] FROM test-integration AS test-integration-rootless # Install SSH for creating systemd user session. @@ -340,12 +340,11 @@ COPY ./Dockerfile.d/etc_systemd_system_user@.service.d_delegate.conf /etc/system # ipfs daemon for rootless containerd will be enabled in /test-integration-rootless.sh RUN systemctl disable test-integration-ipfs-offline VOLUME /home/rootless/.local/share -RUN go test -o /usr/local/bin/nerdctl.test -c ./cmd/nerdctl COPY ./Dockerfile.d/test-integration-rootless.sh / +RUN chmod a+rx /test-integration-rootless.sh CMD ["/test-integration-rootless.sh", \ - "gotestsum", "--format=testname", "--rerun-fails=2", "--raw-command", \ - "--", "/usr/local/go/bin/go", "tool", "test2json", "-t", "-p", "github.com/containerd/nerdctl/v2/cmd/nerdctl", \ - "/usr/local/bin/nerdctl.test", "-test.v", "-test.timeout=60m", "-test.allow-kill-daemon"] + "gotestsum", "--format=testname", "--rerun-fails=2", "--packages=./cmd/nerdctl/...", \ + "--", "-timeout=60m", "-p", "1", "-args", "-test.allow-kill-daemon"] # test for CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=slirp4netns FROM test-integration-rootless AS test-integration-rootless-port-slirp4netns @@ -353,7 +352,7 @@ COPY ./Dockerfile.d/home_rootless_.config_systemd_user_containerd.service.d_port RUN chown -R rootless:rootless /home/rootless/.config FROM test-integration AS test-integration-ipv6 -CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=github.com/containerd/nerdctl/v2/cmd/nerdctl/...", \ - "--", "-timeout=60m", "-args", "-test.allow-kill-daemon", "-test.only-ipv6"] +CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=./cmd/nerdctl/...", \ + "--", "-timeout=60m", "-p", "1", "-args", "-test.allow-kill-daemon", "-test.only-ipv6"] FROM base AS demo diff --git a/Dockerfile.d/test-integration-rootless.sh b/Dockerfile.d/test-integration-rootless.sh index 0e2cb929b4f..4bdbf0fa4eb 100755 --- a/Dockerfile.d/test-integration-rootless.sh +++ b/Dockerfile.d/test-integration-rootless.sh @@ -56,5 +56,8 @@ EOF systemctl --user restart stargz-snapshotter.service export IPFS_PATH="/home/rootless/.local/share/ipfs" containerd-rootless-setuptool.sh install-bypass4netnsd - exec "$@" + # Once ssh-ed, we lost the Dockerfile working dir, so, get back in the nerdctl checkout + cd /go/src/github.com/containerd/nerdctl + # We also lose the PATH (and SendEnv=PATH would require sshd config changes) + exec env PATH="/usr/local/go/bin:$PATH" "$@" fi diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container_run_mount_linux_test.go index 5a6a64a2f20..04dc4440ddb 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container_run_mount_linux_test.go @@ -98,6 +98,7 @@ func TestRunAnonymousVolume(t *testing.T) { func TestRunVolumeRelativePath(t *testing.T) { t.Parallel() base := testutil.NewBase(t) + base.Dir = t.TempDir() base.Cmd("run", "--rm", "-v", "./foo:/mnt/foo", testutil.AlpineImage).AssertOK() base.Cmd("run", "--rm", "-v", "./foo", testutil.AlpineImage).AssertOK() diff --git a/docs/testing.md b/docs/testing.md index 60fa131a7c4..190733cb59d 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -21,18 +21,34 @@ Be sure to first `make && sudo make install` ```bash # Test all with nerdctl (rootless mode, if running go as a non-root user) -go test ./cmd/nerdctl/... +go test -p 1 ./cmd/nerdctl/... # Test all with nerdctl rootful -go test -exec sudo ./cmd/nerdctl/... +go test -p 1 -exec sudo ./cmd/nerdctl/... # Test all with docker -go test ./cmd/nerdctl/... -args -test.target=docker +go test -p 1 ./cmd/nerdctl/... -args -test.target=docker # Test just the tests(s) which names match TestVolume.* -go test ./cmd/nerdctl/... -run "TestVolume.*" +go test -p 1 ./cmd/nerdctl/... -run "TestVolume.*" +# Or alternatively, just test the subpackage +go test ./cmd/nerdctl/volume ``` +### About parallelization + +By default, when `go test ./foo/...` finds subpackages, it does create _a separate test binary +per sub-package_, and execute them _in parallel_. +This effectively will make distinct tests in different subpackages to be executed in +parallel, regardless of whether they called `t.Parallel` or not. + +The `-p 1` flag does inhibit this behavior, and forces go to run each sub-package +sequentially. + +Note that this is different from the `--parallel` flag, which controls the amount of +parallelization that a single go test binary will use when faced with tests that do +explicitly allow it (with a call to `t.Parallel()`). + ### Or test in a container ```bash diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index ee68a1e4cd2..d943de80251 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -58,6 +58,7 @@ type Base struct { Binary string Args []string Env []string + Dir string } // WithStdin sets the standard input of Cmd to the specified reader @@ -70,6 +71,7 @@ func WithStdin(r io.Reader) func(*Cmd) { func (b *Base) Cmd(args ...string) *Cmd { icmdCmd := icmd.Command(b.Binary, append(b.Args, args...)...) icmdCmd.Env = b.Env + icmdCmd.Dir = b.Dir cmd := &Cmd{ Cmd: icmdCmd, Base: b, @@ -83,6 +85,7 @@ func (b *Base) ComposeCmd(args ...string) *Cmd { binaryArgs := append(b.Args, append([]string{"compose"}, args...)...) icmdCmd := icmd.Command(binary, binaryArgs...) icmdCmd.Env = b.Env + icmdCmd.Dir = b.Dir cmd := &Cmd{ Cmd: icmdCmd, Base: b, From c5d3309d032ba1ac956b6585e7855520b22a4386 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 1 Sep 2024 11:51:53 -0700 Subject: [PATCH 0712/1066] Add a locking mechanism to prevent concurrent subpackage testing Signed-off-by: apostasie --- pkg/testutil/testutil.go | 55 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index ee68a1e4cd2..81c24aea155 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -37,12 +37,14 @@ import ( "gotest.tools/v3/icmd" "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/lockutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) @@ -546,14 +548,63 @@ var ( flagTestKube bool ) +var ( + testLockFile = filepath.Join(os.TempDir(), "nerdctl-test-prevent-concurrency", ".lock") +) + func M(m *testing.M) { flag.StringVar(&flagTestTarget, "test.target", Nerdctl, "target to test") flag.BoolVar(&flagTestKillDaemon, "test.allow-kill-daemon", false, "enable tests that kill the daemon") flag.BoolVar(&flagTestIPv6, "test.only-ipv6", false, "enable tests on IPv6") flag.BoolVar(&flagTestKube, "test.only-kubernetes", false, "enable tests on Kubernetes") flag.Parse() - fmt.Fprintf(os.Stderr, "test target: %q\n", flagTestTarget) - os.Exit(m.Run()) + + os.Exit(func() int { + // If there is a lockfile (no err), or if we error-ed stating it (permission), another test run is currently going. + // Note that this could be racy. The .lock file COULD get acquired after this and before we hit the lock section. + // This is not a big deal then: we will just wait for the lock to free. + if _, err := os.Stat(testLockFile); err == nil || !errors.Is(err, os.ErrNotExist) { + log.L.Errorf("Another test binary is already running. If you think this is an error, manually remove %s", testLockFile) + return 1 + } + + err := os.MkdirAll(filepath.Dir(testLockFile), 0o777) + if err != nil { + log.L.WithError(err).Errorf("failed creating testing lock directory %q", filepath.Dir(testLockFile)) + return 1 + } + + // Ensure that permissions are set to 777 (regardless of umask value), so that we do not lock people out when + // switching between rootful and rootless locking + os.Chmod(filepath.Dir(testLockFile), 0o777) + + // Acquire lock + lock, err := lockutil.Lock(filepath.Dir(testLockFile)) + if err != nil { + log.L.WithError(err).Errorf("failed acquiring testing lock %q", filepath.Dir(testLockFile)) + return 1 + } + + // Release... + defer lockutil.Unlock(lock) + + // Create marker file + err = os.WriteFile(testLockFile, []byte("prevent testing from running in parallel for subpackages integration tests"), 0o666) + if err != nil { + log.L.WithError(err).Errorf("failed writing lock file %q", testLockFile) + return 1 + } + + // Ensure cleanup + defer func() { + os.Remove(testLockFile) + }() + + // Now, run the tests + fmt.Fprintf(os.Stderr, "test target: %q\n", flagTestTarget) + + return m.Run() + }()) } func GetTarget() string { From d3a39fd2d4ba9fb0252eb8753df473d71b0afb5d Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 1 Sep 2024 13:47:41 -0700 Subject: [PATCH 0713/1066] Fix TestDiff failure with docker Signed-off-by: apostasie --- cmd/nerdctl/container_diff_linux_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/container_diff_linux_test.go b/cmd/nerdctl/container_diff_linux_test.go index e74ba025333..69041d82e99 100644 --- a/cmd/nerdctl/container_diff_linux_test.go +++ b/cmd/nerdctl/container_diff_linux_test.go @@ -23,7 +23,11 @@ import ( ) func TestDiff(t *testing.T) { - t.Parallel() + // It is unclear why this is failing with docker when run in parallel + // Obviously some other container test is interfering + if testutil.GetTarget() != testutil.Docker { + t.Parallel() + } base := testutil.NewBase(t) containerName := testutil.Identifier(t) defer base.Cmd("rm", containerName).Run() From 51af369069fc41c66be248cad2c8b797af0724f5 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 29 Aug 2024 11:31:53 -0700 Subject: [PATCH 0714/1066] Add Confirm helper Signed-off-by: apostasie --- cmd/nerdctl/builder.go | 14 ++++-------- cmd/nerdctl/compose_rm.go | 10 ++++----- cmd/nerdctl/container_prune.go | 14 ++---------- cmd/nerdctl/helpers/prompt.go | 39 ++++++++++++++++++++++++++++++++++ cmd/nerdctl/image_prune.go | 15 ++++--------- 5 files changed, 53 insertions(+), 39 deletions(-) create mode 100644 cmd/nerdctl/helpers/prompt.go diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index a5f82727ecf..f10b0817d00 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -25,6 +25,7 @@ import ( "github.com/docker/go-units" "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/builder" ) @@ -71,23 +72,16 @@ func builderPruneAction(cmd *cobra.Command, _ []string) error { } if !options.Force { - var ( - confirm string - msg string - ) + var msg string if options.All { msg = "This will remove all build cache." } else { msg = "This will remove any dangling build cache." } - msg += " Are you sure you want to continue? [y/N] " - fmt.Fprintf(cmd.OutOrStdout(), "WARNING! %s", msg) - fmt.Fscanf(cmd.InOrStdin(), "%s", &confirm) - - if strings.ToLower(confirm) != "y" { - return nil + if confirmed, err := helpers.Confirm(cmd, fmt.Sprintf("WARNING! %s.", msg)); err != nil || !confirmed { + return err } } diff --git a/cmd/nerdctl/compose_rm.go b/cmd/nerdctl/compose_rm.go index 778345e993a..f249770881c 100644 --- a/cmd/nerdctl/compose_rm.go +++ b/cmd/nerdctl/compose_rm.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -51,18 +52,15 @@ func composeRemoveAction(cmd *cobra.Command, args []string) error { return err } if !force { - var confirm string services := "all" if len(args) != 0 { services = strings.Join(args, ",") } + msg := fmt.Sprintf("This will remove all stopped containers from services: %s.", services) - msg += "\nAre you sure you want to continue? [y/N] " - fmt.Fprintf(cmd.OutOrStdout(), "WARNING! %s", msg) - fmt.Fscanf(cmd.InOrStdin(), "%s", &confirm) - if strings.ToLower(confirm) != "y" { - return nil + if confirmed, err := helpers.Confirm(cmd, fmt.Sprintf("WARNING! %s.", msg)); err != nil || !confirmed { + return err } } diff --git a/cmd/nerdctl/container_prune.go b/cmd/nerdctl/container_prune.go index fc2bdcc9457..35793a45409 100644 --- a/cmd/nerdctl/container_prune.go +++ b/cmd/nerdctl/container_prune.go @@ -17,11 +17,9 @@ package main import ( - "fmt" - "strings" - "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -59,15 +57,7 @@ func grantPrunePermission(cmd *cobra.Command) (bool, error) { } if !force { - var confirm string - msg := "This will remove all stopped containers." - msg += "\nAre you sure you want to continue? [y/N] " - fmt.Fprintf(cmd.OutOrStdout(), "WARNING! %s", msg) - fmt.Fscanf(cmd.InOrStdin(), "%s", &confirm) - - if strings.ToLower(confirm) != "y" { - return false, nil - } + return helpers.Confirm(cmd, "WARNING! This will remove all stopped containers.") } return true, nil } diff --git a/cmd/nerdctl/helpers/prompt.go b/cmd/nerdctl/helpers/prompt.go new file mode 100644 index 00000000000..9254699f7a6 --- /dev/null +++ b/cmd/nerdctl/helpers/prompt.go @@ -0,0 +1,39 @@ +/* + 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 helpers + +import ( + "fmt" + "strings" + + "github.com/spf13/cobra" +) + +func Confirm(cmd *cobra.Command, message string) (bool, error) { + message += "\nAre you sure you want to continue? [y/N] " + _, err := fmt.Fprint(cmd.OutOrStdout(), message) + if err != nil { + return false, err + } + + var confirm string + _, err = fmt.Fscanf(cmd.InOrStdin(), "%s", &confirm) + if err != nil { + return false, err + } + return strings.ToLower(confirm) == "y", err +} diff --git a/cmd/nerdctl/image_prune.go b/cmd/nerdctl/image_prune.go index 4508efaaa10..507dea9566e 100644 --- a/cmd/nerdctl/image_prune.go +++ b/cmd/nerdctl/image_prune.go @@ -18,10 +18,10 @@ package main import ( "fmt" - "strings" "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -82,22 +82,15 @@ func imagePruneAction(cmd *cobra.Command, _ []string) error { } if !options.Force { - var ( - confirm string - msg string - ) + var msg string if !options.All { msg = "This will remove all dangling images." } else { msg = "This will remove all images without at least one container associated to them." } - msg += "\nAre you sure you want to continue? [y/N] " - fmt.Fprintf(cmd.OutOrStdout(), "WARNING! %s", msg) - fmt.Fscanf(cmd.InOrStdin(), "%s", &confirm) - - if strings.ToLower(confirm) != "y" { - return nil + if confirmed, err := helpers.Confirm(cmd, fmt.Sprintf("WARNING! %s.", msg)); err != nil || !confirmed { + return err } } From b8b5d707983adb83c198693e3245a16c849fb2d7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 29 Aug 2024 11:49:33 -0700 Subject: [PATCH 0715/1066] Move away flagutil under helpers Signed-off-by: apostasie --- cmd/nerdctl/builder.go | 4 ++-- cmd/nerdctl/builder_build.go | 3 ++- cmd/nerdctl/completion.go | 9 +++++---- cmd/nerdctl/compose_build.go | 3 ++- cmd/nerdctl/compose_config.go | 3 ++- cmd/nerdctl/compose_cp.go | 3 ++- cmd/nerdctl/compose_create.go | 3 ++- cmd/nerdctl/compose_down.go | 3 ++- cmd/nerdctl/compose_exec.go | 3 ++- cmd/nerdctl/compose_images.go | 3 ++- cmd/nerdctl/compose_kill.go | 3 ++- cmd/nerdctl/compose_logs.go | 3 ++- cmd/nerdctl/compose_pause.go | 5 +++-- cmd/nerdctl/compose_port.go | 3 ++- cmd/nerdctl/compose_ps.go | 3 ++- cmd/nerdctl/compose_pull.go | 3 ++- cmd/nerdctl/compose_push.go | 3 ++- cmd/nerdctl/compose_restart.go | 3 ++- cmd/nerdctl/compose_rm.go | 2 +- cmd/nerdctl/compose_run.go | 3 ++- cmd/nerdctl/compose_start.go | 3 ++- cmd/nerdctl/compose_stop.go | 3 ++- cmd/nerdctl/compose_top.go | 3 ++- cmd/nerdctl/compose_up.go | 3 ++- cmd/nerdctl/container_attach.go | 3 ++- cmd/nerdctl/container_commit.go | 3 ++- cmd/nerdctl/container_cp_linux.go | 3 ++- cmd/nerdctl/container_create.go | 5 +++-- cmd/nerdctl/container_diff.go | 3 ++- cmd/nerdctl/container_exec.go | 3 ++- cmd/nerdctl/container_inspect.go | 3 ++- cmd/nerdctl/container_kill.go | 3 ++- cmd/nerdctl/container_list.go | 3 ++- cmd/nerdctl/container_logs.go | 3 ++- cmd/nerdctl/container_pause.go | 3 ++- cmd/nerdctl/container_port.go | 3 ++- cmd/nerdctl/container_prune.go | 2 +- cmd/nerdctl/container_remove.go | 3 ++- cmd/nerdctl/container_rename.go | 3 ++- cmd/nerdctl/container_restart.go | 3 ++- cmd/nerdctl/container_start.go | 3 ++- cmd/nerdctl/container_stats.go | 3 ++- cmd/nerdctl/container_stop.go | 3 ++- cmd/nerdctl/container_top.go | 3 ++- cmd/nerdctl/container_unpause.go | 3 ++- cmd/nerdctl/container_update.go | 3 ++- cmd/nerdctl/container_wait.go | 3 ++- cmd/nerdctl/{ => helpers}/flagutil.go | 29 +++------------------------ cmd/nerdctl/image_convert.go | 3 ++- cmd/nerdctl/image_cryptutil.go | 3 ++- cmd/nerdctl/image_history.go | 3 ++- cmd/nerdctl/image_inspect.go | 3 ++- cmd/nerdctl/image_list.go | 3 ++- cmd/nerdctl/image_load.go | 3 ++- cmd/nerdctl/image_prune.go | 2 +- cmd/nerdctl/image_pull.go | 5 +++-- cmd/nerdctl/image_push.go | 26 +++++++++++++++++++++++- cmd/nerdctl/image_remove.go | 3 ++- cmd/nerdctl/image_save.go | 3 ++- cmd/nerdctl/image_tag.go | 3 ++- cmd/nerdctl/inspect.go | 3 ++- cmd/nerdctl/internal_oci_hook.go | 3 ++- cmd/nerdctl/login.go | 3 ++- cmd/nerdctl/main.go | 5 +++-- cmd/nerdctl/main_unix.go | 5 +++-- cmd/nerdctl/namespace.go | 3 ++- cmd/nerdctl/namespace_create.go | 3 ++- cmd/nerdctl/namespace_inspect.go | 3 ++- cmd/nerdctl/namespace_remove.go | 3 ++- cmd/nerdctl/namespace_update.go | 3 ++- cmd/nerdctl/network_create.go | 3 ++- cmd/nerdctl/network_inspect.go | 3 ++- cmd/nerdctl/network_list.go | 3 ++- cmd/nerdctl/network_prune.go | 3 ++- cmd/nerdctl/network_remove.go | 3 ++- cmd/nerdctl/system_events.go | 3 ++- cmd/nerdctl/system_info.go | 3 ++- cmd/nerdctl/system_prune.go | 3 ++- cmd/nerdctl/version.go | 3 ++- cmd/nerdctl/volume_create.go | 3 ++- cmd/nerdctl/volume_inspect.go | 3 ++- cmd/nerdctl/volume_list.go | 3 ++- cmd/nerdctl/volume_prune.go | 3 ++- cmd/nerdctl/volume_remove.go | 3 ++- 84 files changed, 197 insertions(+), 118 deletions(-) rename cmd/nerdctl/{ => helpers}/flagutil.go (81%) diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index f10b0817d00..9a6bb5c5c98 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -102,7 +102,7 @@ func builderPruneAction(cmd *cobra.Command, _ []string) error { } func processBuilderPruneOptions(cmd *cobra.Command) (types.BuilderPruneOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.BuilderPruneOptions{}, err } @@ -151,7 +151,7 @@ func newBuilderDebugCommand() *cobra.Command { } func builderDebugAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index 46e04ed00b4..e496a16fc98 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -25,6 +25,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -82,7 +83,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container } func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBuildOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.BuilderBuildOptions{}, err } diff --git a/cmd/nerdctl/completion.go b/cmd/nerdctl/completion.go index 398723b3ee1..bf03fcdd7a9 100644 --- a/cmd/nerdctl/completion.go +++ b/cmd/nerdctl/completion.go @@ -24,13 +24,14 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/netutil" ) func shellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } @@ -53,7 +54,7 @@ func shellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirec } func shellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd.ProcessStatus) bool) ([]string, cobra.ShellCompDirective) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } @@ -102,7 +103,7 @@ func shellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd. // shellCompleteNetworkNames includes {"bridge","host","none"} func shellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, cobra.ShellCompDirective) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } @@ -134,7 +135,7 @@ func shellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, } func shellCompleteVolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } diff --git a/cmd/nerdctl/compose_build.go b/cmd/nerdctl/compose_build.go index d607d17b2f4..2c8ad6c34a6 100644 --- a/cmd/nerdctl/compose_build.go +++ b/cmd/nerdctl/compose_build.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -40,7 +41,7 @@ func newComposeBuildCommand() *cobra.Command { } func composeBuildAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_config.go b/cmd/nerdctl/compose_config.go index c920c77f441..4467d3f20df 100644 --- a/cmd/nerdctl/compose_config.go +++ b/cmd/nerdctl/compose_config.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -45,7 +46,7 @@ func newComposeConfigCommand() *cobra.Command { } func composeConfigAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_cp.go b/cmd/nerdctl/compose_cp.go index 976a5617ed9..90e7cb8309e 100644 --- a/cmd/nerdctl/compose_cp.go +++ b/cmd/nerdctl/compose_cp.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -45,7 +46,7 @@ func newComposeCopyCommand() *cobra.Command { } func composeCopyAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_create.go b/cmd/nerdctl/compose_create.go index e420984e933..14a8021460a 100644 --- a/cmd/nerdctl/compose_create.go +++ b/cmd/nerdctl/compose_create.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -43,7 +44,7 @@ func newComposeCreateCommand() *cobra.Command { } func composeCreateAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_down.go b/cmd/nerdctl/compose_down.go index 6bcc152963d..9e29281282f 100644 --- a/cmd/nerdctl/compose_down.go +++ b/cmd/nerdctl/compose_down.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -39,7 +40,7 @@ func newComposeDownCommand() *cobra.Command { } func composeDownAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_exec.go b/cmd/nerdctl/compose_exec.go index 863ff1eb281..36958da83ff 100644 --- a/cmd/nerdctl/compose_exec.go +++ b/cmd/nerdctl/compose_exec.go @@ -23,6 +23,7 @@ import ( "github.com/moby/term" "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -61,7 +62,7 @@ func newComposeExecCommand() *cobra.Command { } func composeExecAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_images.go b/cmd/nerdctl/compose_images.go index 852cae4e437..fcb2a373ea0 100644 --- a/cmd/nerdctl/compose_images.go +++ b/cmd/nerdctl/compose_images.go @@ -29,6 +29,7 @@ import ( "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/containerd/v2/pkg/progress" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/formatter" @@ -51,7 +52,7 @@ func newComposeImagesCommand() *cobra.Command { } func composeImagesAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_kill.go b/cmd/nerdctl/compose_kill.go index f6d6a1d6352..1166e24a371 100644 --- a/cmd/nerdctl/compose_kill.go +++ b/cmd/nerdctl/compose_kill.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -37,7 +38,7 @@ func newComposeKillCommand() *cobra.Command { } func composeKillAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_logs.go b/cmd/nerdctl/compose_logs.go index 79af0310b6d..c038d712866 100644 --- a/cmd/nerdctl/compose_logs.go +++ b/cmd/nerdctl/compose_logs.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -41,7 +42,7 @@ func newComposeLogsCommand() *cobra.Command { } func composeLogsAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_pause.go b/cmd/nerdctl/compose_pause.go index b280d5cf950..6250214a269 100644 --- a/cmd/nerdctl/compose_pause.go +++ b/cmd/nerdctl/compose_pause.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" ) @@ -36,7 +37,7 @@ func newComposePauseCommand() *cobra.Command { } func composePauseAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } @@ -71,7 +72,7 @@ func newComposeUnpauseCommand() *cobra.Command { } func composeUnpauseAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_port.go b/cmd/nerdctl/compose_port.go index 95035e833dd..e654f45f9f1 100644 --- a/cmd/nerdctl/compose_port.go +++ b/cmd/nerdctl/compose_port.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -43,7 +44,7 @@ func newComposePortCommand() *cobra.Command { } func composePortAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose_ps.go index b58f3cfc0ff..684428ad8c8 100644 --- a/cmd/nerdctl/compose_ps.go +++ b/cmd/nerdctl/compose_ps.go @@ -32,6 +32,7 @@ import ( gocni "github.com/containerd/go-cni" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/containerutil" @@ -74,7 +75,7 @@ type composeContainerPrintable struct { } func composePsAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_pull.go b/cmd/nerdctl/compose_pull.go index 738c0b955e9..dc90dc17843 100644 --- a/cmd/nerdctl/compose_pull.go +++ b/cmd/nerdctl/compose_pull.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -37,7 +38,7 @@ func newComposePullCommand() *cobra.Command { } func composePullAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_push.go b/cmd/nerdctl/compose_push.go index cfa310a3e98..6aca0c64e5a 100644 --- a/cmd/nerdctl/compose_push.go +++ b/cmd/nerdctl/compose_push.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -36,7 +37,7 @@ func newComposePushCommand() *cobra.Command { } func composePushAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_restart.go b/cmd/nerdctl/compose_restart.go index a68f6e52408..170a3fc4b62 100644 --- a/cmd/nerdctl/compose_restart.go +++ b/cmd/nerdctl/compose_restart.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -37,7 +38,7 @@ func newComposeRestartCommand() *cobra.Command { } func composeRestartAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_rm.go b/cmd/nerdctl/compose_rm.go index f249770881c..b0c32b47c1f 100644 --- a/cmd/nerdctl/compose_rm.go +++ b/cmd/nerdctl/compose_rm.go @@ -43,7 +43,7 @@ func newComposeRemoveCommand() *cobra.Command { } func composeRemoveAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_run.go b/cmd/nerdctl/compose_run.go index 122e6be23bf..9f1ffa76c0b 100644 --- a/cmd/nerdctl/compose_run.go +++ b/cmd/nerdctl/compose_run.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -69,7 +70,7 @@ func newComposeRunCommand() *cobra.Command { } func composeRunAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_start.go b/cmd/nerdctl/compose_start.go index f0ce42cfe29..08ca46b33da 100644 --- a/cmd/nerdctl/compose_start.go +++ b/cmd/nerdctl/compose_start.go @@ -27,6 +27,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/containerutil" @@ -46,7 +47,7 @@ func newComposeStartCommand() *cobra.Command { } func composeStartAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_stop.go b/cmd/nerdctl/compose_stop.go index 07bd789178e..7c769276700 100644 --- a/cmd/nerdctl/compose_stop.go +++ b/cmd/nerdctl/compose_stop.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -37,7 +38,7 @@ func newComposeStopCommand() *cobra.Command { } func composeStopAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_top.go b/cmd/nerdctl/compose_top.go index a3356b8face..f6466f2329b 100644 --- a/cmd/nerdctl/compose_top.go +++ b/cmd/nerdctl/compose_top.go @@ -23,6 +23,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" @@ -44,7 +45,7 @@ func newComposeTopCommand() *cobra.Command { } func composeTopAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/compose_up.go b/cmd/nerdctl/compose_up.go index a38c4f9dab7..b0c8fddab5e 100644 --- a/cmd/nerdctl/compose_up.go +++ b/cmd/nerdctl/compose_up.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/compose" "github.com/containerd/nerdctl/v2/pkg/composer" @@ -51,7 +52,7 @@ func newComposeUpCommand() *cobra.Command { } func composeUpAction(cmd *cobra.Command, services []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container_attach.go b/cmd/nerdctl/container_attach.go index abb4d90db33..031915c46a7 100644 --- a/cmd/nerdctl/container_attach.go +++ b/cmd/nerdctl/container_attach.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -58,7 +59,7 @@ Caveats: } func processContainerAttachOptions(cmd *cobra.Command) (types.ContainerAttachOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerAttachOptions{}, err } diff --git a/cmd/nerdctl/container_commit.go b/cmd/nerdctl/container_commit.go index 96c79cbc66d..42a6539f246 100644 --- a/cmd/nerdctl/container_commit.go +++ b/cmd/nerdctl/container_commit.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -42,7 +43,7 @@ func newCommitCommand() *cobra.Command { } func processCommitCommandOptions(cmd *cobra.Command) (types.ContainerCommitOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerCommitOptions{}, err } diff --git a/cmd/nerdctl/container_cp_linux.go b/cmd/nerdctl/container_cp_linux.go index 3a2c2aa84e1..184cbc66292 100644 --- a/cmd/nerdctl/container_cp_linux.go +++ b/cmd/nerdctl/container_cp_linux.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -78,7 +79,7 @@ func cpAction(cmd *cobra.Command, args []string) error { } func processCpOptions(cmd *cobra.Command, args []string) (types.ContainerCpOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerCpOptions{}, err } diff --git a/cmd/nerdctl/container_create.go b/cmd/nerdctl/container_create.go index 49ed0af26bb..304ae65db87 100644 --- a/cmd/nerdctl/container_create.go +++ b/cmd/nerdctl/container_create.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -61,7 +62,7 @@ func processContainerCreateOptions(cmd *cobra.Command) (types.ContainerCreateOpt Stderr: cmd.ErrOrStderr(), } - opt.GOptions, err = processRootCmdFlags(cmd) + opt.GOptions, err = helpers.ProcessRootCmdFlags(cmd) if err != nil { return opt, err } @@ -404,7 +405,7 @@ func processContainerCreateOptions(cmd *cobra.Command) (types.ContainerCreateOpt // #endregion // #region for image pull and verify options - imageVerifyOpt, err := processImageVerifyOptions(cmd) + imageVerifyOpt, err := helpers.ProcessImageVerifyOptions(cmd) if err != nil { return opt, err } diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index 08cd376d43c..1606345a8a7 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -33,6 +33,7 @@ import ( "github.com/containerd/log" "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/idgen" @@ -55,7 +56,7 @@ func newDiffCommand() *cobra.Command { } func processContainerDiffOptions(cmd *cobra.Command) (types.ContainerDiffOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerDiffOptions{}, err } diff --git a/cmd/nerdctl/container_exec.go b/cmd/nerdctl/container_exec.go index 8e3b5d15d95..a9e68e53b9e 100644 --- a/cmd/nerdctl/container_exec.go +++ b/cmd/nerdctl/container_exec.go @@ -25,6 +25,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -56,7 +57,7 @@ func newExecCommand() *cobra.Command { } func processExecCommandOptions(cmd *cobra.Command) (types.ContainerExecOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerExecOptions{}, err } diff --git a/cmd/nerdctl/container_inspect.go b/cmd/nerdctl/container_inspect.go index e178724617e..e2b11946c57 100644 --- a/cmd/nerdctl/container_inspect.go +++ b/cmd/nerdctl/container_inspect.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -56,7 +57,7 @@ var validModeType = map[string]bool{ } func processContainerInspectOptions(cmd *cobra.Command) (opt types.ContainerInspectOptions, err error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return } diff --git a/cmd/nerdctl/container_kill.go b/cmd/nerdctl/container_kill.go index 75154e63c3b..846c94c111a 100644 --- a/cmd/nerdctl/container_kill.go +++ b/cmd/nerdctl/container_kill.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -41,7 +42,7 @@ func newKillCommand() *cobra.Command { } func killAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container_list.go index f4f43be161a..d92de87a5de 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container_list.go @@ -26,6 +26,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -58,7 +59,7 @@ func newPsCommand() *cobra.Command { } func processOptions(cmd *cobra.Command) (types.ContainerListOptions, FormattingAndPrintingOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerListOptions{}, FormattingAndPrintingOptions{}, err } diff --git a/cmd/nerdctl/container_logs.go b/cmd/nerdctl/container_logs.go index 2e66c91e09e..4f9a2a2a39b 100644 --- a/cmd/nerdctl/container_logs.go +++ b/cmd/nerdctl/container_logs.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -55,7 +56,7 @@ The following containers are supported: } func processContainerLogsOptions(cmd *cobra.Command) (types.ContainerLogsOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerLogsOptions{}, err } diff --git a/cmd/nerdctl/container_pause.go b/cmd/nerdctl/container_pause.go index 8176e8c2f16..fba77b27a0a 100644 --- a/cmd/nerdctl/container_pause.go +++ b/cmd/nerdctl/container_pause.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -40,7 +41,7 @@ func newPauseCommand() *cobra.Command { } func processContainerPauseOptions(cmd *cobra.Command) (types.ContainerPauseOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerPauseOptions{}, err } diff --git a/cmd/nerdctl/container_port.go b/cmd/nerdctl/container_port.go index df98022ad73..dd9d7a73fd8 100644 --- a/cmd/nerdctl/container_port.go +++ b/cmd/nerdctl/container_port.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" @@ -43,7 +44,7 @@ func newPortCommand() *cobra.Command { } func portAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container_prune.go b/cmd/nerdctl/container_prune.go index 35793a45409..960542157d5 100644 --- a/cmd/nerdctl/container_prune.go +++ b/cmd/nerdctl/container_prune.go @@ -39,7 +39,7 @@ func newContainerPruneCommand() *cobra.Command { } func processContainerPruneOptions(cmd *cobra.Command) (types.ContainerPruneOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerPruneOptions{}, err } diff --git a/cmd/nerdctl/container_remove.go b/cmd/nerdctl/container_remove.go index bdd415f836e..4e80f5a138a 100644 --- a/cmd/nerdctl/container_remove.go +++ b/cmd/nerdctl/container_remove.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -41,7 +42,7 @@ func newRmCommand() *cobra.Command { } func rmAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container_rename.go b/cmd/nerdctl/container_rename.go index 915e1d2eb00..9e0400f7e1a 100644 --- a/cmd/nerdctl/container_rename.go +++ b/cmd/nerdctl/container_rename.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -38,7 +39,7 @@ func newRenameCommand() *cobra.Command { } func processContainerRenameOptions(cmd *cobra.Command) (types.ContainerRenameOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerRenameOptions{}, err } diff --git a/cmd/nerdctl/container_restart.go b/cmd/nerdctl/container_restart.go index caf05341746..a29ac4dac1f 100644 --- a/cmd/nerdctl/container_restart.go +++ b/cmd/nerdctl/container_restart.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -41,7 +42,7 @@ func newRestartCommand() *cobra.Command { } func processContainerRestartOptions(cmd *cobra.Command) (types.ContainerRestartOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerRestartOptions{}, err } diff --git a/cmd/nerdctl/container_start.go b/cmd/nerdctl/container_start.go index 793624ecc3e..562a63567a1 100644 --- a/cmd/nerdctl/container_start.go +++ b/cmd/nerdctl/container_start.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -46,7 +47,7 @@ func newStartCommand() *cobra.Command { } func processContainerStartOptions(cmd *cobra.Command) (types.ContainerStartOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerStartOptions{}, err } diff --git a/cmd/nerdctl/container_stats.go b/cmd/nerdctl/container_stats.go index eaec1307c45..d07c5334698 100644 --- a/cmd/nerdctl/container_stats.go +++ b/cmd/nerdctl/container_stats.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -49,7 +50,7 @@ func addStatsFlags(cmd *cobra.Command) { } func processStatsCommandFlags(cmd *cobra.Command) (types.ContainerStatsOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerStatsOptions{}, err } diff --git a/cmd/nerdctl/container_stop.go b/cmd/nerdctl/container_stop.go index 571b9e29e87..fee0183c92c 100644 --- a/cmd/nerdctl/container_stop.go +++ b/cmd/nerdctl/container_stop.go @@ -23,6 +23,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -43,7 +44,7 @@ func newStopCommand() *cobra.Command { } func processContainerStopOptions(cmd *cobra.Command) (types.ContainerStopOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerStopOptions{}, err } diff --git a/cmd/nerdctl/container_top.go b/cmd/nerdctl/container_top.go index 168a4e978b0..5376895d96b 100644 --- a/cmd/nerdctl/container_top.go +++ b/cmd/nerdctl/container_top.go @@ -24,6 +24,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -48,7 +49,7 @@ func newTopCommand() *cobra.Command { func topAction(cmd *cobra.Command, args []string) error { // NOTE: rootless container does not rely on cgroupv1. // more details about possible ways to resolve this concern: #223 - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container_unpause.go b/cmd/nerdctl/container_unpause.go index 98e3e9cb500..7fec1c06a6a 100644 --- a/cmd/nerdctl/container_unpause.go +++ b/cmd/nerdctl/container_unpause.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -40,7 +41,7 @@ func newUnpauseCommand() *cobra.Command { } func processContainerUnpauseOptions(cmd *cobra.Command) (types.ContainerUnpauseOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerUnpauseOptions{}, err } diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index 8f020071bec..f6b9357c661 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -33,6 +33,7 @@ import ( "github.com/containerd/log" "github.com/containerd/typeurl/v2" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" nerdctlContainer "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -89,7 +90,7 @@ func setUpdateFlags(cmd *cobra.Command) { } func updateAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container_wait.go b/cmd/nerdctl/container_wait.go index a4d962bf4ef..03b33abee58 100644 --- a/cmd/nerdctl/container_wait.go +++ b/cmd/nerdctl/container_wait.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -40,7 +41,7 @@ func newWaitCommand() *cobra.Command { } func processContainerWaitOptions(cmd *cobra.Command) (types.ContainerWaitOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerWaitOptions{}, err } diff --git a/cmd/nerdctl/flagutil.go b/cmd/nerdctl/helpers/flagutil.go similarity index 81% rename from cmd/nerdctl/flagutil.go rename to cmd/nerdctl/helpers/flagutil.go index c88e7597af9..9ca11d449fd 100644 --- a/cmd/nerdctl/flagutil.go +++ b/cmd/nerdctl/helpers/flagutil.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package helpers import ( "github.com/spf13/cobra" @@ -22,20 +22,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" ) -func processImageSignOptions(cmd *cobra.Command) (opt types.ImageSignOptions, err error) { - if opt.Provider, err = cmd.Flags().GetString("sign"); err != nil { - return - } - if opt.CosignKey, err = cmd.Flags().GetString("cosign-key"); err != nil { - return - } - if opt.NotationKeyName, err = cmd.Flags().GetString("notation-key-name"); err != nil { - return - } - return -} - -func processImageVerifyOptions(cmd *cobra.Command) (opt types.ImageVerifyOptions, err error) { +func ProcessImageVerifyOptions(cmd *cobra.Command) (opt types.ImageVerifyOptions, err error) { if opt.Provider, err = cmd.Flags().GetString("verify"); err != nil { return } @@ -57,17 +44,7 @@ func processImageVerifyOptions(cmd *cobra.Command) (opt types.ImageVerifyOptions return } -func processSociOptions(cmd *cobra.Command) (opt types.SociOptions, err error) { - if opt.SpanSize, err = cmd.Flags().GetInt64("soci-span-size"); err != nil { - return - } - if opt.MinLayerSize, err = cmd.Flags().GetInt64("soci-min-layer-size"); err != nil { - return - } - return -} - -func processRootCmdFlags(cmd *cobra.Command) (types.GlobalCommandOptions, error) { +func ProcessRootCmdFlags(cmd *cobra.Command) (types.GlobalCommandOptions, error) { debug, err := cmd.Flags().GetBool("debug") if err != nil { return types.GlobalCommandOptions{}, err diff --git a/cmd/nerdctl/image_convert.go b/cmd/nerdctl/image_convert.go index 355a2e9737a..ddefa598dc6 100644 --- a/cmd/nerdctl/image_convert.go +++ b/cmd/nerdctl/image_convert.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -103,7 +104,7 @@ func newImageConvertCommand() *cobra.Command { } func processImageConvertOptions(cmd *cobra.Command) (types.ImageConvertOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImageConvertOptions{}, err } diff --git a/cmd/nerdctl/image_cryptutil.go b/cmd/nerdctl/image_cryptutil.go index 28b38dd1ff2..adee05a6b55 100644 --- a/cmd/nerdctl/image_cryptutil.go +++ b/cmd/nerdctl/image_cryptutil.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -54,7 +55,7 @@ func registerImgcryptFlags(cmd *cobra.Command, encrypt bool) { } func processImgCryptOptions(cmd *cobra.Command, args []string, encrypt bool) (types.ImageCryptOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImageCryptOptions{}, err } diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index 4f77e8a819b..e22cb0601a3 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -35,6 +35,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" @@ -78,7 +79,7 @@ type historyPrintable struct { } func historyAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/image_inspect.go b/cmd/nerdctl/image_inspect.go index 9cc7fbdc81f..0b0222cb043 100644 --- a/cmd/nerdctl/image_inspect.go +++ b/cmd/nerdctl/image_inspect.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -53,7 +54,7 @@ func newImageInspectCommand() *cobra.Command { } func processImageInspectOptions(cmd *cobra.Command, platform *string) (types.ImageInspectOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImageInspectOptions{}, err } diff --git a/cmd/nerdctl/image_list.go b/cmd/nerdctl/image_list.go index 561b0c00956..71616a53989 100644 --- a/cmd/nerdctl/image_list.go +++ b/cmd/nerdctl/image_list.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -69,7 +70,7 @@ Properties: } func processImageListOptions(cmd *cobra.Command, args []string) (types.ImageListOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImageListOptions{}, err } diff --git a/cmd/nerdctl/image_load.go b/cmd/nerdctl/image_load.go index 5e8e5a4228d..ed09919aaf0 100644 --- a/cmd/nerdctl/image_load.go +++ b/cmd/nerdctl/image_load.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -52,7 +53,7 @@ func processLoadCommandFlags(cmd *cobra.Command) (types.ImageLoadOptions, error) if err != nil { return types.ImageLoadOptions{}, err } - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImageLoadOptions{}, err } diff --git a/cmd/nerdctl/image_prune.go b/cmd/nerdctl/image_prune.go index 507dea9566e..0480a6a544d 100644 --- a/cmd/nerdctl/image_prune.go +++ b/cmd/nerdctl/image_prune.go @@ -44,7 +44,7 @@ func newImagePruneCommand() *cobra.Command { } func processImagePruneOptions(cmd *cobra.Command) (types.ImagePruneOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImagePruneOptions{}, err } diff --git a/cmd/nerdctl/image_pull.go b/cmd/nerdctl/image_pull.go index afe8717aa4c..f54a007d08e 100644 --- a/cmd/nerdctl/image_pull.go +++ b/cmd/nerdctl/image_pull.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -71,7 +72,7 @@ func newPullCommand() *cobra.Command { } func processPullCommandFlags(cmd *cobra.Command) (types.ImagePullOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImagePullOptions{}, err } @@ -112,7 +113,7 @@ func processPullCommandFlags(cmd *cobra.Command) (types.ImagePullOptions, error) return types.ImagePullOptions{}, err } - verifyOptions, err := processImageVerifyOptions(cmd) + verifyOptions, err := helpers.ProcessImageVerifyOptions(cmd) if err != nil { return types.ImagePullOptions{}, err } diff --git a/cmd/nerdctl/image_push.go b/cmd/nerdctl/image_push.go index e04f8b5ef41..02e88885a40 100644 --- a/cmd/nerdctl/image_push.go +++ b/cmd/nerdctl/image_push.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -71,7 +72,7 @@ func newPushCommand() *cobra.Command { } func processImagePushOptions(cmd *cobra.Command) (types.ImagePushOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImagePushOptions{}, err } @@ -146,3 +147,26 @@ func pushShellComplete(cmd *cobra.Command, args []string, toComplete string) ([] // show image names return shellCompleteImageNames(cmd) } + +func processImageSignOptions(cmd *cobra.Command) (opt types.ImageSignOptions, err error) { + if opt.Provider, err = cmd.Flags().GetString("sign"); err != nil { + return + } + if opt.CosignKey, err = cmd.Flags().GetString("cosign-key"); err != nil { + return + } + if opt.NotationKeyName, err = cmd.Flags().GetString("notation-key-name"); err != nil { + return + } + return +} + +func processSociOptions(cmd *cobra.Command) (opt types.SociOptions, err error) { + if opt.SpanSize, err = cmd.Flags().GetInt64("soci-span-size"); err != nil { + return + } + if opt.MinLayerSize, err = cmd.Flags().GetInt64("soci-min-layer-size"); err != nil { + return + } + return +} diff --git a/cmd/nerdctl/image_remove.go b/cmd/nerdctl/image_remove.go index f61a39ac6cc..5e677f642d5 100644 --- a/cmd/nerdctl/image_remove.go +++ b/cmd/nerdctl/image_remove.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -41,7 +42,7 @@ func newRmiCommand() *cobra.Command { } func processImageRemoveOptions(cmd *cobra.Command) (types.ImageRemoveOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImageRemoveOptions{}, err } diff --git a/cmd/nerdctl/image_save.go b/cmd/nerdctl/image_save.go index dc4e7a86a0a..9c744bdb324 100644 --- a/cmd/nerdctl/image_save.go +++ b/cmd/nerdctl/image_save.go @@ -23,6 +23,7 @@ import ( "github.com/mattn/go-isatty" "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -52,7 +53,7 @@ func newSaveCommand() *cobra.Command { } func processImageSaveOptions(cmd *cobra.Command) (types.ImageSaveOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImageSaveOptions{}, err } diff --git a/cmd/nerdctl/image_tag.go b/cmd/nerdctl/image_tag.go index abf96ab28cf..ddc3995ad51 100644 --- a/cmd/nerdctl/image_tag.go +++ b/cmd/nerdctl/image_tag.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/image" @@ -38,7 +39,7 @@ func newTagCommand() *cobra.Command { } func tagAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/inspect.go b/cmd/nerdctl/inspect.go index 150b8e7dfcd..dad2b35ded8 100644 --- a/cmd/nerdctl/inspect.go +++ b/cmd/nerdctl/inspect.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -69,7 +70,7 @@ func addInspectFlags(cmd *cobra.Command) { } func inspectAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/internal_oci_hook.go b/cmd/nerdctl/internal_oci_hook.go index 455b41daf7e..4ebad5d2383 100644 --- a/cmd/nerdctl/internal_oci_hook.go +++ b/cmd/nerdctl/internal_oci_hook.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/ocihook" ) @@ -38,7 +39,7 @@ func newInternalOCIHookCommandCommand() *cobra.Command { } func internalOCIHookAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/login.go b/cmd/nerdctl/login.go index 7772692f5ee..047b712d529 100644 --- a/cmd/nerdctl/login.go +++ b/cmd/nerdctl/login.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/login" ) @@ -45,7 +46,7 @@ func newLoginCommand() *cobra.Command { } func processLoginOptions(cmd *cobra.Command) (types.LoginCommandOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.LoginCommandOptions{}, err } diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index e4af1c72fbe..f875052a09f 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -32,6 +32,7 @@ import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/config" ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/errutil" @@ -208,7 +209,7 @@ Config file ($NERDCTL_TOML): %s } rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } @@ -565,7 +566,7 @@ func AddPersistentStringArrayFlag(cmd *cobra.Command, name string, aliases, nonP func checkExperimental(feature string) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/main_unix.go b/cmd/nerdctl/main_unix.go index af6bb4d2434..e66bdfb8950 100644 --- a/cmd/nerdctl/main_unix.go +++ b/cmd/nerdctl/main_unix.go @@ -23,13 +23,14 @@ import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) func shellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } @@ -55,7 +56,7 @@ func shellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete s } func shellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError } diff --git a/cmd/nerdctl/namespace.go b/cmd/nerdctl/namespace.go index 3faa08f09ea..3086c9d06a6 100644 --- a/cmd/nerdctl/namespace.go +++ b/cmd/nerdctl/namespace.go @@ -28,6 +28,7 @@ import ( "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) @@ -65,7 +66,7 @@ func newNamespaceLsCommand() *cobra.Command { } func namespaceLsAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/namespace_create.go b/cmd/nerdctl/namespace_create.go index ee77ba54daf..61700c56d19 100644 --- a/cmd/nerdctl/namespace_create.go +++ b/cmd/nerdctl/namespace_create.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" @@ -39,7 +40,7 @@ func newNamespaceCreateCommand() *cobra.Command { } func processNamespaceCreateCommandOption(cmd *cobra.Command) (types.NamespaceCreateOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.NamespaceCreateOptions{}, err } diff --git a/cmd/nerdctl/namespace_inspect.go b/cmd/nerdctl/namespace_inspect.go index 5df289b35f1..580ed4689e9 100644 --- a/cmd/nerdctl/namespace_inspect.go +++ b/cmd/nerdctl/namespace_inspect.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" @@ -41,7 +42,7 @@ func newNamespaceInspectCommand() *cobra.Command { } func processNamespaceInspectOptions(cmd *cobra.Command) (types.NamespaceInspectOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.NamespaceInspectOptions{}, err } diff --git a/cmd/nerdctl/namespace_remove.go b/cmd/nerdctl/namespace_remove.go index aa9a887a9b0..6ba48fe7200 100644 --- a/cmd/nerdctl/namespace_remove.go +++ b/cmd/nerdctl/namespace_remove.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" @@ -39,7 +40,7 @@ func newNamespaceRmCommand() *cobra.Command { } func processNamespaceRemoveOptions(cmd *cobra.Command) (types.NamespaceRemoveOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.NamespaceRemoveOptions{}, err } diff --git a/cmd/nerdctl/namespace_update.go b/cmd/nerdctl/namespace_update.go index 782d43d7b4f..6debd47cae4 100644 --- a/cmd/nerdctl/namespace_update.go +++ b/cmd/nerdctl/namespace_update.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/namespace" @@ -38,7 +39,7 @@ func newNamespacelabelUpdateCommand() *cobra.Command { } func processNamespaceUpdateCommandOption(cmd *cobra.Command) (types.NamespaceUpdateOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.NamespaceUpdateOptions{}, err } diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index 9a33cb5c67d..a14f30777a4 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" "github.com/containerd/nerdctl/v2/pkg/identifiers" @@ -52,7 +53,7 @@ func newNetworkCreateCommand() *cobra.Command { } func networkCreateAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/network_inspect.go b/cmd/nerdctl/network_inspect.go index ad3bb6eaa91..a1952e761c3 100644 --- a/cmd/nerdctl/network_inspect.go +++ b/cmd/nerdctl/network_inspect.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" ) @@ -45,7 +46,7 @@ func newNetworkInspectCommand() *cobra.Command { } func networkInspectAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/network_list.go b/cmd/nerdctl/network_list.go index de0f35e5d54..8cc8ecde0c8 100644 --- a/cmd/nerdctl/network_list.go +++ b/cmd/nerdctl/network_list.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" ) @@ -43,7 +44,7 @@ func newNetworkLsCommand() *cobra.Command { } func networkLsAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/network_prune.go b/cmd/nerdctl/network_prune.go index 6e1430b22e7..3c68263c0ef 100644 --- a/cmd/nerdctl/network_prune.go +++ b/cmd/nerdctl/network_prune.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/network" @@ -43,7 +44,7 @@ func newNetworkPruneCommand() *cobra.Command { } func networkPruneAction(cmd *cobra.Command, _ []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/network_remove.go b/cmd/nerdctl/network_remove.go index 80eb48ac98d..dac95ed6af4 100644 --- a/cmd/nerdctl/network_remove.go +++ b/cmd/nerdctl/network_remove.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/network" @@ -41,7 +42,7 @@ func newNetworkRmCommand() *cobra.Command { } func networkRmAction(cmd *cobra.Command, args []string) error { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/system_events.go b/cmd/nerdctl/system_events.go index 65eaacff4ba..bc4dcfb57f6 100644 --- a/cmd/nerdctl/system_events.go +++ b/cmd/nerdctl/system_events.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/system" @@ -45,7 +46,7 @@ func newEventsCommand() *cobra.Command { } func processSystemEventsOptions(cmd *cobra.Command) (types.SystemEventsOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.SystemEventsOptions{}, err } diff --git a/cmd/nerdctl/system_info.go b/cmd/nerdctl/system_info.go index b2562319a97..0d461c99a77 100644 --- a/cmd/nerdctl/system_info.go +++ b/cmd/nerdctl/system_info.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/system" @@ -45,7 +46,7 @@ func newInfoCommand() *cobra.Command { } func processInfoOptions(cmd *cobra.Command) (types.SystemInfoOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.SystemInfoOptions{}, err } diff --git a/cmd/nerdctl/system_prune.go b/cmd/nerdctl/system_prune.go index ed3e8cd370f..e8e384cf5fb 100644 --- a/cmd/nerdctl/system_prune.go +++ b/cmd/nerdctl/system_prune.go @@ -24,6 +24,7 @@ import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/system" @@ -45,7 +46,7 @@ func newSystemPruneCommand() *cobra.Command { } func processSystemPruneOptions(cmd *cobra.Command) (types.SystemPruneOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.SystemPruneOptions{}, err } diff --git a/cmd/nerdctl/version.go b/cmd/nerdctl/version.go index 6eb2528dce5..627c8b1940a 100644 --- a/cmd/nerdctl/version.go +++ b/cmd/nerdctl/version.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/infoutil" @@ -53,7 +54,7 @@ func newVersionCommand() *cobra.Command { func versionAction(cmd *cobra.Command, args []string) error { var w io.Writer = os.Stdout var tmpl *template.Template - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume_create.go index fefc7d2c0c4..95ef82d8b52 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume_create.go @@ -23,6 +23,7 @@ import ( "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" ) @@ -41,7 +42,7 @@ func newVolumeCreateCommand() *cobra.Command { } func processVolumeCreateOptions(cmd *cobra.Command) (types.VolumeCreateOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.VolumeCreateOptions{}, err } diff --git a/cmd/nerdctl/volume_inspect.go b/cmd/nerdctl/volume_inspect.go index 9c76242b7f3..f38b5269744 100644 --- a/cmd/nerdctl/volume_inspect.go +++ b/cmd/nerdctl/volume_inspect.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" ) @@ -42,7 +43,7 @@ func newVolumeInspectCommand() *cobra.Command { } func processVolumeInspectOptions(cmd *cobra.Command) (types.VolumeInspectOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.VolumeInspectOptions{}, err } diff --git a/cmd/nerdctl/volume_list.go b/cmd/nerdctl/volume_list.go index b0a7f0783e1..70842abd16a 100644 --- a/cmd/nerdctl/volume_list.go +++ b/cmd/nerdctl/volume_list.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" @@ -46,7 +47,7 @@ func newVolumeLsCommand() *cobra.Command { } func processVolumeLsOptions(cmd *cobra.Command) (types.VolumeListOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.VolumeListOptions{}, err } diff --git a/cmd/nerdctl/volume_prune.go b/cmd/nerdctl/volume_prune.go index 1cc8d1168ce..1833d67dd99 100644 --- a/cmd/nerdctl/volume_prune.go +++ b/cmd/nerdctl/volume_prune.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" @@ -42,7 +43,7 @@ func newVolumePruneCommand() *cobra.Command { } func processVolumePruneOptions(cmd *cobra.Command) (types.VolumePruneOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.VolumePruneOptions{}, err } diff --git a/cmd/nerdctl/volume_remove.go b/cmd/nerdctl/volume_remove.go index 4acc340e172..67c142ec50f 100644 --- a/cmd/nerdctl/volume_remove.go +++ b/cmd/nerdctl/volume_remove.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" @@ -41,7 +42,7 @@ func newVolumeRmCommand() *cobra.Command { } func processVolumeRmOptions(cmd *cobra.Command) (types.VolumeRemoveOptions, error) { - globalOptions, err := processRootCmdFlags(cmd) + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.VolumeRemoveOptions{}, err } From 38bca1f32e0cd30755a5c6619ad26650a611fd1b Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 29 Aug 2024 12:02:39 -0700 Subject: [PATCH 0716/1066] Move completion to sub package Signed-off-by: apostasie --- cmd/nerdctl/apparmor_unload_linux.go | 3 +- cmd/nerdctl/builder_build.go | 3 +- cmd/nerdctl/{ => completion}/completion.go | 26 ++++-- cmd/nerdctl/completion/completion_freebsd.go | 23 +++++ .../{ => completion}/completion_linux.go | 17 +++- .../{ => completion}/completion_linux_test.go | 2 +- cmd/nerdctl/completion/completion_test.go | 27 ++++++ cmd/nerdctl/completion/completion_unix.go | 88 +++++++++++++++++++ cmd/nerdctl/completion/completion_windows.go | 40 +++++++++ cmd/nerdctl/container_attach.go | 3 +- cmd/nerdctl/container_commit.go | 3 +- cmd/nerdctl/container_diff.go | 3 +- cmd/nerdctl/container_exec.go | 3 +- cmd/nerdctl/container_inspect.go | 3 +- cmd/nerdctl/container_kill.go | 3 +- cmd/nerdctl/container_logs.go | 3 +- cmd/nerdctl/container_pause.go | 3 +- cmd/nerdctl/container_port.go | 3 +- cmd/nerdctl/container_remove.go | 3 +- cmd/nerdctl/container_rename.go | 3 +- cmd/nerdctl/container_run.go | 7 +- cmd/nerdctl/container_run_linux.go | 4 +- cmd/nerdctl/container_start.go | 3 +- cmd/nerdctl/container_stats.go | 3 +- cmd/nerdctl/container_stop.go | 3 +- cmd/nerdctl/container_top.go | 3 +- cmd/nerdctl/container_unpause.go | 3 +- cmd/nerdctl/container_update.go | 3 +- cmd/nerdctl/container_wait.go | 3 +- cmd/nerdctl/image_convert.go | 5 +- cmd/nerdctl/image_cryptutil.go | 5 +- cmd/nerdctl/image_history.go | 3 +- cmd/nerdctl/image_inspect.go | 5 +- cmd/nerdctl/image_list.go | 3 +- cmd/nerdctl/image_load.go | 3 +- cmd/nerdctl/image_pull.go | 3 +- cmd/nerdctl/image_push.go | 5 +- cmd/nerdctl/image_remove.go | 3 +- cmd/nerdctl/image_save.go | 5 +- cmd/nerdctl/image_tag.go | 3 +- cmd/nerdctl/inspect.go | 5 +- cmd/nerdctl/main.go | 9 +- cmd/nerdctl/main_freebsd.go | 4 - cmd/nerdctl/main_linux.go | 12 --- cmd/nerdctl/main_unix.go | 60 ------------- cmd/nerdctl/main_windows.go | 12 --- cmd/nerdctl/network_create.go | 5 +- cmd/nerdctl/network_create_unix.go | 15 +--- cmd/nerdctl/network_create_windows.go | 15 +--- cmd/nerdctl/network_inspect.go | 3 +- cmd/nerdctl/network_remove.go | 3 +- cmd/nerdctl/volume_inspect.go | 3 +- cmd/nerdctl/volume_list.go | 10 --- cmd/nerdctl/volume_remove.go | 3 +- 54 files changed, 308 insertions(+), 188 deletions(-) rename cmd/nerdctl/{ => completion}/completion.go (81%) create mode 100644 cmd/nerdctl/completion/completion_freebsd.go rename cmd/nerdctl/{ => completion}/completion_linux.go (62%) rename cmd/nerdctl/{ => completion}/completion_linux_test.go (99%) create mode 100644 cmd/nerdctl/completion/completion_test.go create mode 100644 cmd/nerdctl/completion/completion_unix.go create mode 100644 cmd/nerdctl/completion/completion_windows.go diff --git a/cmd/nerdctl/apparmor_unload_linux.go b/cmd/nerdctl/apparmor_unload_linux.go index 8ab8e1bf2c6..1fc82bc52bd 100644 --- a/cmd/nerdctl/apparmor_unload_linux.go +++ b/cmd/nerdctl/apparmor_unload_linux.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/pkg/cmd/apparmor" "github.com/containerd/nerdctl/v2/pkg/defaults" ) @@ -47,5 +48,5 @@ func apparmorUnloadAction(cmd *cobra.Command, args []string) error { } func apparmorUnloadShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteApparmorProfiles(cmd) + return completion.ShellCompleteApparmorProfiles(cmd) } diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index e496a16fc98..db2a20318bd 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -25,6 +25,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" @@ -72,7 +73,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" buildCommand.Flags().StringSlice("platform", []string{}, "Set target platform for build (e.g., \"amd64\", \"arm64\")") - buildCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + buildCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) buildCommand.Flags().StringArray("build-context", []string{}, "Additional build contexts (e.g., name=path)") // #endregion diff --git a/cmd/nerdctl/completion.go b/cmd/nerdctl/completion/completion.go similarity index 81% rename from cmd/nerdctl/completion.go rename to cmd/nerdctl/completion/completion.go index bf03fcdd7a9..8a5a447a835 100644 --- a/cmd/nerdctl/completion.go +++ b/cmd/nerdctl/completion/completion.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package completion import ( "context" @@ -25,12 +25,15 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/volume" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/netutil" ) -func shellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { +func ShellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError @@ -53,7 +56,7 @@ func shellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirec return candidates, cobra.ShellCompDirectiveNoFileComp } -func shellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd.ProcessStatus) bool) ([]string, cobra.ShellCompDirective) { +func ShellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd.ProcessStatus) bool) ([]string, cobra.ShellCompDirective) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError @@ -101,8 +104,8 @@ func shellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd. return candidates, cobra.ShellCompDirectiveNoFileComp } -// shellCompleteNetworkNames includes {"bridge","host","none"} -func shellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, cobra.ShellCompDirective) { +// ShellCompleteNetworkNames includes {"bridge","host","none"} +func ShellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, cobra.ShellCompDirective) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError @@ -134,7 +137,7 @@ func shellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, return candidates, cobra.ShellCompDirectiveNoFileComp } -func shellCompleteVolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { +func ShellCompleteVolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError @@ -150,7 +153,7 @@ func shellCompleteVolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDire return candidates, cobra.ShellCompDirectiveNoFileComp } -func shellCompletePlatforms(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func ShellCompletePlatforms(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { candidates := []string{ "amd64", "arm64", @@ -163,3 +166,12 @@ func shellCompletePlatforms(cmd *cobra.Command, args []string, toComplete string } return candidates, cobra.ShellCompDirectiveNoFileComp } + +func getVolumes(cmd *cobra.Command, globalOptions types.GlobalCommandOptions) (map[string]native.Volume, error) { + volumeSize, err := cmd.Flags().GetBool("size") + if err != nil { + // The `nerdctl volume rm` does not have the flag `size`, so set it to false as the default value. + volumeSize = false + } + return volume.Volumes(globalOptions.Namespace, globalOptions.DataRoot, globalOptions.Address, volumeSize, nil) +} diff --git a/cmd/nerdctl/completion/completion_freebsd.go b/cmd/nerdctl/completion/completion_freebsd.go new file mode 100644 index 00000000000..5ebfd57f1b6 --- /dev/null +++ b/cmd/nerdctl/completion/completion_freebsd.go @@ -0,0 +1,23 @@ +/* + 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 completion + +import "github.com/spf13/cobra" + +func ShellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/nerdctl/completion_linux.go b/cmd/nerdctl/completion/completion_linux.go similarity index 62% rename from cmd/nerdctl/completion_linux.go rename to cmd/nerdctl/completion/completion_linux.go index 12dd8297b3e..f94a2a018a3 100644 --- a/cmd/nerdctl/completion_linux.go +++ b/cmd/nerdctl/completion/completion_linux.go @@ -14,15 +14,17 @@ limitations under the License. */ -package main +package completion import ( "github.com/spf13/cobra" "github.com/containerd/nerdctl/v2/pkg/apparmorutil" + ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) -func shellCompleteApparmorProfiles(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { +func ShellCompleteApparmorProfiles(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { profiles, err := apparmorutil.Profiles() if err != nil { return nil, cobra.ShellCompDirectiveError @@ -33,3 +35,14 @@ func shellCompleteApparmorProfiles(cmd *cobra.Command) ([]string, cobra.ShellCom } return names, cobra.ShellCompDirectiveNoFileComp } + +func ShellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + candidates := []string{"cgroupfs"} + if ncdefaults.IsSystemdAvailable() { + candidates = append(candidates, "systemd") + } + if rootlessutil.IsRootless() { + candidates = append(candidates, "none") + } + return candidates, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/nerdctl/completion_linux_test.go b/cmd/nerdctl/completion/completion_linux_test.go similarity index 99% rename from cmd/nerdctl/completion_linux_test.go rename to cmd/nerdctl/completion/completion_linux_test.go index 13d96163d61..8abb5483964 100644 --- a/cmd/nerdctl/completion_linux_test.go +++ b/cmd/nerdctl/completion/completion_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package completion import ( "testing" diff --git a/cmd/nerdctl/completion/completion_test.go b/cmd/nerdctl/completion/completion_test.go new file mode 100644 index 00000000000..f37df496baf --- /dev/null +++ b/cmd/nerdctl/completion/completion_test.go @@ -0,0 +1,27 @@ +/* + 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 completion + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/completion/completion_unix.go b/cmd/nerdctl/completion/completion_unix.go new file mode 100644 index 00000000000..1379c825f1c --- /dev/null +++ b/cmd/nerdctl/completion/completion_unix.go @@ -0,0 +1,88 @@ +//go:build unix + +/* + 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 completion + +import ( + "github.com/spf13/cobra" + + "github.com/containerd/log" + + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/infoutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" +) + +func ShellCompleteNetworkDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + candidates := []string{"bridge", "macvlan", "ipvlan"} + return candidates, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteIPAMDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"default", "host-local", "dhcp"}, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + if rootlessutil.IsRootlessParent() { + _ = rootlessutil.ParentMain(globalOptions.HostGatewayIP) + return nil, cobra.ShellCompDirectiveNoFileComp + } + + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + defer cancel() + nsService := client.NamespaceService() + nsList, err := nsService.List(ctx) + if err != nil { + log.L.Warn(err) + return nil, cobra.ShellCompDirectiveError + } + var candidates []string + candidates = append(candidates, nsList...) + return candidates, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + globalOptions, err := helpers.ProcessRootCmdFlags(cmd) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + if rootlessutil.IsRootlessParent() { + _ = rootlessutil.ParentMain(globalOptions.HostGatewayIP) + return nil, cobra.ShellCompDirectiveNoFileComp + } + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + defer cancel() + snapshotterPlugins, err := infoutil.GetSnapshotterNames(ctx, client.IntrospectionService()) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + var candidates []string + candidates = append(candidates, snapshotterPlugins...) + return candidates, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/nerdctl/completion/completion_windows.go b/cmd/nerdctl/completion/completion_windows.go new file mode 100644 index 00000000000..1739017b95b --- /dev/null +++ b/cmd/nerdctl/completion/completion_windows.go @@ -0,0 +1,40 @@ +/* + 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 completion + +import "github.com/spf13/cobra" + +func ShellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteNetworkDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + candidates := []string{"nat"} + return candidates, cobra.ShellCompDirectiveNoFileComp +} + +func ShellCompleteIPAMDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"default"}, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/nerdctl/container_attach.go b/cmd/nerdctl/container_attach.go index 031915c46a7..011184fbb78 100644 --- a/cmd/nerdctl/container_attach.go +++ b/cmd/nerdctl/container_attach.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -95,5 +96,5 @@ func attachShellComplete(cmd *cobra.Command, args []string, toComplete string) ( statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_commit.go b/cmd/nerdctl/container_commit.go index 42a6539f246..e531150a8b2 100644 --- a/cmd/nerdctl/container_commit.go +++ b/cmd/nerdctl/container_commit.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -93,7 +94,7 @@ func commitAction(cmd *cobra.Command, args []string) error { func commitShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index 1606345a8a7..051c84e1ec7 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -33,6 +33,7 @@ import ( "github.com/containerd/log" "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -226,5 +227,5 @@ func appendChanges(changes []fs.Change, new fs.Change) []fs.Change { func diffShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_exec.go b/cmd/nerdctl/container_exec.go index a9e68e53b9e..c1bcb9180d5 100644 --- a/cmd/nerdctl/container_exec.go +++ b/cmd/nerdctl/container_exec.go @@ -25,6 +25,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -157,7 +158,7 @@ func execShellComplete(cmd *cobra.Command, args []string, toComplete string) ([] statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/container_inspect.go b/cmd/nerdctl/container_inspect.go index e2b11946c57..230986a70d8 100644 --- a/cmd/nerdctl/container_inspect.go +++ b/cmd/nerdctl/container_inspect.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -104,5 +105,5 @@ func containerInspectAction(cmd *cobra.Command, args []string) error { func containerInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_kill.go b/cmd/nerdctl/container_kill.go index 846c94c111a..85e5c75cc82 100644 --- a/cmd/nerdctl/container_kill.go +++ b/cmd/nerdctl/container_kill.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -71,5 +72,5 @@ func killShellComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobr statusFilterFn := func(st containerd.ProcessStatus) bool { return st != containerd.Stopped && st != containerd.Created && st != containerd.Unknown } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_logs.go b/cmd/nerdctl/container_logs.go index 4f9a2a2a39b..6569f30da93 100644 --- a/cmd/nerdctl/container_logs.go +++ b/cmd/nerdctl/container_logs.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -116,7 +117,7 @@ func logsAction(cmd *cobra.Command, args []string) error { func logsShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names (TODO: only show containers with logs) - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } // Attempts to parse the argument given to `-n/--tail` as a uint. diff --git a/cmd/nerdctl/container_pause.go b/cmd/nerdctl/container_pause.go index fba77b27a0a..8cbea33b2b9 100644 --- a/cmd/nerdctl/container_pause.go +++ b/cmd/nerdctl/container_pause.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -71,5 +72,5 @@ func pauseShellComplete(cmd *cobra.Command, args []string, toComplete string) ([ statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_port.go b/cmd/nerdctl/container_port.go index dd9d7a73fd8..984464871f4 100644 --- a/cmd/nerdctl/container_port.go +++ b/cmd/nerdctl/container_port.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/containerutil" @@ -100,5 +101,5 @@ func portAction(cmd *cobra.Command, args []string) error { } func portShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_remove.go b/cmd/nerdctl/container_remove.go index 4e80f5a138a..9adf2ee7319 100644 --- a/cmd/nerdctl/container_remove.go +++ b/cmd/nerdctl/container_remove.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -72,5 +73,5 @@ func rmAction(cmd *cobra.Command, args []string) error { func rmShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_rename.go b/cmd/nerdctl/container_rename.go index 9e0400f7e1a..f9938d64d3b 100644 --- a/cmd/nerdctl/container_rename.go +++ b/cmd/nerdctl/container_rename.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -62,5 +63,5 @@ func renameAction(cmd *cobra.Command, args []string) error { return container.Rename(ctx, client, args[0], args[1], options) } func renameShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 1a8b46c1646..514b0262268 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/console" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/pkg/annotations" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -105,18 +106,18 @@ func setCreateFlags(cmd *cobra.Command) { // #region platform flags cmd.Flags().String("platform", "", "Set platform (e.g. \"amd64\", \"arm64\")") // not a slice, and there is no --all-platforms - cmd.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + cmd.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) // #endregion // #region network flags // network (net) is defined as StringSlice, not StringArray, to allow specifying "--network=cni1,cni2" cmd.Flags().StringSlice("network", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|"container:"|)`) cmd.RegisterFlagCompletionFunc("network", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteNetworkNames(cmd, []string{}) + return completion.ShellCompleteNetworkNames(cmd, []string{}) }) cmd.Flags().StringSlice("net", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|)`) cmd.RegisterFlagCompletionFunc("net", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteNetworkNames(cmd, []string{}) + return completion.ShellCompleteNetworkNames(cmd, []string{}) }) // dns is defined as StringSlice, not StringArray, to allow specifying "--dns=1.1.1.1,8.8.8.8" (compatible with Podman) cmd.Flags().StringSlice("dns", nil, "Set custom DNS servers") diff --git a/cmd/nerdctl/container_run_linux.go b/cmd/nerdctl/container_run_linux.go index 28d3f543160..c4059796317 100644 --- a/cmd/nerdctl/container_run_linux.go +++ b/cmd/nerdctl/container_run_linux.go @@ -22,6 +22,8 @@ import ( "github.com/spf13/cobra" "github.com/containerd/containerd/v2/pkg/cap" + + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" ) func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -36,7 +38,7 @@ func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]s func runShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/container_start.go b/cmd/nerdctl/container_start.go index 562a63567a1..446108f3b7f 100644 --- a/cmd/nerdctl/container_start.go +++ b/cmd/nerdctl/container_start.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -87,5 +88,5 @@ func startShellComplete(cmd *cobra.Command, args []string, toComplete string) ([ statusFilterFn := func(st containerd.ProcessStatus) bool { return st != containerd.Running && st != containerd.Unknown } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_stats.go b/cmd/nerdctl/container_stats.go index d07c5334698..a28c118a0a0 100644 --- a/cmd/nerdctl/container_stats.go +++ b/cmd/nerdctl/container_stats.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -106,5 +107,5 @@ func statsShellComplete(cmd *cobra.Command, args []string, toComplete string) ([ statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_stop.go b/cmd/nerdctl/container_stop.go index fee0183c92c..7789eccee76 100644 --- a/cmd/nerdctl/container_stop.go +++ b/cmd/nerdctl/container_stop.go @@ -23,6 +23,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -85,5 +86,5 @@ func stopShellComplete(cmd *cobra.Command, args []string, toComplete string) ([] statusFilterFn := func(st containerd.ProcessStatus) bool { return st != containerd.Stopped && st != containerd.Created && st != containerd.Unknown } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_top.go b/cmd/nerdctl/container_top.go index 5376895d96b..2c1910bf1d2 100644 --- a/cmd/nerdctl/container_top.go +++ b/cmd/nerdctl/container_top.go @@ -24,6 +24,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -77,5 +78,5 @@ func topShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]s statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_unpause.go b/cmd/nerdctl/container_unpause.go index 7fec1c06a6a..043791bb12a 100644 --- a/cmd/nerdctl/container_unpause.go +++ b/cmd/nerdctl/container_unpause.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -71,5 +72,5 @@ func unpauseShellComplete(cmd *cobra.Command, args []string, toComplete string) statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Paused } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index f6b9357c661..4adedd36968 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -33,6 +33,7 @@ import ( "github.com/containerd/log" "github.com/containerd/typeurl/v2" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -398,5 +399,5 @@ func copySpec(spec *runtimespec.Spec) (*runtimespec.Spec, error) { } func updateShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return shellCompleteContainerNames(cmd, nil) + return completion.ShellCompleteContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_wait.go b/cmd/nerdctl/container_wait.go index 03b33abee58..7756ce9d393 100644 --- a/cmd/nerdctl/container_wait.go +++ b/cmd/nerdctl/container_wait.go @@ -21,6 +21,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -71,5 +72,5 @@ func waitShellComplete(cmd *cobra.Command, args []string, toComplete string) ([] statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return shellCompleteContainerNames(cmd, statusFilterFn) + return completion.ShellCompleteContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/image_convert.go b/cmd/nerdctl/image_convert.go index ddefa598dc6..49b7c7c40ce 100644 --- a/cmd/nerdctl/image_convert.go +++ b/cmd/nerdctl/image_convert.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -96,7 +97,7 @@ func newImageConvertCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" imageConvertCommand.Flags().StringSlice("platform", []string{}, "Convert content for a specific platform") - imageConvertCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + imageConvertCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) imageConvertCommand.Flags().Bool("all-platforms", false, "Convert content for all platforms") // #endregion @@ -298,5 +299,5 @@ func imageConvertAction(cmd *cobra.Command, args []string) error { func imageConvertShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/image_cryptutil.go b/cmd/nerdctl/image_cryptutil.go index adee05a6b55..db4a2cb172e 100644 --- a/cmd/nerdctl/image_cryptutil.go +++ b/cmd/nerdctl/image_cryptutil.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -37,7 +38,7 @@ func registerImgcryptFlags(cmd *cobra.Command, encrypt bool) { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" flags.StringSlice("platform", []string{}, "Convert content for a specific platform") - cmd.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + cmd.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) flags.Bool("all-platforms", false, "Convert content for all platforms") // #endregion @@ -124,5 +125,5 @@ func getImgcryptAction(encrypt bool) func(cmd *cobra.Command, args []string) err func imgcryptShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index e22cb0601a3..78ef813a506 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -35,6 +35,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/formatter" @@ -271,5 +272,5 @@ func (x *historyPrinter) printHistory(printable historyPrintable) error { func historyShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/image_inspect.go b/cmd/nerdctl/image_inspect.go index 0b0222cb043..d86be752100 100644 --- a/cmd/nerdctl/image_inspect.go +++ b/cmd/nerdctl/image_inspect.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -47,7 +48,7 @@ func newImageInspectCommand() *cobra.Command { // #region platform flags imageInspectCommand.Flags().String("platform", "", "Inspect a specific platform") // not a slice, and there is no --all-platforms - imageInspectCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + imageInspectCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) // #endregion return imageInspectCommand @@ -99,5 +100,5 @@ func imageInspectAction(cmd *cobra.Command, args []string) error { func imageInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/image_list.go b/cmd/nerdctl/image_list.go index 71616a53989..e8851e17ef4 100644 --- a/cmd/nerdctl/image_list.go +++ b/cmd/nerdctl/image_list.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -147,7 +148,7 @@ func imagesAction(cmd *cobra.Command, args []string) error { func imagesShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/image_load.go b/cmd/nerdctl/image_load.go index ed09919aaf0..2c361335dbc 100644 --- a/cmd/nerdctl/image_load.go +++ b/cmd/nerdctl/image_load.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -41,7 +42,7 @@ func newLoadCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" loadCommand.Flags().StringSlice("platform", []string{}, "Import content for a specific platform") - loadCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + loadCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) loadCommand.Flags().Bool("all-platforms", false, "Import content for all platforms") // #endregion diff --git a/cmd/nerdctl/image_pull.go b/cmd/nerdctl/image_pull.go index f54a007d08e..9da715044a9 100644 --- a/cmd/nerdctl/image_pull.go +++ b/cmd/nerdctl/image_pull.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -44,7 +45,7 @@ func newPullCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" pullCommand.Flags().StringSlice("platform", nil, "Pull content for a specific platform") - pullCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + pullCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) pullCommand.Flags().Bool("all-platforms", false, "Pull content for all platforms") // #endregion diff --git a/cmd/nerdctl/image_push.go b/cmd/nerdctl/image_push.go index 02e88885a40..374a47d4c75 100644 --- a/cmd/nerdctl/image_push.go +++ b/cmd/nerdctl/image_push.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -42,7 +43,7 @@ func newPushCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" pushCommand.Flags().StringSlice("platform", []string{}, "Push content for a specific platform") - pushCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + pushCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) pushCommand.Flags().Bool("all-platforms", false, "Push content for all platforms") // #endregion @@ -145,7 +146,7 @@ func pushAction(cmd *cobra.Command, args []string) error { func pushShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } func processImageSignOptions(cmd *cobra.Command) (opt types.ImageSignOptions, err error) { diff --git a/cmd/nerdctl/image_remove.go b/cmd/nerdctl/image_remove.go index 5e677f642d5..0173b2b34e0 100644 --- a/cmd/nerdctl/image_remove.go +++ b/cmd/nerdctl/image_remove.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -81,5 +82,5 @@ func rmiAction(cmd *cobra.Command, args []string) error { func rmiShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/image_save.go b/cmd/nerdctl/image_save.go index 9c744bdb324..3dc0eb539a8 100644 --- a/cmd/nerdctl/image_save.go +++ b/cmd/nerdctl/image_save.go @@ -23,6 +23,7 @@ import ( "github.com/mattn/go-isatty" "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -45,7 +46,7 @@ func newSaveCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" saveCommand.Flags().StringSlice("platform", []string{}, "Export content for a specific platform") - saveCommand.RegisterFlagCompletionFunc("platform", shellCompletePlatforms) + saveCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) saveCommand.Flags().Bool("all-platforms", false, "Export content for all platforms") // #endregion @@ -110,5 +111,5 @@ func saveAction(cmd *cobra.Command, args []string) error { func saveShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } diff --git a/cmd/nerdctl/image_tag.go b/cmd/nerdctl/image_tag.go index ddc3995ad51..d0bc52003c5 100644 --- a/cmd/nerdctl/image_tag.go +++ b/cmd/nerdctl/image_tag.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -62,7 +63,7 @@ func tagAction(cmd *cobra.Command, args []string) error { func tagShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) < 2 { // show image names - return shellCompleteImageNames(cmd) + return completion.ShellCompleteImageNames(cmd) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/inspect.go b/cmd/nerdctl/inspect.go index dad2b35ded8..e74860a5371 100644 --- a/cmd/nerdctl/inspect.go +++ b/cmd/nerdctl/inspect.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -166,8 +167,8 @@ func inspectAction(cmd *cobra.Command, args []string) error { func inspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names - containers, _ := shellCompleteContainerNames(cmd, nil) + containers, _ := completion.ShellCompleteContainerNames(cmd, nil) // show image names - images, _ := shellCompleteImageNames(cmd) + images, _ := completion.ShellCompleteImageNames(cmd) return append(containers, images...), cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index f875052a09f..b326d382456 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -32,6 +32,7 @@ import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/config" ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" @@ -162,15 +163,15 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, AddPersistentStringFlag(rootCmd, "address", []string{"a", "H"}, nil, []string{"host"}, aliasToBeInherited, cfg.Address, "CONTAINERD_ADDRESS", `containerd address, optionally with "unix://" prefix`) // -n is aliases (conflicts with nerdctl logs -n) AddPersistentStringFlag(rootCmd, "namespace", []string{"n"}, nil, nil, aliasToBeInherited, cfg.Namespace, "CONTAINERD_NAMESPACE", `containerd namespace, such as "moby" for Docker, "k8s.io" for Kubernetes`) - rootCmd.RegisterFlagCompletionFunc("namespace", shellCompleteNamespaceNames) + rootCmd.RegisterFlagCompletionFunc("namespace", completion.ShellCompleteNamespaceNames) AddPersistentStringFlag(rootCmd, "snapshotter", nil, nil, []string{"storage-driver"}, aliasToBeInherited, cfg.Snapshotter, "CONTAINERD_SNAPSHOTTER", "containerd snapshotter") - rootCmd.RegisterFlagCompletionFunc("snapshotter", shellCompleteSnapshotterNames) - rootCmd.RegisterFlagCompletionFunc("storage-driver", shellCompleteSnapshotterNames) + rootCmd.RegisterFlagCompletionFunc("snapshotter", completion.ShellCompleteSnapshotterNames) + rootCmd.RegisterFlagCompletionFunc("storage-driver", completion.ShellCompleteSnapshotterNames) AddPersistentStringFlag(rootCmd, "cni-path", nil, nil, nil, aliasToBeInherited, cfg.CNIPath, "CNI_PATH", "cni plugins binary directory") AddPersistentStringFlag(rootCmd, "cni-netconfpath", nil, nil, nil, aliasToBeInherited, cfg.CNINetConfPath, "NETCONFPATH", "cni config directory") rootCmd.PersistentFlags().String("data-root", cfg.DataRoot, "Root directory of persistent nerdctl state (managed by nerdctl, not by containerd)") rootCmd.PersistentFlags().String("cgroup-manager", cfg.CgroupManager, `Cgroup manager to use ("cgroupfs"|"systemd")`) - rootCmd.RegisterFlagCompletionFunc("cgroup-manager", shellCompleteCgroupManagerNames) + rootCmd.RegisterFlagCompletionFunc("cgroup-manager", completion.ShellCompleteCgroupManagerNames) rootCmd.PersistentFlags().Bool("insecure-registry", cfg.InsecureRegistry, "skips verifying HTTPS certs, and allows falling back to plain HTTP") // hosts-dir is defined as StringSlice, not StringArray, to allow specifying "--hosts-dir=/etc/containerd/certs.d,/etc/docker/certs.d" rootCmd.PersistentFlags().StringSlice("hosts-dir", cfg.HostsDir, "A directory that contains /hosts.toml (containerd style) or /{ca.cert, cert.pem, key.pem} (docker style)") diff --git a/cmd/nerdctl/main_freebsd.go b/cmd/nerdctl/main_freebsd.go index 30ed7a9c1ea..46880c81e87 100644 --- a/cmd/nerdctl/main_freebsd.go +++ b/cmd/nerdctl/main_freebsd.go @@ -24,10 +24,6 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { return false } -func shellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} - func addApparmorCommand(rootCmd *cobra.Command) { // NOP } diff --git a/cmd/nerdctl/main_linux.go b/cmd/nerdctl/main_linux.go index 1512c05a678..2e0c0a853e2 100644 --- a/cmd/nerdctl/main_linux.go +++ b/cmd/nerdctl/main_linux.go @@ -19,7 +19,6 @@ package main import ( "github.com/spf13/cobra" - ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" ) @@ -63,17 +62,6 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { return true } -func shellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - candidates := []string{"cgroupfs"} - if ncdefaults.IsSystemdAvailable() { - candidates = append(candidates, "systemd") - } - if rootlessutil.IsRootless() { - candidates = append(candidates, "none") - } - return candidates, cobra.ShellCompDirectiveNoFileComp -} - func addApparmorCommand(rootCmd *cobra.Command) { rootCmd.AddCommand(newApparmorCommand()) } diff --git a/cmd/nerdctl/main_unix.go b/cmd/nerdctl/main_unix.go index e66bdfb8950..e29c3c6075c 100644 --- a/cmd/nerdctl/main_unix.go +++ b/cmd/nerdctl/main_unix.go @@ -17,63 +17,3 @@ */ package main - -import ( - "github.com/spf13/cobra" - - "github.com/containerd/log" - - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" - "github.com/containerd/nerdctl/v2/pkg/clientutil" - "github.com/containerd/nerdctl/v2/pkg/infoutil" - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" -) - -func shellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - globalOptions, err := helpers.ProcessRootCmdFlags(cmd) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - if rootlessutil.IsRootlessParent() { - _ = rootlessutil.ParentMain(globalOptions.HostGatewayIP) - return nil, cobra.ShellCompDirectiveNoFileComp - } - - client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - defer cancel() - nsService := client.NamespaceService() - nsList, err := nsService.List(ctx) - if err != nil { - log.L.Warn(err) - return nil, cobra.ShellCompDirectiveError - } - var candidates []string - candidates = append(candidates, nsList...) - return candidates, cobra.ShellCompDirectiveNoFileComp -} - -func shellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - globalOptions, err := helpers.ProcessRootCmdFlags(cmd) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - if rootlessutil.IsRootlessParent() { - _ = rootlessutil.ParentMain(globalOptions.HostGatewayIP) - return nil, cobra.ShellCompDirectiveNoFileComp - } - client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - defer cancel() - snapshotterPlugins, err := infoutil.GetSnapshotterNames(ctx, client.IntrospectionService()) - if err != nil { - return nil, cobra.ShellCompDirectiveError - } - var candidates []string - candidates = append(candidates, snapshotterPlugins...) - return candidates, cobra.ShellCompDirectiveNoFileComp -} diff --git a/cmd/nerdctl/main_windows.go b/cmd/nerdctl/main_windows.go index e8c48782a20..46880c81e87 100644 --- a/cmd/nerdctl/main_windows.go +++ b/cmd/nerdctl/main_windows.go @@ -24,18 +24,6 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { return false } -func shellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} - -func shellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} - -func shellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} - func addApparmorCommand(rootCmd *cobra.Command) { // NOP } diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index a14f30777a4..e9c12522eb6 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" @@ -39,10 +40,10 @@ func newNetworkCreateCommand() *cobra.Command { SilenceErrors: true, } networkCreateCommand.Flags().StringP("driver", "d", DefaultNetworkDriver, "Driver to manage the Network") - networkCreateCommand.RegisterFlagCompletionFunc("driver", shellCompleteNetworkDrivers) + networkCreateCommand.RegisterFlagCompletionFunc("driver", completion.ShellCompleteNetworkDrivers) networkCreateCommand.Flags().StringArrayP("opt", "o", nil, "Set driver specific options") networkCreateCommand.Flags().String("ipam-driver", "default", "IP Address Management Driver") - networkCreateCommand.RegisterFlagCompletionFunc("ipam-driver", shellCompleteIPAMDrivers) + networkCreateCommand.RegisterFlagCompletionFunc("ipam-driver", completion.ShellCompleteIPAMDrivers) networkCreateCommand.Flags().StringArray("ipam-opt", nil, "Set IPAM driver specific options") networkCreateCommand.Flags().StringArray("subnet", nil, `Subnet in CIDR format that represents a network segment, e.g. "10.5.0.0/16"`) networkCreateCommand.Flags().String("gateway", "", `Gateway for the master subnet`) diff --git a/cmd/nerdctl/network_create_unix.go b/cmd/nerdctl/network_create_unix.go index 5abc60accc4..a04b6fb790a 100644 --- a/cmd/nerdctl/network_create_unix.go +++ b/cmd/nerdctl/network_create_unix.go @@ -18,17 +18,4 @@ package main -import "github.com/spf13/cobra" - -const ( - DefaultNetworkDriver = "bridge" -) - -func shellCompleteNetworkDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - candidates := []string{"bridge", "macvlan", "ipvlan"} - return candidates, cobra.ShellCompDirectiveNoFileComp -} - -func shellCompleteIPAMDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"default", "host-local", "dhcp"}, cobra.ShellCompDirectiveNoFileComp -} +const DefaultNetworkDriver = "bridge" diff --git a/cmd/nerdctl/network_create_windows.go b/cmd/nerdctl/network_create_windows.go index 2d6acf7e92b..9c11f3c3e81 100644 --- a/cmd/nerdctl/network_create_windows.go +++ b/cmd/nerdctl/network_create_windows.go @@ -16,17 +16,4 @@ package main -import "github.com/spf13/cobra" - -const ( - DefaultNetworkDriver = "nat" -) - -func shellCompleteNetworkDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - candidates := []string{"nat"} - return candidates, cobra.ShellCompDirectiveNoFileComp -} - -func shellCompleteIPAMDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"default"}, cobra.ShellCompDirectiveNoFileComp -} +const DefaultNetworkDriver = "nat" diff --git a/cmd/nerdctl/network_inspect.go b/cmd/nerdctl/network_inspect.go index a1952e761c3..927a50d1a9a 100644 --- a/cmd/nerdctl/network_inspect.go +++ b/cmd/nerdctl/network_inspect.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/network" @@ -70,5 +71,5 @@ func networkInspectAction(cmd *cobra.Command, args []string) error { func networkInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show network names, including "bridge" exclude := []string{"host", "none"} - return shellCompleteNetworkNames(cmd, exclude) + return completion.ShellCompleteNetworkNames(cmd, exclude) } diff --git a/cmd/nerdctl/network_remove.go b/cmd/nerdctl/network_remove.go index dac95ed6af4..e68b12b37cb 100644 --- a/cmd/nerdctl/network_remove.go +++ b/cmd/nerdctl/network_remove.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -65,5 +66,5 @@ func networkRmAction(cmd *cobra.Command, args []string) error { func networkRmShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show network names, including "bridge" exclude := []string{netutil.DefaultNetworkName, "host", "none"} - return shellCompleteNetworkNames(cmd, exclude) + return completion.ShellCompleteNetworkNames(cmd, exclude) } diff --git a/cmd/nerdctl/volume_inspect.go b/cmd/nerdctl/volume_inspect.go index f38b5269744..88cf067496f 100644 --- a/cmd/nerdctl/volume_inspect.go +++ b/cmd/nerdctl/volume_inspect.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" @@ -73,5 +74,5 @@ func volumeInspectAction(cmd *cobra.Command, args []string) error { func volumeInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show volume names - return shellCompleteVolumeNames(cmd) + return completion.ShellCompleteVolumeNames(cmd) } diff --git a/cmd/nerdctl/volume_list.go b/cmd/nerdctl/volume_list.go index 70842abd16a..6c15ee4da4d 100644 --- a/cmd/nerdctl/volume_list.go +++ b/cmd/nerdctl/volume_list.go @@ -22,7 +22,6 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" ) func newVolumeLsCommand() *cobra.Command { @@ -84,12 +83,3 @@ func volumeLsAction(cmd *cobra.Command, args []string) error { } return volume.List(options) } - -func getVolumes(cmd *cobra.Command, globalOptions types.GlobalCommandOptions) (map[string]native.Volume, error) { - volumeSize, err := cmd.Flags().GetBool("size") - if err != nil { - // The `nerdctl volume rm` does not have the flag `size`, so set it to false as the default value. - volumeSize = false - } - return volume.Volumes(globalOptions.Namespace, globalOptions.DataRoot, globalOptions.Address, volumeSize, nil) -} diff --git a/cmd/nerdctl/volume_remove.go b/cmd/nerdctl/volume_remove.go index 67c142ec50f..8b1b5907f39 100644 --- a/cmd/nerdctl/volume_remove.go +++ b/cmd/nerdctl/volume_remove.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" @@ -74,5 +75,5 @@ func volumeRmAction(cmd *cobra.Command, args []string) error { func volumeRmShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show volume names - return shellCompleteVolumeNames(cmd) + return completion.ShellCompleteVolumeNames(cmd) } From ec530147e2390a99c0be7e85593b060e467a4dfe Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 29 Aug 2024 12:37:29 -0700 Subject: [PATCH 0717/1066] Move constants Categroy/Management to helpers Signed-off-by: apostasie --- cmd/nerdctl/apparmor_linux.go | 4 +++- cmd/nerdctl/builder.go | 2 +- cmd/nerdctl/container.go | 4 +++- cmd/nerdctl/helpers/consts.go | 22 ++++++++++++++++++++++ cmd/nerdctl/image.go | 4 +++- cmd/nerdctl/ipfs.go | 4 +++- cmd/nerdctl/ipfs_registry.go | 4 +++- cmd/nerdctl/main.go | 11 +++-------- cmd/nerdctl/namespace.go | 2 +- cmd/nerdctl/network.go | 4 +++- cmd/nerdctl/network_create.go | 2 +- cmd/nerdctl/system.go | 8 ++++++-- cmd/nerdctl/volume.go | 4 +++- 13 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 cmd/nerdctl/helpers/consts.go diff --git a/cmd/nerdctl/apparmor_linux.go b/cmd/nerdctl/apparmor_linux.go index e39985e9294..1d833289e1d 100644 --- a/cmd/nerdctl/apparmor_linux.go +++ b/cmd/nerdctl/apparmor_linux.go @@ -18,11 +18,13 @@ package main import ( "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) func newApparmorCommand() *cobra.Command { cmd := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "apparmor", Short: "Manage AppArmor profiles", RunE: unknownSubcommandAction, diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index 9a6bb5c5c98..397b9f92812 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -32,7 +32,7 @@ import ( func newBuilderCommand() *cobra.Command { var builderCommand = &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "builder", Short: "Manage builds", RunE: unknownSubcommandAction, diff --git a/cmd/nerdctl/container.go b/cmd/nerdctl/container.go index 05cef331ab6..892fbdf0fda 100644 --- a/cmd/nerdctl/container.go +++ b/cmd/nerdctl/container.go @@ -18,11 +18,13 @@ package main import ( "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) func newContainerCommand() *cobra.Command { containerCommand := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "container", Short: "Manage containers", RunE: unknownSubcommandAction, diff --git a/cmd/nerdctl/helpers/consts.go b/cmd/nerdctl/helpers/consts.go new file mode 100644 index 00000000000..ff1cc06ad99 --- /dev/null +++ b/cmd/nerdctl/helpers/consts.go @@ -0,0 +1,22 @@ +/* + 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 helpers + +const ( + Category = "category" + Management = "management" +) diff --git a/cmd/nerdctl/image.go b/cmd/nerdctl/image.go index afae1936335..c14a81c9bf0 100644 --- a/cmd/nerdctl/image.go +++ b/cmd/nerdctl/image.go @@ -18,11 +18,13 @@ package main import ( "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) func newImageCommand() *cobra.Command { cmd := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "image", Short: "Manage images", RunE: unknownSubcommandAction, diff --git a/cmd/nerdctl/ipfs.go b/cmd/nerdctl/ipfs.go index 871077e1e5f..3c5c4b85368 100644 --- a/cmd/nerdctl/ipfs.go +++ b/cmd/nerdctl/ipfs.go @@ -18,11 +18,13 @@ package main import ( "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) func newIPFSCommand() *cobra.Command { cmd := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "ipfs", Short: "Distributing images on IPFS", RunE: unknownSubcommandAction, diff --git a/cmd/nerdctl/ipfs_registry.go b/cmd/nerdctl/ipfs_registry.go index 3211ad6ed8c..7a090e13261 100644 --- a/cmd/nerdctl/ipfs_registry.go +++ b/cmd/nerdctl/ipfs_registry.go @@ -18,11 +18,13 @@ package main import ( "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) func newIPFSRegistryCommand() *cobra.Command { cmd := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "registry", Short: "Manage read-only registry backed by IPFS", PreRunE: checkExperimental("ipfs"), diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index b326d382456..4dc26af179e 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -42,11 +42,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/version" ) -const ( - Category = "category" - Management = "management" -) - var ( // To print Bold Text Bold = color.New(color.Bold).SprintfFunc() @@ -75,7 +70,7 @@ func usage(c *cobra.Command) error { if f.Hidden { continue } - if f.Annotations[Category] == Management { + if f.Annotations[helpers.Category] == helpers.Management { managementCommands = append(managementCommands, f) } else { nonManagementCommands = append(nonManagementCommands, f) @@ -103,7 +98,7 @@ func usage(c *cobra.Command) error { t += "\n" return t } - s += printCommands("Management commands", managementCommands) + s += printCommands("helpers.Management commands", managementCommands) s += printCommands("Commands", nonManagementCommands) s += Bold("Flags") + ":\n" @@ -293,7 +288,7 @@ Config file ($NERDCTL_TOML): %s newTopCommand(), newStatsCommand(), - // #region Management + // #region helpers.Management newContainerCommand(), newImageCommand(), newNetworkCommand(), diff --git a/cmd/nerdctl/namespace.go b/cmd/nerdctl/namespace.go index 3086c9d06a6..d96bc1e384c 100644 --- a/cmd/nerdctl/namespace.go +++ b/cmd/nerdctl/namespace.go @@ -35,7 +35,7 @@ import ( func newNamespaceCommand() *cobra.Command { namespaceCommand := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "namespace", Aliases: []string{"ns"}, Short: "Manage containerd namespaces", diff --git a/cmd/nerdctl/network.go b/cmd/nerdctl/network.go index cc9b38d5f51..6fc3db11feb 100644 --- a/cmd/nerdctl/network.go +++ b/cmd/nerdctl/network.go @@ -18,11 +18,13 @@ package main import ( "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) func newNetworkCommand() *cobra.Command { networkCommand := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "network", Short: "Manage networks", RunE: unknownSubcommandAction, diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index e9c12522eb6..84b39af357a 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -42,7 +42,7 @@ func newNetworkCreateCommand() *cobra.Command { networkCreateCommand.Flags().StringP("driver", "d", DefaultNetworkDriver, "Driver to manage the Network") networkCreateCommand.RegisterFlagCompletionFunc("driver", completion.ShellCompleteNetworkDrivers) networkCreateCommand.Flags().StringArrayP("opt", "o", nil, "Set driver specific options") - networkCreateCommand.Flags().String("ipam-driver", "default", "IP Address Management Driver") + networkCreateCommand.Flags().String("ipam-driver", "default", "IP Address helpers.Management Driver") networkCreateCommand.RegisterFlagCompletionFunc("ipam-driver", completion.ShellCompleteIPAMDrivers) networkCreateCommand.Flags().StringArray("ipam-opt", nil, "Set IPAM driver specific options") networkCreateCommand.Flags().StringArray("subnet", nil, `Subnet in CIDR format that represents a network segment, e.g. "10.5.0.0/16"`) diff --git a/cmd/nerdctl/system.go b/cmd/nerdctl/system.go index bb9635be295..facd7b36ab5 100644 --- a/cmd/nerdctl/system.go +++ b/cmd/nerdctl/system.go @@ -16,11 +16,15 @@ package main -import "github.com/spf13/cobra" +import ( + "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" +) func newSystemCommand() *cobra.Command { var systemCommand = &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "system", Short: "Manage containerd", RunE: unknownSubcommandAction, diff --git a/cmd/nerdctl/volume.go b/cmd/nerdctl/volume.go index b34d1cd471d..ffdb3b9f471 100644 --- a/cmd/nerdctl/volume.go +++ b/cmd/nerdctl/volume.go @@ -18,11 +18,13 @@ package main import ( "github.com/spf13/cobra" + + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) func newVolumeCommand() *cobra.Command { volumeCommand := &cobra.Command{ - Annotations: map[string]string{Category: Management}, + Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "volume", Short: "Manage volumes", RunE: unknownSubcommandAction, From 061d0cb1711ad2c1160cd8159e2e0477089bbe5e Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 29 Aug 2024 12:40:36 -0700 Subject: [PATCH 0718/1066] Move UnknownSubcommandAction to helpers Signed-off-by: apostasie --- cmd/nerdctl/apparmor_linux.go | 2 +- cmd/nerdctl/builder.go | 2 +- cmd/nerdctl/compose.go | 3 ++- cmd/nerdctl/container.go | 2 +- cmd/nerdctl/helpers/cobra.go | 43 +++++++++++++++++++++++++++++++++++ cmd/nerdctl/image.go | 2 +- cmd/nerdctl/ipfs.go | 2 +- cmd/nerdctl/ipfs_registry.go | 2 +- cmd/nerdctl/main.go | 21 +---------------- cmd/nerdctl/namespace.go | 2 +- cmd/nerdctl/network.go | 2 +- cmd/nerdctl/system.go | 2 +- cmd/nerdctl/volume.go | 2 +- 13 files changed, 56 insertions(+), 31 deletions(-) create mode 100644 cmd/nerdctl/helpers/cobra.go diff --git a/cmd/nerdctl/apparmor_linux.go b/cmd/nerdctl/apparmor_linux.go index 1d833289e1d..c94a80258ff 100644 --- a/cmd/nerdctl/apparmor_linux.go +++ b/cmd/nerdctl/apparmor_linux.go @@ -27,7 +27,7 @@ func newApparmorCommand() *cobra.Command { Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "apparmor", Short: "Manage AppArmor profiles", - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index 397b9f92812..6bfb99e456a 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -35,7 +35,7 @@ func newBuilderCommand() *cobra.Command { Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "builder", Short: "Manage builds", - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } diff --git a/cmd/nerdctl/compose.go b/cmd/nerdctl/compose.go index 927f2024dd3..5c3a30368c0 100644 --- a/cmd/nerdctl/compose.go +++ b/cmd/nerdctl/compose.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/composer" ) @@ -26,7 +27,7 @@ func newComposeCommand() *cobra.Command { var composeCommand = &cobra.Command{ Use: "compose [flags] COMMAND", Short: "Compose", - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, TraverseChildren: true, // required for global short hands like -f diff --git a/cmd/nerdctl/container.go b/cmd/nerdctl/container.go index 892fbdf0fda..9db284f5919 100644 --- a/cmd/nerdctl/container.go +++ b/cmd/nerdctl/container.go @@ -27,7 +27,7 @@ func newContainerCommand() *cobra.Command { Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "container", Short: "Manage containers", - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } diff --git a/cmd/nerdctl/helpers/cobra.go b/cmd/nerdctl/helpers/cobra.go new file mode 100644 index 00000000000..791c33deb0e --- /dev/null +++ b/cmd/nerdctl/helpers/cobra.go @@ -0,0 +1,43 @@ +/* + 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 helpers + +import ( + "errors" + "fmt" + + "github.com/spf13/cobra" +) + +// UnknownSubcommandAction is needed to let `nerdctl system non-existent-command` fail +// https://github.com/containerd/nerdctl/issues/487 +// +// Ideally this should be implemented in Cobra itself. +func UnknownSubcommandAction(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return cmd.Help() + } + // The output mimics https://github.com/spf13/cobra/blob/v1.2.1/command.go#L647-L662 + msg := fmt.Sprintf("unknown subcommand %q for %q", args[0], cmd.Name()) + if suggestions := cmd.SuggestionsFor(args[0]); len(suggestions) > 0 { + msg += "\n\nDid you mean this?\n" + for _, s := range suggestions { + msg += fmt.Sprintf("\t%v\n", s) + } + } + return errors.New(msg) +} diff --git a/cmd/nerdctl/image.go b/cmd/nerdctl/image.go index c14a81c9bf0..0a0f190483a 100644 --- a/cmd/nerdctl/image.go +++ b/cmd/nerdctl/image.go @@ -27,7 +27,7 @@ func newImageCommand() *cobra.Command { Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "image", Short: "Manage images", - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } diff --git a/cmd/nerdctl/ipfs.go b/cmd/nerdctl/ipfs.go index 3c5c4b85368..eb08d3dd022 100644 --- a/cmd/nerdctl/ipfs.go +++ b/cmd/nerdctl/ipfs.go @@ -27,7 +27,7 @@ func newIPFSCommand() *cobra.Command { Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "ipfs", Short: "Distributing images on IPFS", - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } diff --git a/cmd/nerdctl/ipfs_registry.go b/cmd/nerdctl/ipfs_registry.go index 7a090e13261..68b9b6e7458 100644 --- a/cmd/nerdctl/ipfs_registry.go +++ b/cmd/nerdctl/ipfs_registry.go @@ -28,7 +28,7 @@ func newIPFSRegistryCommand() *cobra.Command { Use: "registry", Short: "Manage read-only registry backed by IPFS", PreRunE: checkExperimental("ipfs"), - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 4dc26af179e..ff4eb35af47 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -234,7 +234,7 @@ Config file ($NERDCTL_TOML): %s } return nil } - rootCmd.RunE = unknownSubcommandAction + rootCmd.RunE = helpers.UnknownSubcommandAction rootCmd.AddCommand( newCreateCommand(), // #region Run & Exec @@ -346,25 +346,6 @@ func globalFlags(cmd *cobra.Command) (string, []string) { return args0, args } -// unknownSubcommandAction is needed to let `nerdctl system non-existent-command` fail -// https://github.com/containerd/nerdctl/issues/487 -// -// Ideally this should be implemented in Cobra itself. -func unknownSubcommandAction(cmd *cobra.Command, args []string) error { - if len(args) == 0 { - return cmd.Help() - } - // The output mimics https://github.com/spf13/cobra/blob/v1.2.1/command.go#L647-L662 - msg := fmt.Sprintf("unknown subcommand %q for %q", args[0], cmd.Name()) - if suggestions := cmd.SuggestionsFor(args[0]); len(suggestions) > 0 { - msg += "\n\nDid you mean this?\n" - for _, s := range suggestions { - msg += fmt.Sprintf("\t%v\n", s) - } - } - return errors.New(msg) -} - // AddStringFlag is similar to cmd.Flags().String but supports aliases and env var func AddStringFlag(cmd *cobra.Command, name string, aliases []string, value string, env, usage string) { if env != "" { diff --git a/cmd/nerdctl/namespace.go b/cmd/nerdctl/namespace.go index d96bc1e384c..59b2858aa43 100644 --- a/cmd/nerdctl/namespace.go +++ b/cmd/nerdctl/namespace.go @@ -40,7 +40,7 @@ func newNamespaceCommand() *cobra.Command { Aliases: []string{"ns"}, Short: "Manage containerd namespaces", Long: "Unrelated to Linux namespaces and Kubernetes namespaces", - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } diff --git a/cmd/nerdctl/network.go b/cmd/nerdctl/network.go index 6fc3db11feb..b957b61a8eb 100644 --- a/cmd/nerdctl/network.go +++ b/cmd/nerdctl/network.go @@ -27,7 +27,7 @@ func newNetworkCommand() *cobra.Command { Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "network", Short: "Manage networks", - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } diff --git a/cmd/nerdctl/system.go b/cmd/nerdctl/system.go index facd7b36ab5..1119fded332 100644 --- a/cmd/nerdctl/system.go +++ b/cmd/nerdctl/system.go @@ -27,7 +27,7 @@ func newSystemCommand() *cobra.Command { Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "system", Short: "Manage containerd", - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } diff --git a/cmd/nerdctl/volume.go b/cmd/nerdctl/volume.go index ffdb3b9f471..3e6c2ce120e 100644 --- a/cmd/nerdctl/volume.go +++ b/cmd/nerdctl/volume.go @@ -27,7 +27,7 @@ func newVolumeCommand() *cobra.Command { Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "volume", Short: "Manage volumes", - RunE: unknownSubcommandAction, + RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, } From a07d90665d727bdd9080751ec3e72d705ad31ee4 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 29 Aug 2024 12:45:11 -0700 Subject: [PATCH 0719/1066] Move volume actions under subpackage Signed-off-by: apostasie --- cmd/nerdctl/main.go | 3 ++- cmd/nerdctl/{ => volume}/volume.go | 4 +-- cmd/nerdctl/{ => volume}/volume_create.go | 2 +- .../{ => volume}/volume_create_test.go | 2 +- cmd/nerdctl/{ => volume}/volume_inspect.go | 2 +- .../{ => volume}/volume_inspect_test.go | 2 +- cmd/nerdctl/{ => volume}/volume_list.go | 2 +- cmd/nerdctl/{ => volume}/volume_list_test.go | 2 +- .../{ => volume}/volume_namespace_test.go | 2 +- cmd/nerdctl/{ => volume}/volume_prune.go | 2 +- .../{ => volume}/volume_prune_linux_test.go | 2 +- cmd/nerdctl/{ => volume}/volume_remove.go | 2 +- .../{ => volume}/volume_remove_linux_test.go | 2 +- cmd/nerdctl/volume/volume_test.go | 27 +++++++++++++++++++ 14 files changed, 42 insertions(+), 14 deletions(-) rename cmd/nerdctl/{ => volume}/volume.go (95%) rename cmd/nerdctl/{ => volume}/volume_create.go (99%) rename cmd/nerdctl/{ => volume}/volume_create_test.go (99%) rename cmd/nerdctl/{ => volume}/volume_inspect.go (99%) rename cmd/nerdctl/{ => volume}/volume_inspect_test.go (99%) rename cmd/nerdctl/{ => volume}/volume_list.go (99%) rename cmd/nerdctl/{ => volume}/volume_list_test.go (99%) rename cmd/nerdctl/{ => volume}/volume_namespace_test.go (99%) rename cmd/nerdctl/{ => volume}/volume_prune.go (99%) rename cmd/nerdctl/{ => volume}/volume_prune_linux_test.go (99%) rename cmd/nerdctl/{ => volume}/volume_remove.go (99%) rename cmd/nerdctl/{ => volume}/volume_remove_linux_test.go (99%) create mode 100644 cmd/nerdctl/volume/volume_test.go diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index ff4eb35af47..99e2068ae15 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -34,6 +34,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/volume" "github.com/containerd/nerdctl/v2/pkg/config" ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" "github.com/containerd/nerdctl/v2/pkg/errutil" @@ -292,7 +293,7 @@ Config file ($NERDCTL_TOML): %s newContainerCommand(), newImageCommand(), newNetworkCommand(), - newVolumeCommand(), + volume.NewVolumeCommand(), newSystemCommand(), newNamespaceCommand(), newBuilderCommand(), diff --git a/cmd/nerdctl/volume.go b/cmd/nerdctl/volume/volume.go similarity index 95% rename from cmd/nerdctl/volume.go rename to cmd/nerdctl/volume/volume.go index 3e6c2ce120e..352993096b9 100644 --- a/cmd/nerdctl/volume.go +++ b/cmd/nerdctl/volume/volume.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "github.com/spf13/cobra" @@ -22,7 +22,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) -func newVolumeCommand() *cobra.Command { +func NewVolumeCommand() *cobra.Command { volumeCommand := &cobra.Command{ Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "volume", diff --git a/cmd/nerdctl/volume_create.go b/cmd/nerdctl/volume/volume_create.go similarity index 99% rename from cmd/nerdctl/volume_create.go rename to cmd/nerdctl/volume/volume_create.go index 95ef82d8b52..6927c4a556e 100644 --- a/cmd/nerdctl/volume_create.go +++ b/cmd/nerdctl/volume/volume_create.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "fmt" diff --git a/cmd/nerdctl/volume_create_test.go b/cmd/nerdctl/volume/volume_create_test.go similarity index 99% rename from cmd/nerdctl/volume_create_test.go rename to cmd/nerdctl/volume/volume_create_test.go index 9780fc3d20e..a9126f704f7 100644 --- a/cmd/nerdctl/volume_create_test.go +++ b/cmd/nerdctl/volume/volume_create_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "testing" diff --git a/cmd/nerdctl/volume_inspect.go b/cmd/nerdctl/volume/volume_inspect.go similarity index 99% rename from cmd/nerdctl/volume_inspect.go rename to cmd/nerdctl/volume/volume_inspect.go index 88cf067496f..bda84ef77f3 100644 --- a/cmd/nerdctl/volume_inspect.go +++ b/cmd/nerdctl/volume/volume_inspect.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/volume_inspect_test.go b/cmd/nerdctl/volume/volume_inspect_test.go similarity index 99% rename from cmd/nerdctl/volume_inspect_test.go rename to cmd/nerdctl/volume/volume_inspect_test.go index 9b7dfb31e15..0d4ce4e6d05 100644 --- a/cmd/nerdctl/volume_inspect_test.go +++ b/cmd/nerdctl/volume/volume_inspect_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "crypto/rand" diff --git a/cmd/nerdctl/volume_list.go b/cmd/nerdctl/volume/volume_list.go similarity index 99% rename from cmd/nerdctl/volume_list.go rename to cmd/nerdctl/volume/volume_list.go index 6c15ee4da4d..891a626a09c 100644 --- a/cmd/nerdctl/volume_list.go +++ b/cmd/nerdctl/volume/volume_list.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/volume_list_test.go b/cmd/nerdctl/volume/volume_list_test.go similarity index 99% rename from cmd/nerdctl/volume_list_test.go rename to cmd/nerdctl/volume/volume_list_test.go index cbab079ef5c..6195db2eb13 100644 --- a/cmd/nerdctl/volume_list_test.go +++ b/cmd/nerdctl/volume/volume_list_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "errors" diff --git a/cmd/nerdctl/volume_namespace_test.go b/cmd/nerdctl/volume/volume_namespace_test.go similarity index 99% rename from cmd/nerdctl/volume_namespace_test.go rename to cmd/nerdctl/volume/volume_namespace_test.go index 8c775d49a08..dcda29a3648 100644 --- a/cmd/nerdctl/volume_namespace_test.go +++ b/cmd/nerdctl/volume/volume_namespace_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "testing" diff --git a/cmd/nerdctl/volume_prune.go b/cmd/nerdctl/volume/volume_prune.go similarity index 99% rename from cmd/nerdctl/volume_prune.go rename to cmd/nerdctl/volume/volume_prune.go index 1833d67dd99..cbc74fb882f 100644 --- a/cmd/nerdctl/volume_prune.go +++ b/cmd/nerdctl/volume/volume_prune.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "fmt" diff --git a/cmd/nerdctl/volume_prune_linux_test.go b/cmd/nerdctl/volume/volume_prune_linux_test.go similarity index 99% rename from cmd/nerdctl/volume_prune_linux_test.go rename to cmd/nerdctl/volume/volume_prune_linux_test.go index 17f6ad539c7..19632a73992 100644 --- a/cmd/nerdctl/volume_prune_linux_test.go +++ b/cmd/nerdctl/volume/volume_prune_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "strings" diff --git a/cmd/nerdctl/volume_remove.go b/cmd/nerdctl/volume/volume_remove.go similarity index 99% rename from cmd/nerdctl/volume_remove.go rename to cmd/nerdctl/volume/volume_remove.go index 8b1b5907f39..6e8bad49b8f 100644 --- a/cmd/nerdctl/volume_remove.go +++ b/cmd/nerdctl/volume/volume_remove.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/volume_remove_linux_test.go b/cmd/nerdctl/volume/volume_remove_linux_test.go similarity index 99% rename from cmd/nerdctl/volume_remove_linux_test.go rename to cmd/nerdctl/volume/volume_remove_linux_test.go index b5757946720..04c67a131aa 100644 --- a/cmd/nerdctl/volume_remove_linux_test.go +++ b/cmd/nerdctl/volume/volume_remove_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package volume import ( "fmt" diff --git a/cmd/nerdctl/volume/volume_test.go b/cmd/nerdctl/volume/volume_test.go new file mode 100644 index 00000000000..980319ec60a --- /dev/null +++ b/cmd/nerdctl/volume/volume_test.go @@ -0,0 +1,27 @@ +/* + 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 volume + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} From d2741bafca3c855fb09d333b67b38afd9746a8cc Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 08:53:37 -0700 Subject: [PATCH 0720/1066] Rename completion.ShellCompleteX methods to completion.X Signed-off-by: apostasie --- cmd/nerdctl/apparmor_unload_linux.go | 2 +- cmd/nerdctl/builder_build.go | 2 +- cmd/nerdctl/completion/completion.go | 12 ++++++------ cmd/nerdctl/completion/completion_freebsd.go | 2 +- cmd/nerdctl/completion/completion_linux.go | 4 ++-- cmd/nerdctl/completion/completion_unix.go | 8 ++++---- cmd/nerdctl/completion/completion_windows.go | 10 +++++----- cmd/nerdctl/container_attach.go | 2 +- cmd/nerdctl/container_commit.go | 2 +- cmd/nerdctl/container_diff.go | 2 +- cmd/nerdctl/container_exec.go | 2 +- cmd/nerdctl/container_inspect.go | 2 +- cmd/nerdctl/container_kill.go | 2 +- cmd/nerdctl/container_logs.go | 2 +- cmd/nerdctl/container_pause.go | 2 +- cmd/nerdctl/container_port.go | 2 +- cmd/nerdctl/container_remove.go | 2 +- cmd/nerdctl/container_rename.go | 2 +- cmd/nerdctl/container_run.go | 6 +++--- cmd/nerdctl/container_run_linux.go | 2 +- cmd/nerdctl/container_start.go | 2 +- cmd/nerdctl/container_stats.go | 2 +- cmd/nerdctl/container_stop.go | 2 +- cmd/nerdctl/container_top.go | 2 +- cmd/nerdctl/container_unpause.go | 2 +- cmd/nerdctl/container_update.go | 2 +- cmd/nerdctl/container_wait.go | 2 +- cmd/nerdctl/image_convert.go | 4 ++-- cmd/nerdctl/image_cryptutil.go | 4 ++-- cmd/nerdctl/image_history.go | 2 +- cmd/nerdctl/image_inspect.go | 4 ++-- cmd/nerdctl/image_list.go | 2 +- cmd/nerdctl/image_load.go | 2 +- cmd/nerdctl/image_pull.go | 2 +- cmd/nerdctl/image_push.go | 4 ++-- cmd/nerdctl/image_remove.go | 2 +- cmd/nerdctl/image_save.go | 4 ++-- cmd/nerdctl/image_tag.go | 2 +- cmd/nerdctl/inspect.go | 4 ++-- cmd/nerdctl/main.go | 8 ++++---- cmd/nerdctl/network_create.go | 4 ++-- cmd/nerdctl/network_inspect.go | 2 +- cmd/nerdctl/network_remove.go | 2 +- cmd/nerdctl/volume/volume_inspect.go | 2 +- cmd/nerdctl/volume/volume_remove.go | 2 +- 45 files changed, 70 insertions(+), 70 deletions(-) diff --git a/cmd/nerdctl/apparmor_unload_linux.go b/cmd/nerdctl/apparmor_unload_linux.go index 1fc82bc52bd..c20aab68765 100644 --- a/cmd/nerdctl/apparmor_unload_linux.go +++ b/cmd/nerdctl/apparmor_unload_linux.go @@ -48,5 +48,5 @@ func apparmorUnloadAction(cmd *cobra.Command, args []string) error { } func apparmorUnloadShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return completion.ShellCompleteApparmorProfiles(cmd) + return completion.ApparmorProfiles(cmd) } diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index db2a20318bd..50810a8d0fe 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -73,7 +73,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" buildCommand.Flags().StringSlice("platform", []string{}, "Set target platform for build (e.g., \"amd64\", \"arm64\")") - buildCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) + buildCommand.RegisterFlagCompletionFunc("platform", completion.Platforms) buildCommand.Flags().StringArray("build-context", []string{}, "Additional build contexts (e.g., name=path)") // #endregion diff --git a/cmd/nerdctl/completion/completion.go b/cmd/nerdctl/completion/completion.go index 8a5a447a835..ea7352d8561 100644 --- a/cmd/nerdctl/completion/completion.go +++ b/cmd/nerdctl/completion/completion.go @@ -33,7 +33,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/netutil" ) -func ShellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { +func ImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError @@ -56,7 +56,7 @@ func ShellCompleteImageNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirec return candidates, cobra.ShellCompDirectiveNoFileComp } -func ShellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd.ProcessStatus) bool) ([]string, cobra.ShellCompDirective) { +func ContainerNames(cmd *cobra.Command, filterFunc func(containerd.ProcessStatus) bool) ([]string, cobra.ShellCompDirective) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError @@ -104,8 +104,8 @@ func ShellCompleteContainerNames(cmd *cobra.Command, filterFunc func(containerd. return candidates, cobra.ShellCompDirectiveNoFileComp } -// ShellCompleteNetworkNames includes {"bridge","host","none"} -func ShellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, cobra.ShellCompDirective) { +// NetworkNames includes {"bridge","host","none"} +func NetworkNames(cmd *cobra.Command, exclude []string) ([]string, cobra.ShellCompDirective) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError @@ -137,7 +137,7 @@ func ShellCompleteNetworkNames(cmd *cobra.Command, exclude []string) ([]string, return candidates, cobra.ShellCompDirectiveNoFileComp } -func ShellCompleteVolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { +func VolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError @@ -153,7 +153,7 @@ func ShellCompleteVolumeNames(cmd *cobra.Command) ([]string, cobra.ShellCompDire return candidates, cobra.ShellCompDirectiveNoFileComp } -func ShellCompletePlatforms(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func Platforms(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { candidates := []string{ "amd64", "arm64", diff --git a/cmd/nerdctl/completion/completion_freebsd.go b/cmd/nerdctl/completion/completion_freebsd.go index 5ebfd57f1b6..465671cfc24 100644 --- a/cmd/nerdctl/completion/completion_freebsd.go +++ b/cmd/nerdctl/completion/completion_freebsd.go @@ -18,6 +18,6 @@ package completion import "github.com/spf13/cobra" -func ShellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func CgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/completion/completion_linux.go b/cmd/nerdctl/completion/completion_linux.go index f94a2a018a3..38a992c19b5 100644 --- a/cmd/nerdctl/completion/completion_linux.go +++ b/cmd/nerdctl/completion/completion_linux.go @@ -24,7 +24,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) -func ShellCompleteApparmorProfiles(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { +func ApparmorProfiles(cmd *cobra.Command) ([]string, cobra.ShellCompDirective) { profiles, err := apparmorutil.Profiles() if err != nil { return nil, cobra.ShellCompDirectiveError @@ -36,7 +36,7 @@ func ShellCompleteApparmorProfiles(cmd *cobra.Command) ([]string, cobra.ShellCom return names, cobra.ShellCompDirectiveNoFileComp } -func ShellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func CgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { candidates := []string{"cgroupfs"} if ncdefaults.IsSystemdAvailable() { candidates = append(candidates, "systemd") diff --git a/cmd/nerdctl/completion/completion_unix.go b/cmd/nerdctl/completion/completion_unix.go index 1379c825f1c..af0b8698ce2 100644 --- a/cmd/nerdctl/completion/completion_unix.go +++ b/cmd/nerdctl/completion/completion_unix.go @@ -29,16 +29,16 @@ import ( "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) -func ShellCompleteNetworkDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func NetworkDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { candidates := []string{"bridge", "macvlan", "ipvlan"} return candidates, cobra.ShellCompDirectiveNoFileComp } -func ShellCompleteIPAMDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func IPAMDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"default", "host-local", "dhcp"}, cobra.ShellCompDirectiveNoFileComp } -func ShellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func NamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError @@ -64,7 +64,7 @@ func ShellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete s return candidates, cobra.ShellCompDirectiveNoFileComp } -func ShellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func SnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return nil, cobra.ShellCompDirectiveError diff --git a/cmd/nerdctl/completion/completion_windows.go b/cmd/nerdctl/completion/completion_windows.go index 1739017b95b..020e0594926 100644 --- a/cmd/nerdctl/completion/completion_windows.go +++ b/cmd/nerdctl/completion/completion_windows.go @@ -18,23 +18,23 @@ package completion import "github.com/spf13/cobra" -func ShellCompleteNamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func NamespaceNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return nil, cobra.ShellCompDirectiveNoFileComp } -func ShellCompleteSnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func SnapshotterNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return nil, cobra.ShellCompDirectiveNoFileComp } -func ShellCompleteCgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func CgroupManagerNames(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return nil, cobra.ShellCompDirectiveNoFileComp } -func ShellCompleteNetworkDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func NetworkDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { candidates := []string{"nat"} return candidates, cobra.ShellCompDirectiveNoFileComp } -func ShellCompleteIPAMDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { +func IPAMDrivers(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"default"}, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/container_attach.go b/cmd/nerdctl/container_attach.go index 011184fbb78..0bcbc9830c8 100644 --- a/cmd/nerdctl/container_attach.go +++ b/cmd/nerdctl/container_attach.go @@ -96,5 +96,5 @@ func attachShellComplete(cmd *cobra.Command, args []string, toComplete string) ( statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return completion.ShellCompleteContainerNames(cmd, statusFilterFn) + return completion.ContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_commit.go b/cmd/nerdctl/container_commit.go index e531150a8b2..aa646bcd580 100644 --- a/cmd/nerdctl/container_commit.go +++ b/cmd/nerdctl/container_commit.go @@ -94,7 +94,7 @@ func commitAction(cmd *cobra.Command, args []string) error { func commitShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { - return completion.ShellCompleteContainerNames(cmd, nil) + return completion.ContainerNames(cmd, nil) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container_diff.go index 051c84e1ec7..3e2025ea27e 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container_diff.go @@ -227,5 +227,5 @@ func appendChanges(changes []fs.Change, new fs.Change) []fs.Change { func diffShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names - return completion.ShellCompleteContainerNames(cmd, nil) + return completion.ContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_exec.go b/cmd/nerdctl/container_exec.go index c1bcb9180d5..eb559b5515b 100644 --- a/cmd/nerdctl/container_exec.go +++ b/cmd/nerdctl/container_exec.go @@ -158,7 +158,7 @@ func execShellComplete(cmd *cobra.Command, args []string, toComplete string) ([] statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return completion.ShellCompleteContainerNames(cmd, statusFilterFn) + return completion.ContainerNames(cmd, statusFilterFn) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/container_inspect.go b/cmd/nerdctl/container_inspect.go index 230986a70d8..e0d5ab5e35f 100644 --- a/cmd/nerdctl/container_inspect.go +++ b/cmd/nerdctl/container_inspect.go @@ -105,5 +105,5 @@ func containerInspectAction(cmd *cobra.Command, args []string) error { func containerInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names - return completion.ShellCompleteContainerNames(cmd, nil) + return completion.ContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_kill.go b/cmd/nerdctl/container_kill.go index 85e5c75cc82..dd50a24a8cd 100644 --- a/cmd/nerdctl/container_kill.go +++ b/cmd/nerdctl/container_kill.go @@ -72,5 +72,5 @@ func killShellComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobr statusFilterFn := func(st containerd.ProcessStatus) bool { return st != containerd.Stopped && st != containerd.Created && st != containerd.Unknown } - return completion.ShellCompleteContainerNames(cmd, statusFilterFn) + return completion.ContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_logs.go b/cmd/nerdctl/container_logs.go index 6569f30da93..7d633038f48 100644 --- a/cmd/nerdctl/container_logs.go +++ b/cmd/nerdctl/container_logs.go @@ -117,7 +117,7 @@ func logsAction(cmd *cobra.Command, args []string) error { func logsShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names (TODO: only show containers with logs) - return completion.ShellCompleteContainerNames(cmd, nil) + return completion.ContainerNames(cmd, nil) } // Attempts to parse the argument given to `-n/--tail` as a uint. diff --git a/cmd/nerdctl/container_pause.go b/cmd/nerdctl/container_pause.go index 8cbea33b2b9..cf652d51703 100644 --- a/cmd/nerdctl/container_pause.go +++ b/cmd/nerdctl/container_pause.go @@ -72,5 +72,5 @@ func pauseShellComplete(cmd *cobra.Command, args []string, toComplete string) ([ statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return completion.ShellCompleteContainerNames(cmd, statusFilterFn) + return completion.ContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_port.go b/cmd/nerdctl/container_port.go index 984464871f4..8c35bfc75e8 100644 --- a/cmd/nerdctl/container_port.go +++ b/cmd/nerdctl/container_port.go @@ -101,5 +101,5 @@ func portAction(cmd *cobra.Command, args []string) error { } func portShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return completion.ShellCompleteContainerNames(cmd, nil) + return completion.ContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_remove.go b/cmd/nerdctl/container_remove.go index 9adf2ee7319..bf2962bd87e 100644 --- a/cmd/nerdctl/container_remove.go +++ b/cmd/nerdctl/container_remove.go @@ -73,5 +73,5 @@ func rmAction(cmd *cobra.Command, args []string) error { func rmShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names - return completion.ShellCompleteContainerNames(cmd, nil) + return completion.ContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_rename.go b/cmd/nerdctl/container_rename.go index f9938d64d3b..fcd724e8852 100644 --- a/cmd/nerdctl/container_rename.go +++ b/cmd/nerdctl/container_rename.go @@ -63,5 +63,5 @@ func renameAction(cmd *cobra.Command, args []string) error { return container.Rename(ctx, client, args[0], args[1], options) } func renameShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return completion.ShellCompleteContainerNames(cmd, nil) + return completion.ContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container_run.go index 514b0262268..c069dbb1c2d 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container_run.go @@ -106,18 +106,18 @@ func setCreateFlags(cmd *cobra.Command) { // #region platform flags cmd.Flags().String("platform", "", "Set platform (e.g. \"amd64\", \"arm64\")") // not a slice, and there is no --all-platforms - cmd.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) + cmd.RegisterFlagCompletionFunc("platform", completion.Platforms) // #endregion // #region network flags // network (net) is defined as StringSlice, not StringArray, to allow specifying "--network=cni1,cni2" cmd.Flags().StringSlice("network", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|"container:"|)`) cmd.RegisterFlagCompletionFunc("network", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return completion.ShellCompleteNetworkNames(cmd, []string{}) + return completion.NetworkNames(cmd, []string{}) }) cmd.Flags().StringSlice("net", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|)`) cmd.RegisterFlagCompletionFunc("net", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return completion.ShellCompleteNetworkNames(cmd, []string{}) + return completion.NetworkNames(cmd, []string{}) }) // dns is defined as StringSlice, not StringArray, to allow specifying "--dns=1.1.1.1,8.8.8.8" (compatible with Podman) cmd.Flags().StringSlice("dns", nil, "Set custom DNS servers") diff --git a/cmd/nerdctl/container_run_linux.go b/cmd/nerdctl/container_run_linux.go index c4059796317..92dace222b0 100644 --- a/cmd/nerdctl/container_run_linux.go +++ b/cmd/nerdctl/container_run_linux.go @@ -38,7 +38,7 @@ func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]s func runShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { - return completion.ShellCompleteImageNames(cmd) + return completion.ImageNames(cmd) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/container_start.go b/cmd/nerdctl/container_start.go index 446108f3b7f..9a2443d0aa2 100644 --- a/cmd/nerdctl/container_start.go +++ b/cmd/nerdctl/container_start.go @@ -88,5 +88,5 @@ func startShellComplete(cmd *cobra.Command, args []string, toComplete string) ([ statusFilterFn := func(st containerd.ProcessStatus) bool { return st != containerd.Running && st != containerd.Unknown } - return completion.ShellCompleteContainerNames(cmd, statusFilterFn) + return completion.ContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_stats.go b/cmd/nerdctl/container_stats.go index a28c118a0a0..985ac9cef5b 100644 --- a/cmd/nerdctl/container_stats.go +++ b/cmd/nerdctl/container_stats.go @@ -107,5 +107,5 @@ func statsShellComplete(cmd *cobra.Command, args []string, toComplete string) ([ statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return completion.ShellCompleteContainerNames(cmd, statusFilterFn) + return completion.ContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_stop.go b/cmd/nerdctl/container_stop.go index 7789eccee76..d35458d09ca 100644 --- a/cmd/nerdctl/container_stop.go +++ b/cmd/nerdctl/container_stop.go @@ -86,5 +86,5 @@ func stopShellComplete(cmd *cobra.Command, args []string, toComplete string) ([] statusFilterFn := func(st containerd.ProcessStatus) bool { return st != containerd.Stopped && st != containerd.Created && st != containerd.Unknown } - return completion.ShellCompleteContainerNames(cmd, statusFilterFn) + return completion.ContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_top.go b/cmd/nerdctl/container_top.go index 2c1910bf1d2..bc22587287c 100644 --- a/cmd/nerdctl/container_top.go +++ b/cmd/nerdctl/container_top.go @@ -78,5 +78,5 @@ func topShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]s statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return completion.ShellCompleteContainerNames(cmd, statusFilterFn) + return completion.ContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_unpause.go b/cmd/nerdctl/container_unpause.go index 043791bb12a..aaa72ce1475 100644 --- a/cmd/nerdctl/container_unpause.go +++ b/cmd/nerdctl/container_unpause.go @@ -72,5 +72,5 @@ func unpauseShellComplete(cmd *cobra.Command, args []string, toComplete string) statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Paused } - return completion.ShellCompleteContainerNames(cmd, statusFilterFn) + return completion.ContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container_update.go index 4adedd36968..3ca9f9a030c 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container_update.go @@ -399,5 +399,5 @@ func copySpec(spec *runtimespec.Spec) (*runtimespec.Spec, error) { } func updateShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return completion.ShellCompleteContainerNames(cmd, nil) + return completion.ContainerNames(cmd, nil) } diff --git a/cmd/nerdctl/container_wait.go b/cmd/nerdctl/container_wait.go index 7756ce9d393..b9af63c37ed 100644 --- a/cmd/nerdctl/container_wait.go +++ b/cmd/nerdctl/container_wait.go @@ -72,5 +72,5 @@ func waitShellComplete(cmd *cobra.Command, args []string, toComplete string) ([] statusFilterFn := func(st containerd.ProcessStatus) bool { return st == containerd.Running } - return completion.ShellCompleteContainerNames(cmd, statusFilterFn) + return completion.ContainerNames(cmd, statusFilterFn) } diff --git a/cmd/nerdctl/image_convert.go b/cmd/nerdctl/image_convert.go index 49b7c7c40ce..577099245f2 100644 --- a/cmd/nerdctl/image_convert.go +++ b/cmd/nerdctl/image_convert.go @@ -97,7 +97,7 @@ func newImageConvertCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" imageConvertCommand.Flags().StringSlice("platform", []string{}, "Convert content for a specific platform") - imageConvertCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) + imageConvertCommand.RegisterFlagCompletionFunc("platform", completion.Platforms) imageConvertCommand.Flags().Bool("all-platforms", false, "Convert content for all platforms") // #endregion @@ -299,5 +299,5 @@ func imageConvertAction(cmd *cobra.Command, args []string) error { func imageConvertShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return completion.ShellCompleteImageNames(cmd) + return completion.ImageNames(cmd) } diff --git a/cmd/nerdctl/image_cryptutil.go b/cmd/nerdctl/image_cryptutil.go index db4a2cb172e..067a0f1afe6 100644 --- a/cmd/nerdctl/image_cryptutil.go +++ b/cmd/nerdctl/image_cryptutil.go @@ -38,7 +38,7 @@ func registerImgcryptFlags(cmd *cobra.Command, encrypt bool) { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" flags.StringSlice("platform", []string{}, "Convert content for a specific platform") - cmd.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) + cmd.RegisterFlagCompletionFunc("platform", completion.Platforms) flags.Bool("all-platforms", false, "Convert content for all platforms") // #endregion @@ -125,5 +125,5 @@ func getImgcryptAction(encrypt bool) func(cmd *cobra.Command, args []string) err func imgcryptShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return completion.ShellCompleteImageNames(cmd) + return completion.ImageNames(cmd) } diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index 78ef813a506..d0633e2ed01 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -272,5 +272,5 @@ func (x *historyPrinter) printHistory(printable historyPrintable) error { func historyShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return completion.ShellCompleteImageNames(cmd) + return completion.ImageNames(cmd) } diff --git a/cmd/nerdctl/image_inspect.go b/cmd/nerdctl/image_inspect.go index d86be752100..c52e975df76 100644 --- a/cmd/nerdctl/image_inspect.go +++ b/cmd/nerdctl/image_inspect.go @@ -48,7 +48,7 @@ func newImageInspectCommand() *cobra.Command { // #region platform flags imageInspectCommand.Flags().String("platform", "", "Inspect a specific platform") // not a slice, and there is no --all-platforms - imageInspectCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) + imageInspectCommand.RegisterFlagCompletionFunc("platform", completion.Platforms) // #endregion return imageInspectCommand @@ -100,5 +100,5 @@ func imageInspectAction(cmd *cobra.Command, args []string) error { func imageInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return completion.ShellCompleteImageNames(cmd) + return completion.ImageNames(cmd) } diff --git a/cmd/nerdctl/image_list.go b/cmd/nerdctl/image_list.go index e8851e17ef4..c65e960347b 100644 --- a/cmd/nerdctl/image_list.go +++ b/cmd/nerdctl/image_list.go @@ -148,7 +148,7 @@ func imagesAction(cmd *cobra.Command, args []string) error { func imagesShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { // show image names - return completion.ShellCompleteImageNames(cmd) + return completion.ImageNames(cmd) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/image_load.go b/cmd/nerdctl/image_load.go index 2c361335dbc..2cf8fdf3c05 100644 --- a/cmd/nerdctl/image_load.go +++ b/cmd/nerdctl/image_load.go @@ -42,7 +42,7 @@ func newLoadCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" loadCommand.Flags().StringSlice("platform", []string{}, "Import content for a specific platform") - loadCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) + loadCommand.RegisterFlagCompletionFunc("platform", completion.Platforms) loadCommand.Flags().Bool("all-platforms", false, "Import content for all platforms") // #endregion diff --git a/cmd/nerdctl/image_pull.go b/cmd/nerdctl/image_pull.go index 9da715044a9..b7e75938649 100644 --- a/cmd/nerdctl/image_pull.go +++ b/cmd/nerdctl/image_pull.go @@ -45,7 +45,7 @@ func newPullCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" pullCommand.Flags().StringSlice("platform", nil, "Pull content for a specific platform") - pullCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) + pullCommand.RegisterFlagCompletionFunc("platform", completion.Platforms) pullCommand.Flags().Bool("all-platforms", false, "Pull content for all platforms") // #endregion diff --git a/cmd/nerdctl/image_push.go b/cmd/nerdctl/image_push.go index 374a47d4c75..37fee9d3937 100644 --- a/cmd/nerdctl/image_push.go +++ b/cmd/nerdctl/image_push.go @@ -43,7 +43,7 @@ func newPushCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" pushCommand.Flags().StringSlice("platform", []string{}, "Push content for a specific platform") - pushCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) + pushCommand.RegisterFlagCompletionFunc("platform", completion.Platforms) pushCommand.Flags().Bool("all-platforms", false, "Push content for all platforms") // #endregion @@ -146,7 +146,7 @@ func pushAction(cmd *cobra.Command, args []string) error { func pushShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return completion.ShellCompleteImageNames(cmd) + return completion.ImageNames(cmd) } func processImageSignOptions(cmd *cobra.Command) (opt types.ImageSignOptions, err error) { diff --git a/cmd/nerdctl/image_remove.go b/cmd/nerdctl/image_remove.go index 0173b2b34e0..dde5a6d035e 100644 --- a/cmd/nerdctl/image_remove.go +++ b/cmd/nerdctl/image_remove.go @@ -82,5 +82,5 @@ func rmiAction(cmd *cobra.Command, args []string) error { func rmiShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return completion.ShellCompleteImageNames(cmd) + return completion.ImageNames(cmd) } diff --git a/cmd/nerdctl/image_save.go b/cmd/nerdctl/image_save.go index 3dc0eb539a8..287e93c1b39 100644 --- a/cmd/nerdctl/image_save.go +++ b/cmd/nerdctl/image_save.go @@ -46,7 +46,7 @@ func newSaveCommand() *cobra.Command { // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" saveCommand.Flags().StringSlice("platform", []string{}, "Export content for a specific platform") - saveCommand.RegisterFlagCompletionFunc("platform", completion.ShellCompletePlatforms) + saveCommand.RegisterFlagCompletionFunc("platform", completion.Platforms) saveCommand.Flags().Bool("all-platforms", false, "Export content for all platforms") // #endregion @@ -111,5 +111,5 @@ func saveAction(cmd *cobra.Command, args []string) error { func saveShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show image names - return completion.ShellCompleteImageNames(cmd) + return completion.ImageNames(cmd) } diff --git a/cmd/nerdctl/image_tag.go b/cmd/nerdctl/image_tag.go index d0bc52003c5..7daef37cc9a 100644 --- a/cmd/nerdctl/image_tag.go +++ b/cmd/nerdctl/image_tag.go @@ -63,7 +63,7 @@ func tagAction(cmd *cobra.Command, args []string) error { func tagShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) < 2 { // show image names - return completion.ShellCompleteImageNames(cmd) + return completion.ImageNames(cmd) } return nil, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/inspect.go b/cmd/nerdctl/inspect.go index e74860a5371..14f92c8a379 100644 --- a/cmd/nerdctl/inspect.go +++ b/cmd/nerdctl/inspect.go @@ -167,8 +167,8 @@ func inspectAction(cmd *cobra.Command, args []string) error { func inspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show container names - containers, _ := completion.ShellCompleteContainerNames(cmd, nil) + containers, _ := completion.ContainerNames(cmd, nil) // show image names - images, _ := completion.ShellCompleteImageNames(cmd) + images, _ := completion.ImageNames(cmd) return append(containers, images...), cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 99e2068ae15..a8d4bba0aa2 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -159,15 +159,15 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, AddPersistentStringFlag(rootCmd, "address", []string{"a", "H"}, nil, []string{"host"}, aliasToBeInherited, cfg.Address, "CONTAINERD_ADDRESS", `containerd address, optionally with "unix://" prefix`) // -n is aliases (conflicts with nerdctl logs -n) AddPersistentStringFlag(rootCmd, "namespace", []string{"n"}, nil, nil, aliasToBeInherited, cfg.Namespace, "CONTAINERD_NAMESPACE", `containerd namespace, such as "moby" for Docker, "k8s.io" for Kubernetes`) - rootCmd.RegisterFlagCompletionFunc("namespace", completion.ShellCompleteNamespaceNames) + rootCmd.RegisterFlagCompletionFunc("namespace", completion.NamespaceNames) AddPersistentStringFlag(rootCmd, "snapshotter", nil, nil, []string{"storage-driver"}, aliasToBeInherited, cfg.Snapshotter, "CONTAINERD_SNAPSHOTTER", "containerd snapshotter") - rootCmd.RegisterFlagCompletionFunc("snapshotter", completion.ShellCompleteSnapshotterNames) - rootCmd.RegisterFlagCompletionFunc("storage-driver", completion.ShellCompleteSnapshotterNames) + rootCmd.RegisterFlagCompletionFunc("snapshotter", completion.SnapshotterNames) + rootCmd.RegisterFlagCompletionFunc("storage-driver", completion.SnapshotterNames) AddPersistentStringFlag(rootCmd, "cni-path", nil, nil, nil, aliasToBeInherited, cfg.CNIPath, "CNI_PATH", "cni plugins binary directory") AddPersistentStringFlag(rootCmd, "cni-netconfpath", nil, nil, nil, aliasToBeInherited, cfg.CNINetConfPath, "NETCONFPATH", "cni config directory") rootCmd.PersistentFlags().String("data-root", cfg.DataRoot, "Root directory of persistent nerdctl state (managed by nerdctl, not by containerd)") rootCmd.PersistentFlags().String("cgroup-manager", cfg.CgroupManager, `Cgroup manager to use ("cgroupfs"|"systemd")`) - rootCmd.RegisterFlagCompletionFunc("cgroup-manager", completion.ShellCompleteCgroupManagerNames) + rootCmd.RegisterFlagCompletionFunc("cgroup-manager", completion.CgroupManagerNames) rootCmd.PersistentFlags().Bool("insecure-registry", cfg.InsecureRegistry, "skips verifying HTTPS certs, and allows falling back to plain HTTP") // hosts-dir is defined as StringSlice, not StringArray, to allow specifying "--hosts-dir=/etc/containerd/certs.d,/etc/docker/certs.d" rootCmd.PersistentFlags().StringSlice("hosts-dir", cfg.HostsDir, "A directory that contains /hosts.toml (containerd style) or /{ca.cert, cert.pem, key.pem} (docker style)") diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index 84b39af357a..220c0da64d9 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -40,10 +40,10 @@ func newNetworkCreateCommand() *cobra.Command { SilenceErrors: true, } networkCreateCommand.Flags().StringP("driver", "d", DefaultNetworkDriver, "Driver to manage the Network") - networkCreateCommand.RegisterFlagCompletionFunc("driver", completion.ShellCompleteNetworkDrivers) + networkCreateCommand.RegisterFlagCompletionFunc("driver", completion.NetworkDrivers) networkCreateCommand.Flags().StringArrayP("opt", "o", nil, "Set driver specific options") networkCreateCommand.Flags().String("ipam-driver", "default", "IP Address helpers.Management Driver") - networkCreateCommand.RegisterFlagCompletionFunc("ipam-driver", completion.ShellCompleteIPAMDrivers) + networkCreateCommand.RegisterFlagCompletionFunc("ipam-driver", completion.IPAMDrivers) networkCreateCommand.Flags().StringArray("ipam-opt", nil, "Set IPAM driver specific options") networkCreateCommand.Flags().StringArray("subnet", nil, `Subnet in CIDR format that represents a network segment, e.g. "10.5.0.0/16"`) networkCreateCommand.Flags().String("gateway", "", `Gateway for the master subnet`) diff --git a/cmd/nerdctl/network_inspect.go b/cmd/nerdctl/network_inspect.go index 927a50d1a9a..f025922e445 100644 --- a/cmd/nerdctl/network_inspect.go +++ b/cmd/nerdctl/network_inspect.go @@ -71,5 +71,5 @@ func networkInspectAction(cmd *cobra.Command, args []string) error { func networkInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show network names, including "bridge" exclude := []string{"host", "none"} - return completion.ShellCompleteNetworkNames(cmd, exclude) + return completion.NetworkNames(cmd, exclude) } diff --git a/cmd/nerdctl/network_remove.go b/cmd/nerdctl/network_remove.go index e68b12b37cb..e40f53a4b4f 100644 --- a/cmd/nerdctl/network_remove.go +++ b/cmd/nerdctl/network_remove.go @@ -66,5 +66,5 @@ func networkRmAction(cmd *cobra.Command, args []string) error { func networkRmShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show network names, including "bridge" exclude := []string{netutil.DefaultNetworkName, "host", "none"} - return completion.ShellCompleteNetworkNames(cmd, exclude) + return completion.NetworkNames(cmd, exclude) } diff --git a/cmd/nerdctl/volume/volume_inspect.go b/cmd/nerdctl/volume/volume_inspect.go index bda84ef77f3..422df57ab3e 100644 --- a/cmd/nerdctl/volume/volume_inspect.go +++ b/cmd/nerdctl/volume/volume_inspect.go @@ -74,5 +74,5 @@ func volumeInspectAction(cmd *cobra.Command, args []string) error { func volumeInspectShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show volume names - return completion.ShellCompleteVolumeNames(cmd) + return completion.VolumeNames(cmd) } diff --git a/cmd/nerdctl/volume/volume_remove.go b/cmd/nerdctl/volume/volume_remove.go index 6e8bad49b8f..d4350b93cee 100644 --- a/cmd/nerdctl/volume/volume_remove.go +++ b/cmd/nerdctl/volume/volume_remove.go @@ -75,5 +75,5 @@ func volumeRmAction(cmd *cobra.Command, args []string) error { func volumeRmShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // show volume names - return completion.ShellCompleteVolumeNames(cmd) + return completion.VolumeNames(cmd) } From f7e033d9cdb04b5fad33678685b4c97b26399aa0 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 09:13:36 -0700 Subject: [PATCH 0721/1066] Move IsExactArgs and FindIPv6 to helpers Signed-off-by: apostasie --- cmd/nerdctl/container_commit.go | 2 +- cmd/nerdctl/container_cp_linux.go | 2 +- cmd/nerdctl/container_logs.go | 2 +- cmd/nerdctl/container_rename.go | 2 +- .../container_run_network_linux_test.go | 3 +- cmd/nerdctl/helpers/cobra.go | 18 +++++++++ cmd/nerdctl/helpers/testing.go | 37 +++++++++++++++++++ cmd/nerdctl/image_history.go | 2 +- cmd/nerdctl/image_pull.go | 2 +- cmd/nerdctl/image_push.go | 2 +- cmd/nerdctl/image_tag.go | 2 +- cmd/nerdctl/main.go | 18 --------- cmd/nerdctl/network_create.go | 2 +- cmd/nerdctl/network_create_linux_test.go | 19 +--------- 14 files changed, 68 insertions(+), 45 deletions(-) create mode 100644 cmd/nerdctl/helpers/testing.go diff --git a/cmd/nerdctl/container_commit.go b/cmd/nerdctl/container_commit.go index aa646bcd580..c6ef5e1243f 100644 --- a/cmd/nerdctl/container_commit.go +++ b/cmd/nerdctl/container_commit.go @@ -30,7 +30,7 @@ func newCommitCommand() *cobra.Command { var commitCommand = &cobra.Command{ Use: "commit [flags] CONTAINER REPOSITORY[:TAG]", Short: "Create a new image from a container's changes", - Args: IsExactArgs(2), + Args: helpers.IsExactArgs(2), RunE: commitAction, ValidArgsFunction: commitShellComplete, SilenceUsage: true, diff --git a/cmd/nerdctl/container_cp_linux.go b/cmd/nerdctl/container_cp_linux.go index 184cbc66292..c63d46030b6 100644 --- a/cmd/nerdctl/container_cp_linux.go +++ b/cmd/nerdctl/container_cp_linux.go @@ -44,7 +44,7 @@ Using 'nerdctl cp' with untrusted or malicious containers is unsupported and may nerdctl cp [flags] SRC_PATH|- CONTAINER:DEST_PATH` var cpCommand = &cobra.Command{ Use: usage, - Args: IsExactArgs(2), + Args: helpers.IsExactArgs(2), Short: shortHelp, Long: longHelp, RunE: cpAction, diff --git a/cmd/nerdctl/container_logs.go b/cmd/nerdctl/container_logs.go index 7d633038f48..9a14d942e6d 100644 --- a/cmd/nerdctl/container_logs.go +++ b/cmd/nerdctl/container_logs.go @@ -40,7 +40,7 @@ The following containers are supported: ` var logsCommand = &cobra.Command{ Use: "logs [flags] CONTAINER", - Args: IsExactArgs(1), + Args: helpers.IsExactArgs(1), Short: shortUsage, Long: longUsage, RunE: logsAction, diff --git a/cmd/nerdctl/container_rename.go b/cmd/nerdctl/container_rename.go index fcd724e8852..d70ea215960 100644 --- a/cmd/nerdctl/container_rename.go +++ b/cmd/nerdctl/container_rename.go @@ -29,7 +29,7 @@ import ( func newRenameCommand() *cobra.Command { var renameCommand = &cobra.Command{ Use: "rename [flags] CONTAINER NEW_NAME", - Args: IsExactArgs(2), + Args: helpers.IsExactArgs(2), Short: "rename a container", RunE: renameAction, ValidArgsFunction: renameShellComplete, diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container_run_network_linux_test.go index 2321df8927b..a9420fcfaca 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container_run_network_linux_test.go @@ -31,6 +31,7 @@ import ( "github.com/containerd/errdefs" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" @@ -632,7 +633,7 @@ func TestRunContainerWithStaticIP6(t *testing.T) { return } cmd.AssertOutWithFunc(func(stdout string) error { - ip := findIPv6(stdout) + ip := helpers.FindIPv6(stdout) if !subnet.Contains(ip) { return fmt.Errorf("expected subnet %s include ip %s", subnet, ip) } diff --git a/cmd/nerdctl/helpers/cobra.go b/cmd/nerdctl/helpers/cobra.go index 791c33deb0e..f280517b686 100644 --- a/cmd/nerdctl/helpers/cobra.go +++ b/cmd/nerdctl/helpers/cobra.go @@ -41,3 +41,21 @@ func UnknownSubcommandAction(cmd *cobra.Command, args []string) error { } return errors.New(msg) } + +// IsExactArgs returns an error if there is not the exact number of args +func IsExactArgs(number int) cobra.PositionalArgs { + return func(cmd *cobra.Command, args []string) error { + if len(args) == number { + return nil + } + return fmt.Errorf( + "%q requires exactly %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s", + cmd.CommandPath(), + number, + "argument(s)", + cmd.CommandPath(), + cmd.UseLine(), + cmd.Short, + ) + } +} diff --git a/cmd/nerdctl/helpers/testing.go b/cmd/nerdctl/helpers/testing.go new file mode 100644 index 00000000000..b0e6fdf442e --- /dev/null +++ b/cmd/nerdctl/helpers/testing.go @@ -0,0 +1,37 @@ +/* + 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 helpers + +import ( + "net" + "strings" +) + +func FindIPv6(output string) net.IP { + var ipv6 string + lines := strings.Split(output, "\n") + for _, line := range lines { + if strings.Contains(line, "inet6") { + fields := strings.Fields(line) + if len(fields) > 1 { + ipv6 = strings.Split(fields[1], "/")[0] + break + } + } + } + return net.ParseIP(ipv6) +} diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image_history.go index d0633e2ed01..d3d7a6a3c44 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image_history.go @@ -47,7 +47,7 @@ func newHistoryCommand() *cobra.Command { var historyCommand = &cobra.Command{ Use: "history [flags] IMAGE", Short: "Show the history of an image", - Args: IsExactArgs(1), + Args: helpers.IsExactArgs(1), RunE: historyAction, ValidArgsFunction: historyShellComplete, SilenceUsage: true, diff --git a/cmd/nerdctl/image_pull.go b/cmd/nerdctl/image_pull.go index b7e75938649..fdfb2420c6c 100644 --- a/cmd/nerdctl/image_pull.go +++ b/cmd/nerdctl/image_pull.go @@ -32,7 +32,7 @@ func newPullCommand() *cobra.Command { var pullCommand = &cobra.Command{ Use: "pull [flags] NAME[:TAG]", Short: "Pull an image from a registry. Optionally specify \"ipfs://\" or \"ipns://\" scheme to pull image from IPFS.", - Args: IsExactArgs(1), + Args: helpers.IsExactArgs(1), RunE: pullAction, SilenceUsage: true, SilenceErrors: true, diff --git a/cmd/nerdctl/image_push.go b/cmd/nerdctl/image_push.go index 37fee9d3937..147e8dfa063 100644 --- a/cmd/nerdctl/image_push.go +++ b/cmd/nerdctl/image_push.go @@ -34,7 +34,7 @@ func newPushCommand() *cobra.Command { var pushCommand = &cobra.Command{ Use: "push [flags] NAME[:TAG]", Short: "Push an image or a repository to a registry. Optionally specify \"ipfs://\" or \"ipns://\" scheme to push image to IPFS.", - Args: IsExactArgs(1), + Args: helpers.IsExactArgs(1), RunE: pushAction, ValidArgsFunction: pushShellComplete, SilenceUsage: true, diff --git a/cmd/nerdctl/image_tag.go b/cmd/nerdctl/image_tag.go index 7daef37cc9a..9989665d12d 100644 --- a/cmd/nerdctl/image_tag.go +++ b/cmd/nerdctl/image_tag.go @@ -30,7 +30,7 @@ func newTagCommand() *cobra.Command { var tagCommand = &cobra.Command{ Use: "tag [flags] SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]", Short: "Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE", - Args: IsExactArgs(2), + Args: helpers.IsExactArgs(2), RunE: tagAction, ValidArgsFunction: tagShellComplete, SilenceUsage: true, diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index a8d4bba0aa2..85b67d8b842 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -554,21 +554,3 @@ func checkExperimental(feature string) func(cmd *cobra.Command, args []string) e return nil } } - -// IsExactArgs returns an error if there is not the exact number of args -func IsExactArgs(number int) cobra.PositionalArgs { - return func(cmd *cobra.Command, args []string) error { - if len(args) == number { - return nil - } - return fmt.Errorf( - "%q requires exactly %d %s.\nSee '%s --help'.\n\nUsage: %s\n\n%s", - cmd.CommandPath(), - number, - "argument(s)", - cmd.CommandPath(), - cmd.UseLine(), - cmd.Short, - ) - } -} diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network_create.go index 220c0da64d9..c38e555d757 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network_create.go @@ -34,7 +34,7 @@ func newNetworkCreateCommand() *cobra.Command { Use: "create [flags] NETWORK", Short: "Create a network", Long: `NOTE: To isolate CNI bridge, CNI plugin "firewall" (>= v1.1.0) is needed.`, - Args: IsExactArgs(1), + Args: helpers.IsExactArgs(1), RunE: networkCreateAction, SilenceUsage: true, SilenceErrors: true, diff --git a/cmd/nerdctl/network_create_linux_test.go b/cmd/nerdctl/network_create_linux_test.go index 0ff4cc9b4c8..1fb3b3f4fcd 100644 --- a/cmd/nerdctl/network_create_linux_test.go +++ b/cmd/nerdctl/network_create_linux_test.go @@ -19,11 +19,11 @@ package main import ( "fmt" "net" - "strings" "testing" "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -73,25 +73,10 @@ func TestNetworkCreateIPv6(t *testing.T) { }) base.Cmd("run", "--rm", "--net", testNetwork, testutil.CommonImage, "ip", "addr", "show", "dev", "eth0").AssertOutWithFunc(func(stdout string) error { - ip := findIPv6(stdout) + ip := helpers.FindIPv6(stdout) if subnet.Contains(ip) { return nil } return fmt.Errorf("expected subnet %s include ip %s", subnet, ip) }) } - -func findIPv6(output string) net.IP { - var ipv6 string - lines := strings.Split(output, "\n") - for _, line := range lines { - if strings.Contains(line, "inet6") { - fields := strings.Fields(line) - if len(fields) > 1 { - ipv6 = strings.Split(fields[1], "/")[0] - break - } - } - } - return net.ParseIP(ipv6) -} From d1bc54d92bc3df6f61d4840e4ad3e52d60577a0c Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 09:17:23 -0700 Subject: [PATCH 0722/1066] Move network to cmd/nerdctl/network Signed-off-by: apostasie --- cmd/nerdctl/main.go | 3 ++- cmd/nerdctl/{ => network}/network.go | 4 +-- cmd/nerdctl/{ => network}/network_create.go | 2 +- .../network_create_linux_test.go | 2 +- .../{ => network}/network_create_unix.go | 2 +- .../{ => network}/network_create_windows.go | 2 +- cmd/nerdctl/{ => network}/network_inspect.go | 2 +- .../{ => network}/network_inspect_test.go | 2 +- cmd/nerdctl/{ => network}/network_list.go | 2 +- .../{ => network}/network_list_linux_test.go | 2 +- cmd/nerdctl/{ => network}/network_prune.go | 6 ++--- .../{ => network}/network_prune_linux_test.go | 2 +- cmd/nerdctl/{ => network}/network_remove.go | 2 +- .../network_remove_linux_test.go | 2 +- cmd/nerdctl/network/network_test.go | 27 +++++++++++++++++++ cmd/nerdctl/system_prune.go | 3 ++- 16 files changed, 47 insertions(+), 18 deletions(-) rename cmd/nerdctl/{ => network}/network.go (95%) rename cmd/nerdctl/{ => network}/network_create.go (99%) rename cmd/nerdctl/{ => network}/network_create_linux_test.go (99%) rename cmd/nerdctl/{ => network}/network_create_unix.go (97%) rename cmd/nerdctl/{ => network}/network_create_windows.go (97%) rename cmd/nerdctl/{ => network}/network_inspect.go (99%) rename cmd/nerdctl/{ => network}/network_inspect_test.go (99%) rename cmd/nerdctl/{ => network}/network_list.go (99%) rename cmd/nerdctl/{ => network}/network_list_linux_test.go (99%) rename cmd/nerdctl/{ => network}/network_prune.go (94%) rename cmd/nerdctl/{ => network}/network_prune_linux_test.go (98%) rename cmd/nerdctl/{ => network}/network_remove.go (99%) rename cmd/nerdctl/{ => network}/network_remove_linux_test.go (99%) create mode 100644 cmd/nerdctl/network/network_test.go diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 85b67d8b842..0da60f83fdb 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -34,6 +34,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/network" "github.com/containerd/nerdctl/v2/cmd/nerdctl/volume" "github.com/containerd/nerdctl/v2/pkg/config" ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" @@ -292,7 +293,7 @@ Config file ($NERDCTL_TOML): %s // #region helpers.Management newContainerCommand(), newImageCommand(), - newNetworkCommand(), + network.NewNetworkCommand(), volume.NewVolumeCommand(), newSystemCommand(), newNamespaceCommand(), diff --git a/cmd/nerdctl/network.go b/cmd/nerdctl/network/network.go similarity index 95% rename from cmd/nerdctl/network.go rename to cmd/nerdctl/network/network.go index b957b61a8eb..b953135cd0e 100644 --- a/cmd/nerdctl/network.go +++ b/cmd/nerdctl/network/network.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "github.com/spf13/cobra" @@ -22,7 +22,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) -func newNetworkCommand() *cobra.Command { +func NewNetworkCommand() *cobra.Command { networkCommand := &cobra.Command{ Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "network", diff --git a/cmd/nerdctl/network_create.go b/cmd/nerdctl/network/network_create.go similarity index 99% rename from cmd/nerdctl/network_create.go rename to cmd/nerdctl/network/network_create.go index c38e555d757..1b996d27f4d 100644 --- a/cmd/nerdctl/network_create.go +++ b/cmd/nerdctl/network/network_create.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "fmt" diff --git a/cmd/nerdctl/network_create_linux_test.go b/cmd/nerdctl/network/network_create_linux_test.go similarity index 99% rename from cmd/nerdctl/network_create_linux_test.go rename to cmd/nerdctl/network/network_create_linux_test.go index 1fb3b3f4fcd..adf61d67c11 100644 --- a/cmd/nerdctl/network_create_linux_test.go +++ b/cmd/nerdctl/network/network_create_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "fmt" diff --git a/cmd/nerdctl/network_create_unix.go b/cmd/nerdctl/network/network_create_unix.go similarity index 97% rename from cmd/nerdctl/network_create_unix.go rename to cmd/nerdctl/network/network_create_unix.go index a04b6fb790a..dbfb8a9781c 100644 --- a/cmd/nerdctl/network_create_unix.go +++ b/cmd/nerdctl/network/network_create_unix.go @@ -16,6 +16,6 @@ limitations under the License. */ -package main +package network const DefaultNetworkDriver = "bridge" diff --git a/cmd/nerdctl/network_create_windows.go b/cmd/nerdctl/network/network_create_windows.go similarity index 97% rename from cmd/nerdctl/network_create_windows.go rename to cmd/nerdctl/network/network_create_windows.go index 9c11f3c3e81..1be4a08f4e4 100644 --- a/cmd/nerdctl/network_create_windows.go +++ b/cmd/nerdctl/network/network_create_windows.go @@ -14,6 +14,6 @@ limitations under the License. */ -package main +package network const DefaultNetworkDriver = "nat" diff --git a/cmd/nerdctl/network_inspect.go b/cmd/nerdctl/network/network_inspect.go similarity index 99% rename from cmd/nerdctl/network_inspect.go rename to cmd/nerdctl/network/network_inspect.go index f025922e445..6a0c0a6bc53 100644 --- a/cmd/nerdctl/network_inspect.go +++ b/cmd/nerdctl/network/network_inspect.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/network_inspect_test.go b/cmd/nerdctl/network/network_inspect_test.go similarity index 99% rename from cmd/nerdctl/network_inspect_test.go rename to cmd/nerdctl/network/network_inspect_test.go index aa47a33ce4f..1f91f09963e 100644 --- a/cmd/nerdctl/network_inspect_test.go +++ b/cmd/nerdctl/network/network_inspect_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "runtime" diff --git a/cmd/nerdctl/network_list.go b/cmd/nerdctl/network/network_list.go similarity index 99% rename from cmd/nerdctl/network_list.go rename to cmd/nerdctl/network/network_list.go index 8cc8ecde0c8..22a10a239cd 100644 --- a/cmd/nerdctl/network_list.go +++ b/cmd/nerdctl/network/network_list.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/network_list_linux_test.go b/cmd/nerdctl/network/network_list_linux_test.go similarity index 99% rename from cmd/nerdctl/network_list_linux_test.go rename to cmd/nerdctl/network/network_list_linux_test.go index adf5cd71efa..62927f04b3f 100644 --- a/cmd/nerdctl/network_list_linux_test.go +++ b/cmd/nerdctl/network/network_list_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "errors" diff --git a/cmd/nerdctl/network_prune.go b/cmd/nerdctl/network/network_prune.go similarity index 94% rename from cmd/nerdctl/network_prune.go rename to cmd/nerdctl/network/network_prune.go index 3c68263c0ef..f9114fe6bbe 100644 --- a/cmd/nerdctl/network_prune.go +++ b/cmd/nerdctl/network/network_prune.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "fmt" @@ -28,7 +28,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/network" ) -var networkDriversToKeep = []string{"host", "none", DefaultNetworkDriver} +var NetworkDriversToKeep = []string{"host", "none", DefaultNetworkDriver} func newNetworkPruneCommand() *cobra.Command { networkPruneCommand := &cobra.Command{ @@ -67,7 +67,7 @@ func networkPruneAction(cmd *cobra.Command, _ []string) error { } options := types.NetworkPruneOptions{ GOptions: globalOptions, - NetworkDriversToKeep: networkDriversToKeep, + NetworkDriversToKeep: NetworkDriversToKeep, Stdout: cmd.OutOrStdout(), } diff --git a/cmd/nerdctl/network_prune_linux_test.go b/cmd/nerdctl/network/network_prune_linux_test.go similarity index 98% rename from cmd/nerdctl/network_prune_linux_test.go rename to cmd/nerdctl/network/network_prune_linux_test.go index ae1b92d41a0..cb137c4c68f 100644 --- a/cmd/nerdctl/network_prune_linux_test.go +++ b/cmd/nerdctl/network/network_prune_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "testing" diff --git a/cmd/nerdctl/network_remove.go b/cmd/nerdctl/network/network_remove.go similarity index 99% rename from cmd/nerdctl/network_remove.go rename to cmd/nerdctl/network/network_remove.go index e40f53a4b4f..907908979bc 100644 --- a/cmd/nerdctl/network_remove.go +++ b/cmd/nerdctl/network/network_remove.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/network_remove_linux_test.go b/cmd/nerdctl/network/network_remove_linux_test.go similarity index 99% rename from cmd/nerdctl/network_remove_linux_test.go rename to cmd/nerdctl/network/network_remove_linux_test.go index eed01050c36..7b8acb7b4b8 100644 --- a/cmd/nerdctl/network_remove_linux_test.go +++ b/cmd/nerdctl/network/network_remove_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package network import ( "testing" diff --git a/cmd/nerdctl/network/network_test.go b/cmd/nerdctl/network/network_test.go new file mode 100644 index 00000000000..245f26e3b09 --- /dev/null +++ b/cmd/nerdctl/network/network_test.go @@ -0,0 +1,27 @@ +/* + 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 network + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/system_prune.go b/cmd/nerdctl/system_prune.go index e8e384cf5fb..2f446572618 100644 --- a/cmd/nerdctl/system_prune.go +++ b/cmd/nerdctl/system_prune.go @@ -25,6 +25,7 @@ import ( "github.com/containerd/log" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/network" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/system" @@ -74,7 +75,7 @@ func processSystemPruneOptions(cmd *cobra.Command) (types.SystemPruneOptions, er All: all, Volumes: vFlag, BuildKitHost: buildkitHost, - NetworkDriversToKeep: networkDriversToKeep, + NetworkDriversToKeep: network.NetworkDriversToKeep, }, nil } From 9c75f29dcb6deab6326874760e840fdee314080e Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 09:22:20 -0700 Subject: [PATCH 0723/1066] Move namespace code to subpackage Signed-off-by: apostasie --- cmd/nerdctl/main.go | 3 ++- cmd/nerdctl/{ => namespace}/namespace.go | 4 +-- .../{ => namespace}/namespace_create.go | 2 +- .../{ => namespace}/namespace_inspect.go | 2 +- .../{ => namespace}/namespace_remove.go | 2 +- cmd/nerdctl/namespace/namespace_test.go | 27 +++++++++++++++++++ .../{ => namespace}/namespace_update.go | 2 +- 7 files changed, 35 insertions(+), 7 deletions(-) rename cmd/nerdctl/{ => namespace}/namespace.go (98%) rename cmd/nerdctl/{ => namespace}/namespace_create.go (99%) rename cmd/nerdctl/{ => namespace}/namespace_inspect.go (99%) rename cmd/nerdctl/{ => namespace}/namespace_remove.go (99%) create mode 100644 cmd/nerdctl/namespace/namespace_test.go rename cmd/nerdctl/{ => namespace}/namespace_update.go (99%) diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 0da60f83fdb..aa91738cc2a 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -34,6 +34,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/namespace" "github.com/containerd/nerdctl/v2/cmd/nerdctl/network" "github.com/containerd/nerdctl/v2/cmd/nerdctl/volume" "github.com/containerd/nerdctl/v2/pkg/config" @@ -296,7 +297,7 @@ Config file ($NERDCTL_TOML): %s network.NewNetworkCommand(), volume.NewVolumeCommand(), newSystemCommand(), - newNamespaceCommand(), + namespace.NewNamespaceCommand(), newBuilderCommand(), // #endregion diff --git a/cmd/nerdctl/namespace.go b/cmd/nerdctl/namespace/namespace.go similarity index 98% rename from cmd/nerdctl/namespace.go rename to cmd/nerdctl/namespace/namespace.go index 59b2858aa43..f83cc956862 100644 --- a/cmd/nerdctl/namespace.go +++ b/cmd/nerdctl/namespace/namespace.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package namespace import ( "fmt" @@ -33,7 +33,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" ) -func newNamespaceCommand() *cobra.Command { +func NewNamespaceCommand() *cobra.Command { namespaceCommand := &cobra.Command{ Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "namespace", diff --git a/cmd/nerdctl/namespace_create.go b/cmd/nerdctl/namespace/namespace_create.go similarity index 99% rename from cmd/nerdctl/namespace_create.go rename to cmd/nerdctl/namespace/namespace_create.go index 61700c56d19..4c6e51312fb 100644 --- a/cmd/nerdctl/namespace_create.go +++ b/cmd/nerdctl/namespace/namespace_create.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package namespace import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/namespace_inspect.go b/cmd/nerdctl/namespace/namespace_inspect.go similarity index 99% rename from cmd/nerdctl/namespace_inspect.go rename to cmd/nerdctl/namespace/namespace_inspect.go index 580ed4689e9..cd3a5ff98e0 100644 --- a/cmd/nerdctl/namespace_inspect.go +++ b/cmd/nerdctl/namespace/namespace_inspect.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package namespace import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/namespace_remove.go b/cmd/nerdctl/namespace/namespace_remove.go similarity index 99% rename from cmd/nerdctl/namespace_remove.go rename to cmd/nerdctl/namespace/namespace_remove.go index 6ba48fe7200..b665736b1d8 100644 --- a/cmd/nerdctl/namespace_remove.go +++ b/cmd/nerdctl/namespace/namespace_remove.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package namespace import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/namespace/namespace_test.go b/cmd/nerdctl/namespace/namespace_test.go new file mode 100644 index 00000000000..bad2c633371 --- /dev/null +++ b/cmd/nerdctl/namespace/namespace_test.go @@ -0,0 +1,27 @@ +/* + 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 namespace + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/namespace_update.go b/cmd/nerdctl/namespace/namespace_update.go similarity index 99% rename from cmd/nerdctl/namespace_update.go rename to cmd/nerdctl/namespace/namespace_update.go index 6debd47cae4..b390dc26792 100644 --- a/cmd/nerdctl/namespace_update.go +++ b/cmd/nerdctl/namespace/namespace_update.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package namespace import ( "github.com/spf13/cobra" From 3b8a098d5b921250b5e5b5861a4c7e96a8613879 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 09:37:45 -0700 Subject: [PATCH 0724/1066] Move login/logout to subpackage Signed-off-by: apostasie --- cmd/nerdctl/{ => login}/login.go | 4 +-- cmd/nerdctl/{ => login}/login_linux_test.go | 2 +- cmd/nerdctl/login/login_test.go | 27 +++++++++++++++++++++ cmd/nerdctl/{ => login}/logout.go | 4 +-- cmd/nerdctl/main.go | 5 ++-- 5 files changed, 35 insertions(+), 7 deletions(-) rename cmd/nerdctl/{ => login}/login.go (98%) rename cmd/nerdctl/{ => login}/login_linux_test.go (99%) create mode 100644 cmd/nerdctl/login/login_test.go rename cmd/nerdctl/{ => login}/logout.go (98%) diff --git a/cmd/nerdctl/login.go b/cmd/nerdctl/login/login.go similarity index 98% rename from cmd/nerdctl/login.go rename to cmd/nerdctl/login/login.go index 047b712d529..64dc5f4b265 100644 --- a/cmd/nerdctl/login.go +++ b/cmd/nerdctl/login/login.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package login import ( "errors" @@ -30,7 +30,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/login" ) -func newLoginCommand() *cobra.Command { +func NewLoginCommand() *cobra.Command { var loginCommand = &cobra.Command{ Use: "login [flags] [SERVER]", Args: cobra.MaximumNArgs(1), diff --git a/cmd/nerdctl/login_linux_test.go b/cmd/nerdctl/login/login_linux_test.go similarity index 99% rename from cmd/nerdctl/login_linux_test.go rename to cmd/nerdctl/login/login_linux_test.go index 395792c32fb..ef65e9868fd 100644 --- a/cmd/nerdctl/login_linux_test.go +++ b/cmd/nerdctl/login/login_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package login import ( "crypto/rand" diff --git a/cmd/nerdctl/login/login_test.go b/cmd/nerdctl/login/login_test.go new file mode 100644 index 00000000000..ca5ad784c9b --- /dev/null +++ b/cmd/nerdctl/login/login_test.go @@ -0,0 +1,27 @@ +/* + 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 login + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/logout.go b/cmd/nerdctl/login/logout.go similarity index 98% rename from cmd/nerdctl/logout.go rename to cmd/nerdctl/login/logout.go index 4c7d10c07b8..17019c6a485 100644 --- a/cmd/nerdctl/logout.go +++ b/cmd/nerdctl/login/logout.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package login import ( "fmt" @@ -25,7 +25,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" ) -func newLogoutCommand() *cobra.Command { +func NewLogoutCommand() *cobra.Command { var logoutCommand = &cobra.Command{ Use: "logout [flags] [SERVER]", Args: cobra.MaximumNArgs(1), diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index aa91738cc2a..d6aa9377560 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -34,6 +34,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/login" "github.com/containerd/nerdctl/v2/cmd/nerdctl/namespace" "github.com/containerd/nerdctl/v2/cmd/nerdctl/network" "github.com/containerd/nerdctl/v2/cmd/nerdctl/volume" @@ -305,10 +306,10 @@ Config file ($NERDCTL_TOML): %s newInternalCommand(), // login - newLoginCommand(), + login.NewLoginCommand(), // Logout - newLogoutCommand(), + login.NewLogoutCommand(), // Compose newComposeCommand(), From c8df501eb2040ba335b1771037c266a03a23b648 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 09:52:59 -0700 Subject: [PATCH 0725/1066] Move a bunch of helpers AddIntFlag AddDurationFlag AddStringFlag checkExperimental createBuildContext testComposeUp requiresStargz newJWEKeyPair rmiAll Signed-off-by: apostasie --- cmd/nerdctl/builder.go | 4 +- cmd/nerdctl/builder_build.go | 2 +- cmd/nerdctl/builder_build_linux_test.go | 5 +- cmd/nerdctl/builder_build_test.go | 42 +++---- cmd/nerdctl/builder_linux_test.go | 7 +- cmd/nerdctl/compose_up_linux_test.go | 56 +--------- cmd/nerdctl/container_run_mount_linux_test.go | 11 +- .../container_run_stargz_linux_test.go | 13 +-- cmd/nerdctl/container_run_test.go | 5 +- .../container_run_verify_linux_test.go | 3 +- cmd/nerdctl/helpers/cobra.go | 79 +++++++++++++ cmd/nerdctl/helpers/flagutil.go | 15 +++ cmd/nerdctl/helpers/testing.go | 104 ++++++++++++++++++ cmd/nerdctl/helpers/testing_linux.go | 79 +++++++++++++ cmd/nerdctl/image_encrypt_linux_test.go | 97 ++-------------- cmd/nerdctl/image_list_test.go | 5 +- cmd/nerdctl/image_prune_test.go | 9 +- cmd/nerdctl/image_pull_linux_test.go | 7 +- cmd/nerdctl/ipfs_build_linux_test.go | 3 +- cmd/nerdctl/ipfs_compose_linux_test.go | 5 +- cmd/nerdctl/ipfs_linux_test.go | 21 ++-- cmd/nerdctl/ipfs_registry.go | 2 +- cmd/nerdctl/ipfs_registry_linux_test.go | 3 +- cmd/nerdctl/ipfs_registry_serve.go | 9 +- cmd/nerdctl/main.go | 88 --------------- cmd/nerdctl/multi_platform_linux_test.go | 5 +- 26 files changed, 367 insertions(+), 312 deletions(-) create mode 100644 cmd/nerdctl/helpers/testing_linux.go diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder.go index 6bfb99e456a..af3eadce09d 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder.go @@ -58,7 +58,7 @@ func newBuilderPruneCommand() *cobra.Command { SilenceErrors: true, } - AddStringFlag(buildPruneCommand, "buildkit-host", nil, "", "BUILDKIT_HOST", "BuildKit address") + helpers.AddStringFlag(buildPruneCommand, "buildkit-host", nil, "", "BUILDKIT_HOST", "BuildKit address") buildPruneCommand.Flags().BoolP("all", "a", false, "Remove all unused build cache, not just dangling ones") buildPruneCommand.Flags().BoolP("force", "f", false, "Do not prompt for confirmation") @@ -136,7 +136,7 @@ func newBuilderDebugCommand() *cobra.Command { var buildDebugCommand = &cobra.Command{ Use: "debug", Short: shortHelp, - PreRunE: checkExperimental("`nerdctl builder debug`"), + PreRunE: helpers.CheckExperimental("`nerdctl builder debug`"), RunE: builderDebugAction, SilenceUsage: true, SilenceErrors: true, diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder_build.go index 50810a8d0fe..6881e2ec169 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder_build.go @@ -44,7 +44,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container SilenceUsage: true, SilenceErrors: true, } - AddStringFlag(buildCommand, "buildkit-host", nil, "", "BUILDKIT_HOST", "BuildKit address") + helpers.AddStringFlag(buildCommand, "buildkit-host", nil, "", "BUILDKIT_HOST", "BuildKit address") buildCommand.Flags().StringArrayP("tag", "t", nil, "Name and optionally a tag in the 'name:tag' format") buildCommand.Flags().StringP("file", "f", "", "Name of the Dockerfile") buildCommand.Flags().String("target", "", "Set the target build stage to build") diff --git a/cmd/nerdctl/builder_build_linux_test.go b/cmd/nerdctl/builder_build_linux_test.go index 3e3fc7334ee..63ca1b6c014 100644 --- a/cmd/nerdctl/builder_build_linux_test.go +++ b/cmd/nerdctl/builder_build_linux_test.go @@ -22,6 +22,7 @@ import ( "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -51,7 +52,7 @@ func TestBuildContextWithOCILayout(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s LABEL layer=oci-layout-parent CMD ["echo", "test-nerdctl-build-context-oci-layout-parent"]`, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) tarPath := fmt.Sprintf("%s/%s.tar", buildCtx, ociLayout) @@ -66,7 +67,7 @@ CMD ["echo", "test-nerdctl-build-context-oci-layout-parent"]`, testutil.CommonIm dockerfile = fmt.Sprintf(`FROM %s CMD ["echo", "test-nerdctl-build-context-oci-layout"]`, ociLayout) - buildCtx = createBuildContext(t, dockerfile) + buildCtx = helpers.CreateBuildContext(t, dockerfile) var buildArgs = []string{} if testutil.IsDocker() { diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder_build_test.go index 774bf02d5b2..82dd9cfa438 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder_build_test.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -41,7 +42,7 @@ func TestBuild(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("build", buildCtx, "-t", imageName).AssertOK() @@ -66,7 +67,7 @@ func TestBuildIsShareableForCompatiblePlatform(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", buildCtx, "-t", imageName).AssertErrNotContains("tarball") @@ -99,7 +100,7 @@ RUN echo hello > /hello CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("build", buildCtx, "-t", imageName).AssertOK() @@ -109,7 +110,7 @@ RUN echo hello2 > /hello2 CMD ["cat", "/hello2"] `, imageName) - buildCtx2 := createBuildContext(t, dockerfile2) + buildCtx2 := helpers.CreateBuildContext(t, dockerfile2) base.Cmd("build", "-t", imageName2, buildCtx2).AssertOK() base.Cmd("build", buildCtx2, "-t", imageName2).AssertOK() @@ -142,7 +143,7 @@ RUN echo hello2 > /hello2 CMD ["cat", "/hello2"] `, imageName) - buildCtx2 := createBuildContext(t, dockerfile2) + buildCtx2 := helpers.CreateBuildContext(t, dockerfile2) base.Cmd("build", "-t", imageName2, buildCtx2).AssertOK() base.Cmd("build", buildCtx2, "-t", imageName2).AssertOK() @@ -208,7 +209,7 @@ func TestBuildLocal(t *testing.T) { COPY %s /`, testFileName) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) if err := os.WriteFile(filepath.Join(buildCtx, testFileName), []byte(testContent), 0644); err != nil { t.Fatal(err) @@ -234,13 +235,6 @@ COPY %s /`, assert.Equal(t, string(data), testContent) } -func createBuildContext(t *testing.T, dockerfile string) string { - tmpDir := t.TempDir() - err := os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644) - assert.NilError(t, err) - return tmpDir -} - func TestBuildWithBuildArg(t *testing.T) { testutil.RequiresBuild(t) testutil.RegisterBuildCacheCleanup(t) @@ -254,7 +248,7 @@ ENV TEST_STRING=$TEST_STRING CMD echo $TEST_STRING `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", buildCtx, "-t", imageName).AssertOK() base.Cmd("run", "--rm", imageName).AssertOutExactly("1\n") @@ -297,7 +291,7 @@ func TestBuildWithIIDFile(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) fileName := filepath.Join(t.TempDir(), "id.txt") base.Cmd("build", "-t", imageName, buildCtx, "--iidfile", fileName).AssertOK() @@ -320,7 +314,7 @@ func TestBuildWithLabels(t *testing.T) { LABEL name=nerdctl-build-test-label `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx, "--label", "label=test").AssertOK() defer base.Cmd("rmi", imageName).Run() @@ -343,7 +337,7 @@ func TestBuildMultipleTags(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "%s"] `, testutil.CommonImage, output) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", img, buildCtx).AssertOK() base.Cmd("build", buildCtx, "-t", img, "-t", imgWithNoTag, "-t", imgWithCustomTag).AssertOK() @@ -396,7 +390,7 @@ CMD ["echo", "dockerfile"] err = os.WriteFile(filepath.Join(tmpDir, "Containerfile"), []byte(containerfile), 0644) assert.NilError(t, err) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("run", "--rm", imageName).AssertOutExactly("dockerfile\n") @@ -411,7 +405,7 @@ func TestBuildNoTag(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-notag-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", buildCtx).AssertOK() base.Cmd("images").AssertOutContains("") @@ -426,7 +420,7 @@ func TestBuildContextDockerImageAlias(t *testing.T) { dockerfile := `FROM myorg/myapp CMD ["echo", "nerdctl-build-myorg/myapp"]` - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", buildCtx, fmt.Sprintf("--build-context=myorg/myapp=docker-image://%s", testutil.CommonImage)).AssertOK() base.Cmd("images").AssertOutContains("") @@ -451,7 +445,7 @@ func TestBuildContextWithCopyFromDir(t *testing.T) { COPY --from=dir2 /%s /hello_from_dir2.txt RUN ["cat", "/hello_from_dir2.txt"]`, testutil.CommonImage, filename) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", buildCtx, fmt.Sprintf("--build-context=dir2=%s", dir2)).AssertOK() base.Cmd("images").AssertOutContains("") @@ -472,7 +466,7 @@ RUN echo $SOURCE_DATE_EPOCH >/source-date-epoch CMD ["cat", "/source-date-epoch"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) const sourceDateEpochEnvStr = "1111111111" base.Env = append(base.Env, "SOURCE_DATE_EPOCH="+sourceDateEpochEnvStr) @@ -493,7 +487,7 @@ func TestBuildNetwork(t *testing.T) { RUN apk add --no-cache curl RUN curl -I http://google.com `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) validCases := []struct { name string @@ -549,7 +543,7 @@ func TestBuildAttestation(t *testing.T) { } dockerfile := "FROM " + testutil.NginxAlpineImage - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) // Test sbom outputSBOMDir := t.TempDir() diff --git a/cmd/nerdctl/builder_linux_test.go b/cmd/nerdctl/builder_linux_test.go index cc70bd640de..4aa0e212e08 100644 --- a/cmd/nerdctl/builder_linux_test.go +++ b/cmd/nerdctl/builder_linux_test.go @@ -26,6 +26,7 @@ import ( "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -39,7 +40,7 @@ func TestBuilderPrune(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-builder-prune"]`, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) testCases := []struct { name string @@ -71,7 +72,7 @@ func TestBuilderDebug(t *testing.T) { CMD ["echo", "nerdctl-builder-debug-test-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("builder", "debug", buildCtx).CmdOption(testutil.WithStdin(bytes.NewReader([]byte("c\n")))).AssertOK() } @@ -132,7 +133,7 @@ namespace = "%s"`, testutil.Namespace) err := os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644) assert.NilError(t, err) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) buildCmd := []string{"build", buildCtx} switch tc.pull { diff --git a/cmd/nerdctl/compose_up_linux_test.go b/cmd/nerdctl/compose_up_linux_test.go index cbcdbb7e43b..d17df207462 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/cmd/nerdctl/compose_up_linux_test.go @@ -29,6 +29,7 @@ import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" @@ -37,7 +38,7 @@ import ( func TestComposeUp(t *testing.T) { base := testutil.NewBase(t) - testComposeUp(t, base, fmt.Sprintf(` + helpers.ComposeUp(t, base, fmt.Sprintf(` version: '3.1' services: @@ -72,57 +73,6 @@ volumes: `, testutil.WordpressImage, testutil.MariaDBImage)) } -func testComposeUp(t *testing.T, base *testutil.Base, dockerComposeYAML string, opts ...string) { - comp := testutil.NewComposeDir(t, dockerComposeYAML) - defer comp.CleanUp() - - projectName := comp.ProjectName() - t.Logf("projectName=%q", projectName) - - base.ComposeCmd(append(append([]string{"-f", comp.YAMLFullPath()}, opts...), "up", "-d")...).AssertOK() - defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() - base.Cmd("volume", "inspect", fmt.Sprintf("%s_db", projectName)).AssertOK() - base.Cmd("network", "inspect", fmt.Sprintf("%s_default", projectName)).AssertOK() - - checkWordpress := func() error { - resp, err := nettestutil.HTTPGet("http://127.0.0.1:8080", 10, false) - if err != nil { - return err - } - respBody, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - if !strings.Contains(string(respBody), testutil.WordpressIndexHTMLSnippet) { - t.Logf("respBody=%q", respBody) - return fmt.Errorf("respBody does not contain %q", testutil.WordpressIndexHTMLSnippet) - } - return nil - } - - var wordpressWorking bool - for i := 0; i < 30; i++ { - t.Logf("(retry %d)", i) - err := checkWordpress() - if err == nil { - wordpressWorking = true - break - } - // NOTE: "

Error establishing a database connection

" is expected for the first few iterations - t.Log(err) - time.Sleep(3 * time.Second) - } - - if !wordpressWorking { - t.Fatal("wordpress is not working") - } - t.Log("wordpress seems functional") - - base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").AssertOK() - base.Cmd("volume", "inspect", fmt.Sprintf("%s_db", projectName)).AssertFail() - base.Cmd("network", "inspect", fmt.Sprintf("%s_default", projectName)).AssertFail() -} - func TestComposeUpBuild(t *testing.T) { testutil.RequiresBuild(t) testutil.RegisterBuildCacheCleanup(t) @@ -505,7 +455,7 @@ func TestComposeUpWithBypass4netns(t *testing.T) { testutil.RequireKernelVersion(t, ">= 5.9.0-0") testutil.RequireSystemService(t, "bypass4netnsd") base := testutil.NewBase(t) - testComposeUp(t, base, fmt.Sprintf(` + helpers.ComposeUp(t, base, fmt.Sprintf(` version: '3.1' services: diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container_run_mount_linux_test.go index 04dc4440ddb..ab382c7cf5f 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container_run_mount_linux_test.go @@ -28,6 +28,7 @@ import ( "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -125,7 +126,7 @@ func TestRunAnonymousVolumeWithBuild(t *testing.T) { VOLUME /foo `, testutil.AlpineImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("run", "--rm", "-v", "/foo", testutil.AlpineImage, @@ -147,7 +148,7 @@ RUN mkdir -p /mnt && echo hi > /mnt/initial_file CMD ["cat", "/mnt/initial_file"] `, testutil.AlpineImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() @@ -175,7 +176,7 @@ VOLUME /mnt CMD ["cat", "/mnt/initial_file"] `, testutil.AlpineImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() //AnonymousVolume @@ -208,7 +209,7 @@ CMD ["readlink", "/mnt/passwd"] `, testutil.AlpineImage) const expected = "../../../../../../../../../../../../../../../../../../etc/passwd\n" - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() @@ -235,7 +236,7 @@ func TestRunCopyingUpInitialContentsShouldNotResetTheCopiedContents(t *testing.T RUN echo -n "rev0" > /mnt/file `, testutil.AlpineImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() diff --git a/cmd/nerdctl/container_run_stargz_linux_test.go b/cmd/nerdctl/container_run_stargz_linux_test.go index 469cb641b00..2b8a79ad975 100644 --- a/cmd/nerdctl/container_run_stargz_linux_test.go +++ b/cmd/nerdctl/container_run_stargz_linux_test.go @@ -20,6 +20,7 @@ import ( "runtime" "testing" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -30,17 +31,7 @@ func TestRunStargz(t *testing.T) { } base := testutil.NewBase(t) - requiresStargz(base) + helpers.RequiresStargz(base) // if stargz snapshotter is functional, "/.stargz-snapshotter" appears base.Cmd("--snapshotter=stargz", "run", "--rm", testutil.FedoraESGZImage, "ls", "/.stargz-snapshotter").AssertOK() } - -func requiresStargz(base *testutil.Base) { - info := base.Info() - for _, p := range info.Plugins.Storage { - if p == "stargz" { - return - } - } - base.T.Skip("test requires stargz") -} diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container_run_test.go index 53103317451..d1ece634eed 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container_run_test.go @@ -34,6 +34,7 @@ import ( "gotest.tools/v3/icmd" "gotest.tools/v3/poll" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -50,7 +51,7 @@ ENTRYPOINT ["echo", "foo"] CMD ["echo", "bar"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("run", "--rm", imageName).AssertOutExactly("foo echo bar\n") @@ -440,7 +441,7 @@ FROM scratch COPY --from=builder /go/src/logger/logger / ` - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) tmpDir := t.TempDir() base.Cmd("build", buildCtx, "--output", fmt.Sprintf("type=local,src=/go/src/logger/logger,dest=%s", tmpDir)).AssertOK() defer base.Cmd("image", "rm", "-f", imageName).AssertOK() diff --git a/cmd/nerdctl/container_run_verify_linux_test.go b/cmd/nerdctl/container_run_verify_linux_test.go index 3522f12cfa6..06459f93297 100644 --- a/cmd/nerdctl/container_run_verify_linux_test.go +++ b/cmd/nerdctl/container_run_verify_linux_test.go @@ -20,6 +20,7 @@ import ( "fmt" "testing" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) @@ -47,7 +48,7 @@ func TestRunVerifyCosign(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() diff --git a/cmd/nerdctl/helpers/cobra.go b/cmd/nerdctl/helpers/cobra.go index f280517b686..b41c851bb77 100644 --- a/cmd/nerdctl/helpers/cobra.go +++ b/cmd/nerdctl/helpers/cobra.go @@ -19,8 +19,13 @@ package helpers import ( "errors" "fmt" + "os" + "strconv" + "time" "github.com/spf13/cobra" + + "github.com/containerd/log" ) // UnknownSubcommandAction is needed to let `nerdctl system non-existent-command` fail @@ -59,3 +64,77 @@ func IsExactArgs(number int) cobra.PositionalArgs { ) } } + +// AddStringFlag is similar to cmd.Flags().String but supports aliases and env var +func AddStringFlag(cmd *cobra.Command, name string, aliases []string, value string, env, usage string) { + if env != "" { + usage = fmt.Sprintf("%s [$%s]", usage, env) + } + if envV, ok := os.LookupEnv(env); ok { + value = envV + } + aliasesUsage := fmt.Sprintf("Alias of --%s", name) + p := new(string) + flags := cmd.Flags() + flags.StringVar(p, name, value, usage) + for _, a := range aliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + flags.StringVarP(p, a, a, value, aliasesUsage) + } else { + flags.StringVar(p, a, value, aliasesUsage) + } + } +} + +// AddIntFlag is similar to cmd.Flags().Int but supports aliases and env var +func AddIntFlag(cmd *cobra.Command, name string, aliases []string, value int, env, usage string) { + if env != "" { + usage = fmt.Sprintf("%s [$%s]", usage, env) + } + if envV, ok := os.LookupEnv(env); ok { + v, err := strconv.ParseInt(envV, 10, 64) + if err != nil { + log.L.WithError(err).Warnf("Invalid int value for `%s`", env) + } + value = int(v) + } + aliasesUsage := fmt.Sprintf("Alias of --%s", name) + p := new(int) + flags := cmd.Flags() + flags.IntVar(p, name, value, usage) + for _, a := range aliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + flags.IntVarP(p, a, a, value, aliasesUsage) + } else { + flags.IntVar(p, a, value, aliasesUsage) + } + } +} + +// AddDurationFlag is similar to cmd.Flags().Duration but supports aliases and env var +func AddDurationFlag(cmd *cobra.Command, name string, aliases []string, value time.Duration, env, usage string) { + if env != "" { + usage = fmt.Sprintf("%s [$%s]", usage, env) + } + if envV, ok := os.LookupEnv(env); ok { + var err error + value, err = time.ParseDuration(envV) + if err != nil { + log.L.WithError(err).Warnf("Invalid duration value for `%s`", env) + } + } + aliasesUsage := fmt.Sprintf("Alias of --%s", name) + p := new(time.Duration) + flags := cmd.Flags() + flags.DurationVar(p, name, value, usage) + for _, a := range aliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + flags.DurationVarP(p, a, a, value, aliasesUsage) + } else { + flags.DurationVar(p, a, value, aliasesUsage) + } + } +} diff --git a/cmd/nerdctl/helpers/flagutil.go b/cmd/nerdctl/helpers/flagutil.go index 9ca11d449fd..8e87839b2f9 100644 --- a/cmd/nerdctl/helpers/flagutil.go +++ b/cmd/nerdctl/helpers/flagutil.go @@ -17,6 +17,8 @@ package helpers import ( + "fmt" + "github.com/spf13/cobra" "github.com/containerd/nerdctl/v2/pkg/api/types" @@ -113,3 +115,16 @@ func ProcessRootCmdFlags(cmd *cobra.Command) (types.GlobalCommandOptions, error) HostGatewayIP: hostGatewayIP, }, nil } + +func CheckExperimental(feature string) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + globalOptions, err := ProcessRootCmdFlags(cmd) + if err != nil { + return err + } + if !globalOptions.Experimental { + return fmt.Errorf("%s is experimental feature, you should enable experimental config", feature) + } + return nil + } +} diff --git a/cmd/nerdctl/helpers/testing.go b/cmd/nerdctl/helpers/testing.go index b0e6fdf442e..553f4d996d2 100644 --- a/cmd/nerdctl/helpers/testing.go +++ b/cmd/nerdctl/helpers/testing.go @@ -17,8 +17,21 @@ package helpers import ( + "context" "net" + "os" + "os/exec" + "path/filepath" "strings" + "testing" + + "gotest.tools/v3/assert" + + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func FindIPv6(output string) net.IP { @@ -35,3 +48,94 @@ func FindIPv6(output string) net.IP { } return net.ParseIP(ipv6) } + +func RequiresStargz(base *testutil.Base) { + info := base.Info() + for _, p := range info.Plugins.Storage { + if p == "stargz" { + return + } + } + base.T.Skip("test requires stargz") +} + +type JweKeyPair struct { + Prv string + Pub string + Cleanup func() +} + +func NewJWEKeyPair(t testing.TB) *JweKeyPair { + testutil.RequireExecutable(t, "openssl") + td, err := os.MkdirTemp(t.TempDir(), "jwe-key-pair") + assert.NilError(t, err) + prv := filepath.Join(td, "mykey.pem") + pub := filepath.Join(td, "mypubkey.pem") + cmds := [][]string{ + // Exec openssl commands to ensure that nerdctl is compatible with the output of openssl commands. + // Do NOT refactor this function to use "crypto/rsa" stdlib. + {"openssl", "genrsa", "-out", prv}, + {"openssl", "rsa", "-in", prv, "-pubout", "-out", pub}, + } + for _, f := range cmds { + cmd := exec.Command(f[0], f[1:]...) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) + } + } + return &JweKeyPair{ + Prv: prv, + Pub: pub, + Cleanup: func() { + _ = os.RemoveAll(td) + }, + } +} + +func RmiAll(base *testutil.Base) { + base.T.Logf("Pruning images") + imageIDs := base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() + // remove empty output line at the end + imageIDs = imageIDs[:len(imageIDs)-1] + // use `Run` on purpose (same below) because `rmi all` may fail on individual + // image id that has an expected running container (e.g. a registry) + base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() + + base.T.Logf("Pruning build caches") + if _, err := buildkitutil.GetBuildkitHost(testutil.Namespace); err == nil { + base.Cmd("builder", "prune", "--force").AssertOK() + } + + // For BuildKit >= 0.11, pruning cache isn't enough to remove manifest blobs that are referred by build history blobs + // https://github.com/containerd/nerdctl/pull/1833 + if base.Target == testutil.Nerdctl { + base.T.Logf("Pruning all content blobs") + addr := base.ContainerdAddress() + client, err := containerd.New(addr, containerd.WithDefaultNamespace(testutil.Namespace)) + assert.NilError(base.T, err) + cs := client.ContentStore() + ctx := context.TODO() + wf := func(info content.Info) error { + base.T.Logf("Pruning blob %+v", info) + if err := cs.Delete(ctx, info.Digest); err != nil { + base.T.Log(err) + } + return nil + } + if err := cs.Walk(ctx, wf); err != nil { + base.T.Log(err) + } + + base.T.Logf("Pruning all images (again?)") + imageIDs = base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() + base.T.Logf("pruning following images: %+v", imageIDs) + base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() + } +} + +func CreateBuildContext(t *testing.T, dockerfile string) string { + tmpDir := t.TempDir() + err := os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644) + assert.NilError(t, err) + return tmpDir +} diff --git a/cmd/nerdctl/helpers/testing_linux.go b/cmd/nerdctl/helpers/testing_linux.go new file mode 100644 index 00000000000..d459e9272b5 --- /dev/null +++ b/cmd/nerdctl/helpers/testing_linux.go @@ -0,0 +1,79 @@ +/* + 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 helpers + +import ( + "fmt" + "io" + "strings" + "testing" + "time" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" +) + +func ComposeUp(t *testing.T, base *testutil.Base, dockerComposeYAML string, opts ...string) { + comp := testutil.NewComposeDir(t, dockerComposeYAML) + defer comp.CleanUp() + + projectName := comp.ProjectName() + t.Logf("projectName=%q", projectName) + + base.ComposeCmd(append(append([]string{"-f", comp.YAMLFullPath()}, opts...), "up", "-d")...).AssertOK() + defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() + base.Cmd("volume", "inspect", fmt.Sprintf("%s_db", projectName)).AssertOK() + base.Cmd("network", "inspect", fmt.Sprintf("%s_default", projectName)).AssertOK() + + checkWordpress := func() error { + resp, err := nettestutil.HTTPGet("http://127.0.0.1:8080", 10, false) + if err != nil { + return err + } + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + if !strings.Contains(string(respBody), testutil.WordpressIndexHTMLSnippet) { + t.Logf("respBody=%q", respBody) + return fmt.Errorf("respBody does not contain %q", testutil.WordpressIndexHTMLSnippet) + } + return nil + } + + var wordpressWorking bool + for i := 0; i < 30; i++ { + t.Logf("(retry %d)", i) + err := checkWordpress() + if err == nil { + wordpressWorking = true + break + } + // NOTE: "

Error establishing a database connection

" is expected for the first few iterations + t.Log(err) + time.Sleep(3 * time.Second) + } + + if !wordpressWorking { + t.Fatal("wordpress is not working") + } + t.Log("wordpress seems functional") + + base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").AssertOK() + base.Cmd("volume", "inspect", fmt.Sprintf("%s_db", projectName)).AssertFail() + base.Cmd("network", "inspect", fmt.Sprintf("%s_default", projectName)).AssertFail() +} diff --git a/cmd/nerdctl/image_encrypt_linux_test.go b/cmd/nerdctl/image_encrypt_linux_test.go index e6809d29f5b..1cd71d49af9 100644 --- a/cmd/nerdctl/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image_encrypt_linux_test.go @@ -17,102 +17,19 @@ package main import ( - "context" "fmt" - "os" - "os/exec" - "path/filepath" "testing" - "gotest.tools/v3/assert" - - containerd "github.com/containerd/containerd/v2/client" - "github.com/containerd/containerd/v2/core/content" - - "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) -type jweKeyPair struct { - prv string - pub string - cleanup func() -} - -func newJWEKeyPair(t testing.TB) *jweKeyPair { - testutil.RequireExecutable(t, "openssl") - td, err := os.MkdirTemp(t.TempDir(), "jwe-key-pair") - assert.NilError(t, err) - prv := filepath.Join(td, "mykey.pem") - pub := filepath.Join(td, "mypubkey.pem") - cmds := [][]string{ - // Exec openssl commands to ensure that nerdctl is compatible with the output of openssl commands. - // Do NOT refactor this function to use "crypto/rsa" stdlib. - {"openssl", "genrsa", "-out", prv}, - {"openssl", "rsa", "-in", prv, "-pubout", "-out", pub}, - } - for _, f := range cmds { - cmd := exec.Command(f[0], f[1:]...) - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) - } - } - return &jweKeyPair{ - prv: prv, - pub: pub, - cleanup: func() { - _ = os.RemoveAll(td) - }, - } -} - -func rmiAll(base *testutil.Base) { - base.T.Logf("Pruning images") - imageIDs := base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() - // remove empty output line at the end - imageIDs = imageIDs[:len(imageIDs)-1] - // use `Run` on purpose (same below) because `rmi all` may fail on individual - // image id that has an expected running container (e.g. a registry) - base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() - - base.T.Logf("Pruning build caches") - if _, err := buildkitutil.GetBuildkitHost(testutil.Namespace); err == nil { - base.Cmd("builder", "prune", "--force").AssertOK() - } - - // For BuildKit >= 0.11, pruning cache isn't enough to remove manifest blobs that are referred by build history blobs - // https://github.com/containerd/nerdctl/pull/1833 - if base.Target == testutil.Nerdctl { - base.T.Logf("Pruning all content blobs") - addr := base.ContainerdAddress() - client, err := containerd.New(addr, containerd.WithDefaultNamespace(testutil.Namespace)) - assert.NilError(base.T, err) - cs := client.ContentStore() - ctx := context.TODO() - wf := func(info content.Info) error { - base.T.Logf("Pruning blob %+v", info) - if err := cs.Delete(ctx, info.Digest); err != nil { - base.T.Log(err) - } - return nil - } - if err := cs.Walk(ctx, wf); err != nil { - base.T.Log(err) - } - - base.T.Logf("Pruning all images (again?)") - imageIDs = base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() - base.T.Logf("pruning following images: %+v", imageIDs) - base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() - } -} - func TestImageEncryptJWE(t *testing.T) { testutil.RequiresBuild(t) testutil.DockerIncompatible(t) - keyPair := newJWEKeyPair(t) - defer keyPair.cleanup() + keyPair := helpers.NewJWEKeyPair(t) + defer keyPair.Cleanup() base := testutil.NewBase(t) tID := testutil.Identifier(t) reg := testregistry.NewWithNoAuth(base, 0, false) @@ -120,16 +37,16 @@ func TestImageEncryptJWE(t *testing.T) { base.Cmd("pull", testutil.CommonImage).AssertOK() encryptImageRef := fmt.Sprintf("127.0.0.1:%d/%s:encrypted", reg.Port, tID) defer base.Cmd("rmi", encryptImageRef).Run() - base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.pub, testutil.CommonImage, encryptImageRef).AssertOK() + base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, testutil.CommonImage, encryptImageRef).AssertOK() base.Cmd("image", "inspect", "--mode=native", "--format={{len .Index.Manifests}}", encryptImageRef).AssertOutExactly("1\n") base.Cmd("image", "inspect", "--mode=native", "--format={{json .Manifest.Layers}}", encryptImageRef).AssertOutContains("org.opencontainers.image.enc.keys.jwe") base.Cmd("push", encryptImageRef).AssertOK() // remove all local images (in the nerdctl-test namespace), to ensure that we do not have blobs of the original image. - rmiAll(base) + helpers.RmiAll(base) base.Cmd("pull", encryptImageRef).AssertFail() // defaults to --unpack=true, and fails due to missing prv key base.Cmd("pull", "--unpack=false", encryptImageRef).AssertOK() decryptImageRef := tID + ":decrypted" defer base.Cmd("rmi", decryptImageRef).Run() - base.Cmd("image", "decrypt", "--key="+keyPair.pub, encryptImageRef, decryptImageRef).AssertFail() // decryption needs prv key, not pub key - base.Cmd("image", "decrypt", "--key="+keyPair.prv, encryptImageRef, decryptImageRef).AssertOK() + base.Cmd("image", "decrypt", "--key="+keyPair.Pub, encryptImageRef, decryptImageRef).AssertFail() // decryption needs prv key, not pub key + base.Cmd("image", "decrypt", "--key="+keyPair.Prv, encryptImageRef, decryptImageRef).AssertOK() } diff --git a/cmd/nerdctl/image_list_test.go b/cmd/nerdctl/image_list_test.go index e91a9043f54..12edc26472b 100644 --- a/cmd/nerdctl/image_list_test.go +++ b/cmd/nerdctl/image_list_test.go @@ -24,6 +24,7 @@ import ( "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/tabutil" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -90,7 +91,7 @@ CMD ["echo", "nerdctl-build-test-string"] \n LABEL foo=bar LABEL version=0.1`, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", tempName, "-f", buildCtx+"/Dockerfile", buildCtx).AssertOK() defer base.Cmd("rmi", tempName).AssertOK() @@ -129,7 +130,7 @@ func TestImagesFilterDangling(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-notag-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-f", buildCtx+"/Dockerfile", buildCtx).AssertOK() diff --git a/cmd/nerdctl/image_prune_test.go b/cmd/nerdctl/image_prune_test.go index 17d7ec038a9..2c07a5a330d 100644 --- a/cmd/nerdctl/image_prune_test.go +++ b/cmd/nerdctl/image_prune_test.go @@ -21,6 +21,7 @@ import ( "testing" "time" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -35,7 +36,7 @@ func TestImagePrune(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune"]`, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", buildCtx).AssertOK() base.Cmd("build", "-t", imageName, buildCtx).AssertOK() @@ -56,7 +57,7 @@ func TestImagePruneAll(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune"]`, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() // The following commands will clean up all images, so it should fail at this point. @@ -86,7 +87,7 @@ CMD ["echo", "nerdctl-test-image-prune-filter-label"] LABEL foo=bar LABEL version=0.1`, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("images", "--all").AssertOutContains(imageName) @@ -117,7 +118,7 @@ func TestImagePruneFilterUntil(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune-filter-until"]`, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, buildCtx).AssertOK() base.Cmd("images", "--all").AssertOutContains(imageName) diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image_pull_linux_test.go index dbb0ff4d8e8..577e54291df 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image_pull_linux_test.go @@ -26,6 +26,7 @@ import ( "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) @@ -81,7 +82,7 @@ func TestImageVerifyWithCosign(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() @@ -103,7 +104,7 @@ func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() base.Cmd("--insecure-registry", "push", testImageRef).AssertOK() base.Cmd("--insecure-registry", "pull", testImageRef).AssertOK() @@ -131,7 +132,7 @@ func TestImageVerifyWithCosignShouldFailWhenKeyIsNotCorrect(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() diff --git a/cmd/nerdctl/ipfs_build_linux_test.go b/cmd/nerdctl/ipfs_build_linux_test.go index c3373715fa9..cdc47bc3b2a 100644 --- a/cmd/nerdctl/ipfs_build_linux_test.go +++ b/cmd/nerdctl/ipfs_build_linux_test.go @@ -25,6 +25,7 @@ import ( "gotest.tools/v3/assert" "gotest.tools/v3/icmd" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -43,7 +44,7 @@ func TestIPFSBuild(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, ipfsCIDBase) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) done := ipfsRegistryUp(t, base) defer done() diff --git a/cmd/nerdctl/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs_compose_linux_test.go index 3257fef88d3..c8d60900cc5 100644 --- a/cmd/nerdctl/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs_compose_linux_test.go @@ -24,6 +24,7 @@ import ( "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" @@ -67,14 +68,14 @@ func TestIPFSComposeUp(t *testing.T) { t.Run(tt.name, func(t *testing.T) { base := testutil.NewBase(t) if tt.requiresStargz { - requiresStargz(base) + helpers.RequiresStargz(base) } ipfsImgs := make([]string, 2) for i, img := range []string{testutil.WordpressImage, testutil.MariaDBImage} { ipfsImgs[i] = pushImageToIPFS(t, base, img, tt.pushOptions...) } base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER="+tt.snapshotter) - testComposeUp(t, base, fmt.Sprintf(` + helpers.ComposeUp(t, base, fmt.Sprintf(` version: '3.1' services: diff --git a/cmd/nerdctl/ipfs_linux_test.go b/cmd/nerdctl/ipfs_linux_test.go index 0cff7e9433e..b9f5471bc97 100644 --- a/cmd/nerdctl/ipfs_linux_test.go +++ b/cmd/nerdctl/ipfs_linux_test.go @@ -22,6 +22,7 @@ import ( "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" @@ -37,23 +38,23 @@ func TestIPFS(t *testing.T) { base.Cmd("run", "--rm", ipfsCID, "echo", "hello").AssertOK() // encryption - keyPair := newJWEKeyPair(t) - defer keyPair.cleanup() + keyPair := helpers.NewJWEKeyPair(t) + defer keyPair.Cleanup() tID := testutil.Identifier(t) encryptImageRef := tID + ":enc" layersNum := 1 - base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.pub, ipfsCID, encryptImageRef).AssertOK() + base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, ipfsCID, encryptImageRef).AssertOK() base.Cmd("image", "inspect", "--mode=native", "--format={{len .Manifest.Layers}}", encryptImageRef).AssertOutExactly(fmt.Sprintf("%d\n", layersNum)) for i := 0; i < layersNum; i++ { base.Cmd("image", "inspect", "--mode=native", fmt.Sprintf("--format={{json (index .Manifest.Layers %d) }}", i), encryptImageRef).AssertOutContains("org.opencontainers.image.enc.keys.jwe") } ipfsCIDEnc := cidOf(t, base.Cmd("push", "ipfs://"+encryptImageRef).OutLines()) - rmiAll(base) + helpers.RmiAll(base) decryptImageRef := tID + ":dec" base.Cmd("pull", "--unpack=false", ipfsCIDEnc).AssertOK() - base.Cmd("image", "decrypt", "--key="+keyPair.pub, ipfsCIDEnc, decryptImageRef).AssertFail() // decryption needs prv key, not pub key - base.Cmd("image", "decrypt", "--key="+keyPair.prv, ipfsCIDEnc, decryptImageRef).AssertOK() + base.Cmd("image", "decrypt", "--key="+keyPair.Pub, ipfsCIDEnc, decryptImageRef).AssertFail() // decryption needs prv key, not pub key + base.Cmd("image", "decrypt", "--key="+keyPair.Prv, ipfsCIDEnc, decryptImageRef).AssertOK() base.Cmd("run", "--rm", decryptImageRef, "/bin/sh", "-c", "echo hello").AssertOK() } @@ -91,7 +92,7 @@ func TestIPFSCommit(t *testing.T) { base.Cmd("kill", newContainer).AssertOK() base.Cmd("rm", newContainer).AssertOK() ipfsCID2 := cidOf(t, base.Cmd("push", "ipfs://"+newImg).OutLines()) - rmiAll(base) + helpers.RmiAll(base) base.Cmd("pull", ipfsCID2).AssertOK() base.Cmd("run", "--rm", ipfsCID2, "/bin/sh", "-c", "cat /hello").AssertOK() } @@ -99,7 +100,7 @@ func TestIPFSCommit(t *testing.T) { func TestIPFSWithLazyPulling(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - requiresStargz(base) + helpers.RequiresStargz(base) ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=stargz") @@ -114,7 +115,7 @@ func TestIPFSWithLazyPullingCommit(t *testing.T) { } testutil.DockerIncompatible(t) base := testutil.NewBase(t) - requiresStargz(base) + helpers.RequiresStargz(base) ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=stargz") @@ -127,7 +128,7 @@ func TestIPFSWithLazyPullingCommit(t *testing.T) { base.Cmd("kill", newContainer).AssertOK() base.Cmd("rm", newContainer).AssertOK() ipfsCID2 := cidOf(t, base.Cmd("push", "--estargz", "ipfs://"+newImg).OutLines()) - rmiAll(base) + helpers.RmiAll(base) base.Cmd("pull", ipfsCID2).AssertOK() base.Cmd("run", "--rm", ipfsCID2, "/bin/sh", "-c", "ls /.stargz-snapshotter && cat /hello").AssertOK() diff --git a/cmd/nerdctl/ipfs_registry.go b/cmd/nerdctl/ipfs_registry.go index 68b9b6e7458..c61468df40e 100644 --- a/cmd/nerdctl/ipfs_registry.go +++ b/cmd/nerdctl/ipfs_registry.go @@ -27,7 +27,7 @@ func newIPFSRegistryCommand() *cobra.Command { Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "registry", Short: "Manage read-only registry backed by IPFS", - PreRunE: checkExperimental("ipfs"), + PreRunE: helpers.CheckExperimental("ipfs"), RunE: helpers.UnknownSubcommandAction, SilenceUsage: true, SilenceErrors: true, diff --git a/cmd/nerdctl/ipfs_registry_linux_test.go b/cmd/nerdctl/ipfs_registry_linux_test.go index c47ad9f606b..1d2ce14ebd7 100644 --- a/cmd/nerdctl/ipfs_registry_linux_test.go +++ b/cmd/nerdctl/ipfs_registry_linux_test.go @@ -20,6 +20,7 @@ import ( "strings" "testing" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -42,7 +43,7 @@ func TestIPFSRegistryWithLazyPulling(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - requiresStargz(base) + helpers.RequiresStargz(base) base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=stargz") ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") ipfsRegistryAddr := "localhost:5555" diff --git a/cmd/nerdctl/ipfs_registry_serve.go b/cmd/nerdctl/ipfs_registry_serve.go index c02b32937a1..1ccbcd67720 100644 --- a/cmd/nerdctl/ipfs_registry_serve.go +++ b/cmd/nerdctl/ipfs_registry_serve.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/cmd/ipfs" ) @@ -38,10 +39,10 @@ func newIPFSRegistryServeCommand() *cobra.Command { SilenceErrors: true, } - AddStringFlag(ipfsRegistryServeCommand, "listen-registry", nil, defaultIPFSRegistry, "IPFS_REGISTRY_SERVE_LISTEN_REGISTRY", "address to listen") - AddStringFlag(ipfsRegistryServeCommand, "ipfs-address", nil, "", "IPFS_REGISTRY_SERVE_IPFS_ADDRESS", "multiaddr of IPFS API (default is pulled from $IPFS_PATH/api file. If $IPFS_PATH env var is not present, it defaults to ~/.ipfs)") - AddIntFlag(ipfsRegistryServeCommand, "read-retry-num", nil, defaultIPFSReadRetryNum, "IPFS_REGISTRY_SERVE_READ_RETRY_NUM", "times to retry query on IPFS. Zero or lower means no retry.") - AddDurationFlag(ipfsRegistryServeCommand, "read-timeout", nil, defaultIPFSReadTimeoutDuration, "IPFS_REGISTRY_SERVE_READ_TIMEOUT", "timeout duration of a read request to IPFS. Zero means no timeout.") + helpers.AddStringFlag(ipfsRegistryServeCommand, "listen-registry", nil, defaultIPFSRegistry, "IPFS_REGISTRY_SERVE_LISTEN_REGISTRY", "address to listen") + helpers.AddStringFlag(ipfsRegistryServeCommand, "ipfs-address", nil, "", "IPFS_REGISTRY_SERVE_IPFS_ADDRESS", "multiaddr of IPFS API (default is pulled from $IPFS_PATH/api file. If $IPFS_PATH env var is not present, it defaults to ~/.ipfs)") + helpers.AddIntFlag(ipfsRegistryServeCommand, "read-retry-num", nil, defaultIPFSReadRetryNum, "IPFS_REGISTRY_SERVE_READ_RETRY_NUM", "times to retry query on IPFS. Zero or lower means no retry.") + helpers.AddDurationFlag(ipfsRegistryServeCommand, "read-timeout", nil, defaultIPFSReadTimeoutDuration, "IPFS_REGISTRY_SERVE_READ_TIMEOUT", "timeout duration of a read request to IPFS. Zero means no timeout.") return ipfsRegistryServeCommand } diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index d6aa9377560..5a7d6b194a7 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -23,7 +23,6 @@ import ( "runtime" "strconv" "strings" - "time" "github.com/fatih/color" "github.com/pelletier/go-toml/v2" @@ -350,80 +349,6 @@ func globalFlags(cmd *cobra.Command) (string, []string) { return args0, args } -// AddStringFlag is similar to cmd.Flags().String but supports aliases and env var -func AddStringFlag(cmd *cobra.Command, name string, aliases []string, value string, env, usage string) { - if env != "" { - usage = fmt.Sprintf("%s [$%s]", usage, env) - } - if envV, ok := os.LookupEnv(env); ok { - value = envV - } - aliasesUsage := fmt.Sprintf("Alias of --%s", name) - p := new(string) - flags := cmd.Flags() - flags.StringVar(p, name, value, usage) - for _, a := range aliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - flags.StringVarP(p, a, a, value, aliasesUsage) - } else { - flags.StringVar(p, a, value, aliasesUsage) - } - } -} - -// AddIntFlag is similar to cmd.Flags().Int but supports aliases and env var -func AddIntFlag(cmd *cobra.Command, name string, aliases []string, value int, env, usage string) { - if env != "" { - usage = fmt.Sprintf("%s [$%s]", usage, env) - } - if envV, ok := os.LookupEnv(env); ok { - v, err := strconv.ParseInt(envV, 10, 64) - if err != nil { - log.L.WithError(err).Warnf("Invalid int value for `%s`", env) - } - value = int(v) - } - aliasesUsage := fmt.Sprintf("Alias of --%s", name) - p := new(int) - flags := cmd.Flags() - flags.IntVar(p, name, value, usage) - for _, a := range aliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - flags.IntVarP(p, a, a, value, aliasesUsage) - } else { - flags.IntVar(p, a, value, aliasesUsage) - } - } -} - -// AddDurationFlag is similar to cmd.Flags().Duration but supports aliases and env var -func AddDurationFlag(cmd *cobra.Command, name string, aliases []string, value time.Duration, env, usage string) { - if env != "" { - usage = fmt.Sprintf("%s [$%s]", usage, env) - } - if envV, ok := os.LookupEnv(env); ok { - var err error - value, err = time.ParseDuration(envV) - if err != nil { - log.L.WithError(err).Warnf("Invalid duration value for `%s`", env) - } - } - aliasesUsage := fmt.Sprintf("Alias of --%s", name) - p := new(time.Duration) - flags := cmd.Flags() - flags.DurationVar(p, name, value, usage) - for _, a := range aliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - flags.DurationVarP(p, a, a, value, aliasesUsage) - } else { - flags.DurationVar(p, a, value, aliasesUsage) - } - } -} - // AddPersistentStringFlag is similar to AddStringFlag but persistent. // See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". func AddPersistentStringFlag(cmd *cobra.Command, name string, aliases, localAliases, persistentAliases []string, aliasToBeInherited *pflag.FlagSet, value string, env, usage string) { @@ -544,16 +469,3 @@ func AddPersistentStringArrayFlag(cmd *cobra.Command, name string, aliases, nonP } } } - -func checkExperimental(feature string) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - globalOptions, err := helpers.ProcessRootCmdFlags(cmd) - if err != nil { - return err - } - if !globalOptions.Experimental { - return fmt.Errorf("%s is experimental feature, you should enable experimental config", feature) - } - return nil - } -} diff --git a/cmd/nerdctl/multi_platform_linux_test.go b/cmd/nerdctl/multi_platform_linux_test.go index 944bcf48e28..411df72b308 100644 --- a/cmd/nerdctl/multi_platform_linux_test.go +++ b/cmd/nerdctl/multi_platform_linux_test.go @@ -24,6 +24,7 @@ import ( "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" @@ -68,7 +69,7 @@ func TestMultiPlatformBuildPush(t *testing.T) { RUN echo dummy `, testutil.AlpineImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, "--platform=amd64,arm64,linux/arm/v7", buildCtx).AssertOK() testMultiPlatformRun(base, imageName) @@ -95,7 +96,7 @@ func TestMultiPlatformBuildPushNoRun(t *testing.T) { CMD echo dummy `, testutil.AlpineImage) - buildCtx := createBuildContext(t, dockerfile) + buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", imageName, "--platform=amd64,arm64,linux/arm/v7", buildCtx).AssertOK() testMultiPlatformRun(base, imageName) From 3ea64eb9c4972c1daefb8776afda4c0cf51fbc59 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 09:56:37 -0700 Subject: [PATCH 0726/1066] Move ipfs to subpackage Signed-off-by: apostasie --- cmd/nerdctl/{ => ipfs}/ipfs.go | 4 +-- .../{ => ipfs}/ipfs_build_linux_test.go | 2 +- .../{ => ipfs}/ipfs_compose_linux_test.go | 2 +- cmd/nerdctl/{ => ipfs}/ipfs_linux_test.go | 2 +- cmd/nerdctl/{ => ipfs}/ipfs_registry.go | 2 +- .../{ => ipfs}/ipfs_registry_linux_test.go | 2 +- cmd/nerdctl/{ => ipfs}/ipfs_registry_serve.go | 2 +- cmd/nerdctl/ipfs/ipfs_test.go | 27 +++++++++++++++++++ cmd/nerdctl/main.go | 3 ++- 9 files changed, 37 insertions(+), 9 deletions(-) rename cmd/nerdctl/{ => ipfs}/ipfs.go (95%) rename cmd/nerdctl/{ => ipfs}/ipfs_build_linux_test.go (99%) rename cmd/nerdctl/{ => ipfs}/ipfs_compose_linux_test.go (99%) rename cmd/nerdctl/{ => ipfs}/ipfs_linux_test.go (99%) rename cmd/nerdctl/{ => ipfs}/ipfs_registry.go (98%) rename cmd/nerdctl/{ => ipfs}/ipfs_registry_linux_test.go (99%) rename cmd/nerdctl/{ => ipfs}/ipfs_registry_serve.go (99%) create mode 100644 cmd/nerdctl/ipfs/ipfs_test.go diff --git a/cmd/nerdctl/ipfs.go b/cmd/nerdctl/ipfs/ipfs.go similarity index 95% rename from cmd/nerdctl/ipfs.go rename to cmd/nerdctl/ipfs/ipfs.go index eb08d3dd022..e6e3a2194c8 100644 --- a/cmd/nerdctl/ipfs.go +++ b/cmd/nerdctl/ipfs/ipfs.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package ipfs import ( "github.com/spf13/cobra" @@ -22,7 +22,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) -func newIPFSCommand() *cobra.Command { +func NewIPFSCommand() *cobra.Command { cmd := &cobra.Command{ Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "ipfs", diff --git a/cmd/nerdctl/ipfs_build_linux_test.go b/cmd/nerdctl/ipfs/ipfs_build_linux_test.go similarity index 99% rename from cmd/nerdctl/ipfs_build_linux_test.go rename to cmd/nerdctl/ipfs/ipfs_build_linux_test.go index cdc47bc3b2a..7ca00803bdb 100644 --- a/cmd/nerdctl/ipfs_build_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_build_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package ipfs import ( "fmt" diff --git a/cmd/nerdctl/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go similarity index 99% rename from cmd/nerdctl/ipfs_compose_linux_test.go rename to cmd/nerdctl/ipfs/ipfs_compose_linux_test.go index c8d60900cc5..1ac2b682482 100644 --- a/cmd/nerdctl/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package ipfs import ( "fmt" diff --git a/cmd/nerdctl/ipfs_linux_test.go b/cmd/nerdctl/ipfs/ipfs_linux_test.go similarity index 99% rename from cmd/nerdctl/ipfs_linux_test.go rename to cmd/nerdctl/ipfs/ipfs_linux_test.go index b9f5471bc97..a50e426ae0f 100644 --- a/cmd/nerdctl/ipfs_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package ipfs import ( "fmt" diff --git a/cmd/nerdctl/ipfs_registry.go b/cmd/nerdctl/ipfs/ipfs_registry.go similarity index 98% rename from cmd/nerdctl/ipfs_registry.go rename to cmd/nerdctl/ipfs/ipfs_registry.go index c61468df40e..9beb019f8f3 100644 --- a/cmd/nerdctl/ipfs_registry.go +++ b/cmd/nerdctl/ipfs/ipfs_registry.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package ipfs import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/ipfs_registry_linux_test.go b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go similarity index 99% rename from cmd/nerdctl/ipfs_registry_linux_test.go rename to cmd/nerdctl/ipfs/ipfs_registry_linux_test.go index 1d2ce14ebd7..d367d0d9f86 100644 --- a/cmd/nerdctl/ipfs_registry_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package ipfs import ( "strings" diff --git a/cmd/nerdctl/ipfs_registry_serve.go b/cmd/nerdctl/ipfs/ipfs_registry_serve.go similarity index 99% rename from cmd/nerdctl/ipfs_registry_serve.go rename to cmd/nerdctl/ipfs/ipfs_registry_serve.go index 1ccbcd67720..739d3d3ece6 100644 --- a/cmd/nerdctl/ipfs_registry_serve.go +++ b/cmd/nerdctl/ipfs/ipfs_registry_serve.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package ipfs import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/ipfs/ipfs_test.go b/cmd/nerdctl/ipfs/ipfs_test.go new file mode 100644 index 00000000000..1b6749bee5f --- /dev/null +++ b/cmd/nerdctl/ipfs/ipfs_test.go @@ -0,0 +1,27 @@ +/* + 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 ipfs + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 5a7d6b194a7..373cbc80e20 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -33,6 +33,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/ipfs" "github.com/containerd/nerdctl/v2/cmd/nerdctl/login" "github.com/containerd/nerdctl/v2/cmd/nerdctl/namespace" "github.com/containerd/nerdctl/v2/cmd/nerdctl/network" @@ -314,7 +315,7 @@ Config file ($NERDCTL_TOML): %s newComposeCommand(), // IPFS - newIPFSCommand(), + ipfs.NewIPFSCommand(), ) addApparmorCommand(rootCmd) addCpCommand(rootCmd) From 4b8061d979d358dc1f1eae6187b0acc88965c340 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 11:19:49 -0700 Subject: [PATCH 0727/1066] Move cmd/image & cmd/builder to subpackages Signed-off-by: apostasie --- cmd/nerdctl/{ => builder}/builder.go | 8 +-- cmd/nerdctl/{ => builder}/builder_build.go | 8 +-- .../{ => builder}/builder_build_linux_test.go | 4 +- .../{ => builder}/builder_build_test.go | 2 +- .../{ => builder}/builder_linux_test.go | 2 +- cmd/nerdctl/builder/builder_test.go | 27 ++++++++ cmd/nerdctl/compose_run_linux_test.go | 9 +-- cmd/nerdctl/container_run_linux_test.go | 3 +- cmd/nerdctl/container_run_soci_linux_test.go | 13 +--- .../container_run_verify_linux_test.go | 8 +-- cmd/nerdctl/helpers/testing.go | 40 ++++++++++++ cmd/nerdctl/helpers/testing_linux.go | 58 +++++++++++++++++ cmd/nerdctl/{ => image}/image.go | 23 +++---- cmd/nerdctl/{ => image}/image_convert.go | 2 +- .../{ => image}/image_convert_linux_test.go | 2 +- cmd/nerdctl/{ => image}/image_convert_test.go | 2 +- cmd/nerdctl/{ => image}/image_cryptutil.go | 2 +- cmd/nerdctl/{ => image}/image_decrypt.go | 2 +- cmd/nerdctl/{ => image}/image_encrypt.go | 2 +- .../{ => image}/image_encrypt_linux_test.go | 2 +- cmd/nerdctl/{ => image}/image_history.go | 4 +- cmd/nerdctl/{ => image}/image_history_test.go | 2 +- cmd/nerdctl/{ => image}/image_inspect.go | 6 +- cmd/nerdctl/{ => image}/image_inspect_test.go | 2 +- cmd/nerdctl/{ => image}/image_list.go | 4 +- cmd/nerdctl/{ => image}/image_list_test.go | 2 +- cmd/nerdctl/{ => image}/image_load.go | 4 +- .../{ => image}/image_load_linux_test.go | 2 +- cmd/nerdctl/{ => image}/image_prune.go | 2 +- cmd/nerdctl/{ => image}/image_prune_test.go | 2 +- cmd/nerdctl/{ => image}/image_pull.go | 4 +- .../{ => image}/image_pull_linux_test.go | 57 ++++------------- cmd/nerdctl/{ => image}/image_push.go | 4 +- .../{ => image}/image_push_linux_test.go | 5 +- cmd/nerdctl/{ => image}/image_remove.go | 4 +- .../{ => image}/image_remove_linux_test.go | 2 +- cmd/nerdctl/{ => image}/image_save.go | 4 +- .../{ => image}/image_save_linux_test.go | 62 +------------------ cmd/nerdctl/{ => image}/image_save_test.go | 2 +- cmd/nerdctl/{ => image}/image_tag.go | 4 +- cmd/nerdctl/image/image_test.go | 27 ++++++++ cmd/nerdctl/inspect.go | 3 +- cmd/nerdctl/main.go | 24 +++---- cmd/nerdctl/system_prune.go | 3 +- 44 files changed, 258 insertions(+), 196 deletions(-) rename cmd/nerdctl/{ => builder}/builder.go (97%) rename cmd/nerdctl/{ => builder}/builder_build.go (98%) rename cmd/nerdctl/{ => builder}/builder_build_linux_test.go (97%) rename cmd/nerdctl/{ => builder}/builder_build_test.go (99%) rename cmd/nerdctl/{ => builder}/builder_linux_test.go (99%) create mode 100644 cmd/nerdctl/builder/builder_test.go rename cmd/nerdctl/{ => image}/image.go (82%) rename cmd/nerdctl/{ => image}/image_convert.go (99%) rename cmd/nerdctl/{ => image}/image_convert_linux_test.go (99%) rename cmd/nerdctl/{ => image}/image_convert_test.go (99%) rename cmd/nerdctl/{ => image}/image_cryptutil.go (99%) rename cmd/nerdctl/{ => image}/image_decrypt.go (99%) rename cmd/nerdctl/{ => image}/image_encrypt.go (99%) rename cmd/nerdctl/{ => image}/image_encrypt_linux_test.go (99%) rename cmd/nerdctl/{ => image}/image_history.go (99%) rename cmd/nerdctl/{ => image}/image_history_test.go (99%) rename cmd/nerdctl/{ => image}/image_inspect.go (96%) rename cmd/nerdctl/{ => image}/image_inspect_test.go (99%) rename cmd/nerdctl/{ => image}/image_list.go (98%) rename cmd/nerdctl/{ => image}/image_list_test.go (99%) rename cmd/nerdctl/{ => image}/image_load.go (98%) rename cmd/nerdctl/{ => image}/image_load_linux_test.go (99%) rename cmd/nerdctl/{ => image}/image_prune.go (99%) rename cmd/nerdctl/{ => image}/image_prune_test.go (99%) rename cmd/nerdctl/{ => image}/image_pull.go (99%) rename cmd/nerdctl/{ => image}/image_pull_linux_test.go (82%) rename cmd/nerdctl/{ => image}/image_push.go (99%) rename cmd/nerdctl/{ => image}/image_push_linux_test.go (98%) rename cmd/nerdctl/{ => image}/image_remove.go (98%) rename cmd/nerdctl/{ => image}/image_remove_linux_test.go (99%) rename cmd/nerdctl/{ => image}/image_save.go (98%) rename cmd/nerdctl/{ => image}/image_save_linux_test.go (51%) rename cmd/nerdctl/{ => image}/image_save_test.go (99%) rename cmd/nerdctl/{ => image}/image_tag.go (97%) create mode 100644 cmd/nerdctl/image/image_test.go diff --git a/cmd/nerdctl/builder.go b/cmd/nerdctl/builder/builder.go similarity index 97% rename from cmd/nerdctl/builder.go rename to cmd/nerdctl/builder/builder.go index af3eadce09d..3e8e120f23c 100644 --- a/cmd/nerdctl/builder.go +++ b/cmd/nerdctl/builder/builder.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package builder import ( "fmt" @@ -30,7 +30,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/builder" ) -func newBuilderCommand() *cobra.Command { +func NewBuilderCommand() *cobra.Command { var builderCommand = &cobra.Command{ Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "builder", @@ -40,7 +40,7 @@ func newBuilderCommand() *cobra.Command { SilenceErrors: true, } builderCommand.AddCommand( - newBuildCommand(), + NewBuildCommand(), newBuilderPruneCommand(), newBuilderDebugCommand(), ) @@ -107,7 +107,7 @@ func processBuilderPruneOptions(cmd *cobra.Command) (types.BuilderPruneOptions, return types.BuilderPruneOptions{}, err } - buildkitHost, err := getBuildkitHost(cmd, globalOptions.Namespace) + buildkitHost, err := GetBuildkitHost(cmd, globalOptions.Namespace) if err != nil { return types.BuilderPruneOptions{}, err } diff --git a/cmd/nerdctl/builder_build.go b/cmd/nerdctl/builder/builder_build.go similarity index 98% rename from cmd/nerdctl/builder_build.go rename to cmd/nerdctl/builder/builder_build.go index 6881e2ec169..096a86df668 100644 --- a/cmd/nerdctl/builder_build.go +++ b/cmd/nerdctl/builder/builder_build.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package builder import ( "errors" @@ -34,7 +34,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/strutil" ) -func newBuildCommand() *cobra.Command { +func NewBuildCommand() *cobra.Command { var buildCommand = &cobra.Command{ Use: "build [flags] PATH", Short: "Build an image from a Dockerfile. Needs buildkitd to be running.", @@ -88,7 +88,7 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu if err != nil { return types.BuilderBuildOptions{}, err } - buildKitHost, err := getBuildkitHost(cmd, globalOptions.Namespace) + buildKitHost, err := GetBuildkitHost(cmd, globalOptions.Namespace) if err != nil { return types.BuilderBuildOptions{}, err } @@ -235,7 +235,7 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu }, nil } -func getBuildkitHost(cmd *cobra.Command, namespace string) (string, error) { +func GetBuildkitHost(cmd *cobra.Command, namespace string) (string, error) { if cmd.Flags().Changed("buildkit-host") || os.Getenv("BUILDKIT_HOST") != "" { // If address is explicitly specified, use it. buildkitHost, err := cmd.Flags().GetString("buildkit-host") diff --git a/cmd/nerdctl/builder_build_linux_test.go b/cmd/nerdctl/builder/builder_build_linux_test.go similarity index 97% rename from cmd/nerdctl/builder_build_linux_test.go rename to cmd/nerdctl/builder/builder_build_linux_test.go index 63ca1b6c014..0f80066b0a2 100644 --- a/cmd/nerdctl/builder_build_linux_test.go +++ b/cmd/nerdctl/builder/builder_build_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package builder import ( "fmt" @@ -62,7 +62,7 @@ CMD ["echo", "test-nerdctl-build-context-oci-layout-parent"]`, testutil.CommonIm // Unpack OCI archive into OCI layout directory. ociLayoutDir := t.TempDir() - err := extractTarFile(ociLayoutDir, tarPath) + err := helpers.ExtractTarFile(ociLayoutDir, tarPath) assert.NilError(t, err) dockerfile = fmt.Sprintf(`FROM %s diff --git a/cmd/nerdctl/builder_build_test.go b/cmd/nerdctl/builder/builder_build_test.go similarity index 99% rename from cmd/nerdctl/builder_build_test.go rename to cmd/nerdctl/builder/builder_build_test.go index 82dd9cfa438..92a0928ecae 100644 --- a/cmd/nerdctl/builder_build_test.go +++ b/cmd/nerdctl/builder/builder_build_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package builder import ( "fmt" diff --git a/cmd/nerdctl/builder_linux_test.go b/cmd/nerdctl/builder/builder_linux_test.go similarity index 99% rename from cmd/nerdctl/builder_linux_test.go rename to cmd/nerdctl/builder/builder_linux_test.go index 4aa0e212e08..862320142f9 100644 --- a/cmd/nerdctl/builder_linux_test.go +++ b/cmd/nerdctl/builder/builder_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package builder import ( "bytes" diff --git a/cmd/nerdctl/builder/builder_test.go b/cmd/nerdctl/builder/builder_test.go new file mode 100644 index 00000000000..fee2491cb9b --- /dev/null +++ b/cmd/nerdctl/builder/builder_test.go @@ -0,0 +1,27 @@ +/* + 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 builder + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/compose_run_linux_test.go b/cmd/nerdctl/compose_run_linux_test.go index cd8d353bc9a..e3e3e5ea559 100644 --- a/cmd/nerdctl/compose_run_linux_test.go +++ b/cmd/nerdctl/compose_run_linux_test.go @@ -27,6 +27,7 @@ import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" @@ -432,10 +433,10 @@ func TestComposePushAndPullWithCosignVerify(t *testing.T) { base := testutil.NewBase(t) base.Env = append(base.Env, "COSIGN_PASSWORD=1") - keyPair := newCosignKeyPair(t, "cosign-key-pair", "1") + keyPair := helpers.NewCosignKeyPair(t, "cosign-key-pair", "1") reg := testregistry.NewWithNoAuth(base, 0, false) t.Cleanup(func() { - keyPair.cleanup() + keyPair.Cleanup() reg.Cleanup(nil) }) @@ -475,8 +476,8 @@ services: x-nerdctl-sign: none entrypoint: - stty -`, imageSvc0, keyPair.publicKey, keyPair.privateKey, - imageSvc1, keyPair.privateKey, imageSvc2) +`, imageSvc0, keyPair.PublicKey, keyPair.PrivateKey, + imageSvc1, keyPair.PrivateKey, imageSvc2) dockerfile := fmt.Sprintf(`FROM %s`, testutil.AlpineImage) diff --git a/cmd/nerdctl/container_run_linux_test.go b/cmd/nerdctl/container_run_linux_test.go index 93e9de95d8f..04b7b851a1d 100644 --- a/cmd/nerdctl/container_run_linux_test.go +++ b/cmd/nerdctl/container_run_linux_test.go @@ -35,6 +35,7 @@ import ( "gotest.tools/v3/assert" "gotest.tools/v3/icmd" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/testutil" @@ -70,7 +71,7 @@ func prepareCustomRootfs(base *testutil.Base, imageName string) string { base.Cmd("save", "-o", archiveTarPath, imageName).AssertOK() rootfs, err := os.MkdirTemp(base.T.TempDir(), "rootfs") assert.NilError(base.T, err) - err = extractDockerArchive(archiveTarPath, rootfs) + err = helpers.ExtractDockerArchive(archiveTarPath, rootfs) assert.NilError(base.T, err) return rootfs } diff --git a/cmd/nerdctl/container_run_soci_linux_test.go b/cmd/nerdctl/container_run_soci_linux_test.go index 635f2710cf9..a8085164168 100644 --- a/cmd/nerdctl/container_run_soci_linux_test.go +++ b/cmd/nerdctl/container_run_soci_linux_test.go @@ -21,6 +21,7 @@ import ( "strings" "testing" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -41,7 +42,7 @@ func TestRunSoci(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { base := testutil.NewBase(t) - requiresSoci(base) + helpers.RequiresSoci(base) //counting initial snapshot mounts initialMounts, err := exec.Command("mount").Output() @@ -73,13 +74,3 @@ func TestRunSoci(t *testing.T) { }) } } - -func requiresSoci(base *testutil.Base) { - info := base.Info() - for _, p := range info.Plugins.Storage { - if p == "soci" { - return - } - } - base.T.Skip("test requires soci") -} diff --git a/cmd/nerdctl/container_run_verify_linux_test.go b/cmd/nerdctl/container_run_verify_linux_test.go index 06459f93297..bb3556b7da6 100644 --- a/cmd/nerdctl/container_run_verify_linux_test.go +++ b/cmd/nerdctl/container_run_verify_linux_test.go @@ -35,10 +35,10 @@ func TestRunVerifyCosign(t *testing.T) { base := testutil.NewBase(t) base.Env = append(base.Env, "COSIGN_PASSWORD=1") - keyPair := newCosignKeyPair(t, "cosign-key-pair", "1") + keyPair := helpers.NewCosignKeyPair(t, "cosign-key-pair", "1") reg := testregistry.NewWithNoAuth(base, 0, false) t.Cleanup(func() { - keyPair.cleanup() + keyPair.Cleanup() reg.Cleanup(nil) }) @@ -51,7 +51,7 @@ CMD ["echo", "nerdctl-build-test-string"] buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() - base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() - base.Cmd("run", "--rm", "--verify=cosign", "--cosign-key="+keyPair.publicKey, testImageRef).AssertOK() + base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.PrivateKey).AssertOK() + base.Cmd("run", "--rm", "--verify=cosign", "--cosign-key="+keyPair.PublicKey, testImageRef).AssertOK() base.Cmd("run", "--rm", "--verify=cosign", "--cosign-key=dummy", testImageRef).AssertFail() } diff --git a/cmd/nerdctl/helpers/testing.go b/cmd/nerdctl/helpers/testing.go index 553f4d996d2..d3197a531a5 100644 --- a/cmd/nerdctl/helpers/testing.go +++ b/cmd/nerdctl/helpers/testing.go @@ -18,6 +18,7 @@ package helpers import ( "context" + "fmt" "net" "os" "os/exec" @@ -139,3 +140,42 @@ func CreateBuildContext(t *testing.T, dockerfile string) string { assert.NilError(t, err) return tmpDir } + +func RequiresSoci(base *testutil.Base) { + info := base.Info() + for _, p := range info.Plugins.Storage { + if p == "soci" { + return + } + } + base.T.Skip("test requires soci") +} + +type CosignKeyPair struct { + PublicKey string + PrivateKey string + Cleanup func() +} + +func NewCosignKeyPair(t testing.TB, path string, password string) *CosignKeyPair { + td, err := os.MkdirTemp(t.TempDir(), path) + assert.NilError(t, err) + + cmd := exec.Command("cosign", "generate-key-pair") + cmd.Dir = td + cmd.Env = append(cmd.Env, fmt.Sprintf("COSIGN_PASSWORD=%s", password)) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) + } + + publicKey := filepath.Join(td, "cosign.pub") + privateKey := filepath.Join(td, "cosign.key") + + return &CosignKeyPair{ + PublicKey: publicKey, + PrivateKey: privateKey, + Cleanup: func() { + _ = os.RemoveAll(td) + }, + } +} diff --git a/cmd/nerdctl/helpers/testing_linux.go b/cmd/nerdctl/helpers/testing_linux.go index d459e9272b5..4aed02384bf 100644 --- a/cmd/nerdctl/helpers/testing_linux.go +++ b/cmd/nerdctl/helpers/testing_linux.go @@ -17,8 +17,13 @@ package helpers import ( + "encoding/json" + "errors" "fmt" "io" + "os" + "os/exec" + "path/filepath" "strings" "testing" "time" @@ -77,3 +82,56 @@ func ComposeUp(t *testing.T, base *testutil.Base, dockerComposeYAML string, opts base.Cmd("volume", "inspect", fmt.Sprintf("%s_db", projectName)).AssertFail() base.Cmd("network", "inspect", fmt.Sprintf("%s_default", projectName)).AssertFail() } + +func ExtractDockerArchive(archiveTarPath, rootfsPath string) error { + if err := os.MkdirAll(rootfsPath, 0755); err != nil { + return err + } + workDir, err := os.MkdirTemp("", "extract-docker-archive") + if err != nil { + return err + } + defer os.RemoveAll(workDir) + if err := ExtractTarFile(workDir, archiveTarPath); err != nil { + return err + } + manifestJSONPath := filepath.Join(workDir, "manifest.json") + manifestJSONBytes, err := os.ReadFile(manifestJSONPath) + if err != nil { + return err + } + var mani DockerArchiveManifestJSON + if err := json.Unmarshal(manifestJSONBytes, &mani); err != nil { + return err + } + if len(mani) > 1 { + return fmt.Errorf("multi-image archive cannot be extracted: contains %d images", len(mani)) + } + if len(mani) < 1 { + return errors.New("invalid archive") + } + ent := mani[0] + for _, l := range ent.Layers { + layerTarPath := filepath.Join(workDir, l) + if err := ExtractTarFile(rootfsPath, layerTarPath); err != nil { + return err + } + } + return nil +} + +type DockerArchiveManifestJSON []DockerArchiveManifestJSONEntry + +type DockerArchiveManifestJSONEntry struct { + Config string + RepoTags []string + Layers []string +} + +func ExtractTarFile(dirPath, tarFilePath string) error { + cmd := exec.Command("tar", "Cxf", dirPath, tarFilePath) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to run %v: %q: %w", cmd.Args, string(out), err) + } + return nil +} diff --git a/cmd/nerdctl/image.go b/cmd/nerdctl/image/image.go similarity index 82% rename from cmd/nerdctl/image.go rename to cmd/nerdctl/image/image.go index 0a0f190483a..3c4bc48eeb3 100644 --- a/cmd/nerdctl/image.go +++ b/cmd/nerdctl/image/image.go @@ -14,15 +14,16 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/builder" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) -func newImageCommand() *cobra.Command { +func NewImageCommand() *cobra.Command { cmd := &cobra.Command{ Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "image", @@ -32,15 +33,15 @@ func newImageCommand() *cobra.Command { SilenceErrors: true, } cmd.AddCommand( - newBuildCommand(), + builder.NewBuildCommand(), // commitCommand is in "container", not in "image" imageLsCommand(), - newHistoryCommand(), - newPullCommand(), - newPushCommand(), - newLoadCommand(), - newSaveCommand(), - newTagCommand(), + NewHistoryCommand(), + NewPullCommand(), + NewPushCommand(), + NewLoadCommand(), + NewSaveCommand(), + NewTagCommand(), imageRmCommand(), newImageConvertCommand(), newImageInspectCommand(), @@ -52,14 +53,14 @@ func newImageCommand() *cobra.Command { } func imageLsCommand() *cobra.Command { - x := newImagesCommand() + x := NewImagesCommand() x.Use = "ls" x.Aliases = []string{"list"} return x } func imageRmCommand() *cobra.Command { - x := newRmiCommand() + x := NewRmiCommand() x.Use = "rm" x.Aliases = []string{"remove"} return x diff --git a/cmd/nerdctl/image_convert.go b/cmd/nerdctl/image/image_convert.go similarity index 99% rename from cmd/nerdctl/image_convert.go rename to cmd/nerdctl/image/image_convert.go index 577099245f2..5b181580da6 100644 --- a/cmd/nerdctl/image_convert.go +++ b/cmd/nerdctl/image/image_convert.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "compress/gzip" diff --git a/cmd/nerdctl/image_convert_linux_test.go b/cmd/nerdctl/image/image_convert_linux_test.go similarity index 99% rename from cmd/nerdctl/image_convert_linux_test.go rename to cmd/nerdctl/image/image_convert_linux_test.go index 8022035d0c7..ae90cca5af9 100644 --- a/cmd/nerdctl/image_convert_linux_test.go +++ b/cmd/nerdctl/image/image_convert_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "fmt" diff --git a/cmd/nerdctl/image_convert_test.go b/cmd/nerdctl/image/image_convert_test.go similarity index 99% rename from cmd/nerdctl/image_convert_test.go rename to cmd/nerdctl/image/image_convert_test.go index 8df0b5d6e76..ca5780597d3 100644 --- a/cmd/nerdctl/image_convert_test.go +++ b/cmd/nerdctl/image/image_convert_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "runtime" diff --git a/cmd/nerdctl/image_cryptutil.go b/cmd/nerdctl/image/image_cryptutil.go similarity index 99% rename from cmd/nerdctl/image_cryptutil.go rename to cmd/nerdctl/image/image_cryptutil.go index 067a0f1afe6..0268bddb001 100644 --- a/cmd/nerdctl/image_cryptutil.go +++ b/cmd/nerdctl/image/image_cryptutil.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/image_decrypt.go b/cmd/nerdctl/image/image_decrypt.go similarity index 99% rename from cmd/nerdctl/image_decrypt.go rename to cmd/nerdctl/image/image_decrypt.go index fa6faf46629..6830d137d73 100644 --- a/cmd/nerdctl/image_decrypt.go +++ b/cmd/nerdctl/image/image_decrypt.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/image_encrypt.go b/cmd/nerdctl/image/image_encrypt.go similarity index 99% rename from cmd/nerdctl/image_encrypt.go rename to cmd/nerdctl/image/image_encrypt.go index 39ee30659f3..7c2ef199cbc 100644 --- a/cmd/nerdctl/image_encrypt.go +++ b/cmd/nerdctl/image/image_encrypt.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/image_encrypt_linux_test.go b/cmd/nerdctl/image/image_encrypt_linux_test.go similarity index 99% rename from cmd/nerdctl/image_encrypt_linux_test.go rename to cmd/nerdctl/image/image_encrypt_linux_test.go index 1cd71d49af9..61fb6c30981 100644 --- a/cmd/nerdctl/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image/image_encrypt_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "fmt" diff --git a/cmd/nerdctl/image_history.go b/cmd/nerdctl/image/image_history.go similarity index 99% rename from cmd/nerdctl/image_history.go rename to cmd/nerdctl/image/image_history.go index d3d7a6a3c44..d4f4aa9bcc8 100644 --- a/cmd/nerdctl/image_history.go +++ b/cmd/nerdctl/image/image_history.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "bytes" @@ -43,7 +43,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/imgutil" ) -func newHistoryCommand() *cobra.Command { +func NewHistoryCommand() *cobra.Command { var historyCommand = &cobra.Command{ Use: "history [flags] IMAGE", Short: "Show the history of an image", diff --git a/cmd/nerdctl/image_history_test.go b/cmd/nerdctl/image/image_history_test.go similarity index 99% rename from cmd/nerdctl/image_history_test.go rename to cmd/nerdctl/image/image_history_test.go index d68930cb384..21bef4f5692 100644 --- a/cmd/nerdctl/image_history_test.go +++ b/cmd/nerdctl/image/image_history_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "encoding/json" diff --git a/cmd/nerdctl/image_inspect.go b/cmd/nerdctl/image/image_inspect.go similarity index 96% rename from cmd/nerdctl/image_inspect.go rename to cmd/nerdctl/image/image_inspect.go index c52e975df76..c24d8cf64e3 100644 --- a/cmd/nerdctl/image_inspect.go +++ b/cmd/nerdctl/image/image_inspect.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" @@ -54,7 +54,7 @@ func newImageInspectCommand() *cobra.Command { return imageInspectCommand } -func processImageInspectOptions(cmd *cobra.Command, platform *string) (types.ImageInspectOptions, error) { +func ProcessImageInspectOptions(cmd *cobra.Command, platform *string) (types.ImageInspectOptions, error) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ImageInspectOptions{}, err @@ -84,7 +84,7 @@ func processImageInspectOptions(cmd *cobra.Command, platform *string) (types.Ima } func imageInspectAction(cmd *cobra.Command, args []string) error { - options, err := processImageInspectOptions(cmd, nil) + options, err := ProcessImageInspectOptions(cmd, nil) if err != nil { return err } diff --git a/cmd/nerdctl/image_inspect_test.go b/cmd/nerdctl/image/image_inspect_test.go similarity index 99% rename from cmd/nerdctl/image_inspect_test.go rename to cmd/nerdctl/image/image_inspect_test.go index 4b54c6bbb13..14fcb90caf8 100644 --- a/cmd/nerdctl/image_inspect_test.go +++ b/cmd/nerdctl/image/image_inspect_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "encoding/json" diff --git a/cmd/nerdctl/image_list.go b/cmd/nerdctl/image/image_list.go similarity index 98% rename from cmd/nerdctl/image_list.go rename to cmd/nerdctl/image/image_list.go index c65e960347b..d01fbbd13e2 100644 --- a/cmd/nerdctl/image_list.go +++ b/cmd/nerdctl/image/image_list.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "fmt" @@ -29,7 +29,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) -func newImagesCommand() *cobra.Command { +func NewImagesCommand() *cobra.Command { shortHelp := "List images" longHelp := shortHelp + ` diff --git a/cmd/nerdctl/image_list_test.go b/cmd/nerdctl/image/image_list_test.go similarity index 99% rename from cmd/nerdctl/image_list_test.go rename to cmd/nerdctl/image/image_list_test.go index 12edc26472b..72e902fa62b 100644 --- a/cmd/nerdctl/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "fmt" diff --git a/cmd/nerdctl/image_load.go b/cmd/nerdctl/image/image_load.go similarity index 98% rename from cmd/nerdctl/image_load.go rename to cmd/nerdctl/image/image_load.go index 2cf8fdf3c05..b56a905a0ab 100644 --- a/cmd/nerdctl/image_load.go +++ b/cmd/nerdctl/image/image_load.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" @@ -26,7 +26,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/image" ) -func newLoadCommand() *cobra.Command { +func NewLoadCommand() *cobra.Command { var loadCommand = &cobra.Command{ Use: "load", Args: cobra.NoArgs, diff --git a/cmd/nerdctl/image_load_linux_test.go b/cmd/nerdctl/image/image_load_linux_test.go similarity index 99% rename from cmd/nerdctl/image_load_linux_test.go rename to cmd/nerdctl/image/image_load_linux_test.go index f8e3c9684f8..d92a2167f80 100644 --- a/cmd/nerdctl/image_load_linux_test.go +++ b/cmd/nerdctl/image/image_load_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "fmt" diff --git a/cmd/nerdctl/image_prune.go b/cmd/nerdctl/image/image_prune.go similarity index 99% rename from cmd/nerdctl/image_prune.go rename to cmd/nerdctl/image/image_prune.go index 0480a6a544d..9eefa288958 100644 --- a/cmd/nerdctl/image_prune.go +++ b/cmd/nerdctl/image/image_prune.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "fmt" diff --git a/cmd/nerdctl/image_prune_test.go b/cmd/nerdctl/image/image_prune_test.go similarity index 99% rename from cmd/nerdctl/image_prune_test.go rename to cmd/nerdctl/image/image_prune_test.go index 2c07a5a330d..94ef0c625f2 100644 --- a/cmd/nerdctl/image_prune_test.go +++ b/cmd/nerdctl/image/image_prune_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "fmt" diff --git a/cmd/nerdctl/image_pull.go b/cmd/nerdctl/image/image_pull.go similarity index 99% rename from cmd/nerdctl/image_pull.go rename to cmd/nerdctl/image/image_pull.go index fdfb2420c6c..9b1f961d8e1 100644 --- a/cmd/nerdctl/image_pull.go +++ b/cmd/nerdctl/image/image_pull.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" @@ -28,7 +28,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/strutil" ) -func newPullCommand() *cobra.Command { +func NewPullCommand() *cobra.Command { var pullCommand = &cobra.Command{ Use: "pull [flags] NAME[:TAG]", Short: "Pull an image from a registry. Optionally specify \"ipfs://\" or \"ipns://\" scheme to pull image from IPFS.", diff --git a/cmd/nerdctl/image_pull_linux_test.go b/cmd/nerdctl/image/image_pull_linux_test.go similarity index 82% rename from cmd/nerdctl/image_pull_linux_test.go rename to cmd/nerdctl/image/image_pull_linux_test.go index 577e54291df..d3e956238cf 100644 --- a/cmd/nerdctl/image_pull_linux_test.go +++ b/cmd/nerdctl/image/image_pull_linux_test.go @@ -14,52 +14,19 @@ limitations under the License. */ -package main +package image import ( "fmt" - "os" "os/exec" - "path/filepath" "strings" "testing" - "gotest.tools/v3/assert" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) -type cosignKeyPair struct { - publicKey string - privateKey string - cleanup func() -} - -func newCosignKeyPair(t testing.TB, path string, password string) *cosignKeyPair { - td, err := os.MkdirTemp(t.TempDir(), path) - assert.NilError(t, err) - - cmd := exec.Command("cosign", "generate-key-pair") - cmd.Dir = td - cmd.Env = append(cmd.Env, fmt.Sprintf("COSIGN_PASSWORD=%s", password)) - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) - } - - publicKey := filepath.Join(td, "cosign.pub") - privateKey := filepath.Join(td, "cosign.key") - - return &cosignKeyPair{ - publicKey: publicKey, - privateKey: privateKey, - cleanup: func() { - _ = os.RemoveAll(td) - }, - } -} - func TestImageVerifyWithCosign(t *testing.T) { testutil.RequireExecutable(t, "cosign") testutil.DockerIncompatible(t) @@ -67,8 +34,8 @@ func TestImageVerifyWithCosign(t *testing.T) { testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) base.Env = append(base.Env, "COSIGN_PASSWORD=1") - keyPair := newCosignKeyPair(t, "cosign-key-pair", "1") - defer keyPair.cleanup() + keyPair := helpers.NewCosignKeyPair(t, "cosign-key-pair", "1") + defer keyPair.Cleanup() tID := testutil.Identifier(t) reg := testregistry.NewWithNoAuth(base, 0, false) defer reg.Cleanup(nil) @@ -85,8 +52,8 @@ CMD ["echo", "nerdctl-build-test-string"] buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() - base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() - base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.publicKey).AssertOK() + base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.PrivateKey).AssertOK() + base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.PublicKey).AssertOK() } func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { @@ -117,8 +84,8 @@ func TestImageVerifyWithCosignShouldFailWhenKeyIsNotCorrect(t *testing.T) { testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) base.Env = append(base.Env, "COSIGN_PASSWORD=1") - keyPair := newCosignKeyPair(t, "cosign-key-pair", "1") - defer keyPair.cleanup() + keyPair := helpers.NewCosignKeyPair(t, "cosign-key-pair", "1") + defer keyPair.Cleanup() tID := testutil.Identifier(t) reg := testregistry.NewWithNoAuth(base, 0, false) defer reg.Cleanup(nil) @@ -135,12 +102,12 @@ CMD ["echo", "nerdctl-build-test-string"] buildCtx := helpers.CreateBuildContext(t, dockerfile) base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() - base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.privateKey).AssertOK() - base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.publicKey).AssertOK() + base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.PrivateKey).AssertOK() + base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.PublicKey).AssertOK() base.Env = append(base.Env, "COSIGN_PASSWORD=2") - newKeyPair := newCosignKeyPair(t, "cosign-key-pair-test", "2") - base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+newKeyPair.publicKey).AssertFail() + newKeyPair := helpers.NewCosignKeyPair(t, "cosign-key-pair-test", "2") + base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+newKeyPair.PublicKey).AssertFail() } func TestPullSoci(t *testing.T) { @@ -168,7 +135,7 @@ func TestPullSoci(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { base := testutil.NewBase(t) - requiresSoci(base) + helpers.RequiresSoci(base) //counting initial snapshot mounts initialMounts, err := exec.Command("mount").Output() diff --git a/cmd/nerdctl/image_push.go b/cmd/nerdctl/image/image_push.go similarity index 99% rename from cmd/nerdctl/image_push.go rename to cmd/nerdctl/image/image_push.go index 147e8dfa063..eebadbf7586 100644 --- a/cmd/nerdctl/image_push.go +++ b/cmd/nerdctl/image/image_push.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" @@ -30,7 +30,7 @@ const ( allowNonDistFlag = "allow-nondistributable-artifacts" ) -func newPushCommand() *cobra.Command { +func NewPushCommand() *cobra.Command { var pushCommand = &cobra.Command{ Use: "push [flags] NAME[:TAG]", Short: "Push an image or a repository to a registry. Optionally specify \"ipfs://\" or \"ipns://\" scheme to push image to IPFS.", diff --git a/cmd/nerdctl/image_push_linux_test.go b/cmd/nerdctl/image/image_push_linux_test.go similarity index 98% rename from cmd/nerdctl/image_push_linux_test.go rename to cmd/nerdctl/image/image_push_linux_test.go index 17ab1a89227..17f757703cf 100644 --- a/cmd/nerdctl/image_push_linux_test.go +++ b/cmd/nerdctl/image/image_push_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "fmt" @@ -24,6 +24,7 @@ import ( "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) @@ -179,7 +180,7 @@ func TestPushNonDistributableArtifacts(t *testing.T) { func TestPushSoci(t *testing.T) { testutil.DockerIncompatible(t) base := testutil.NewBase(t) - requiresSoci(base) + helpers.RequiresSoci(base) reg := testregistry.NewWithNoAuth(base, 0, false) defer reg.Cleanup(nil) diff --git a/cmd/nerdctl/image_remove.go b/cmd/nerdctl/image/image_remove.go similarity index 98% rename from cmd/nerdctl/image_remove.go rename to cmd/nerdctl/image/image_remove.go index dde5a6d035e..cb9a86c39d5 100644 --- a/cmd/nerdctl/image_remove.go +++ b/cmd/nerdctl/image/image_remove.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" @@ -26,7 +26,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/image" ) -func newRmiCommand() *cobra.Command { +func NewRmiCommand() *cobra.Command { var rmiCommand = &cobra.Command{ Use: "rmi [flags] IMAGE [IMAGE, ...]", Short: "Remove one or more images", diff --git a/cmd/nerdctl/image_remove_linux_test.go b/cmd/nerdctl/image/image_remove_linux_test.go similarity index 99% rename from cmd/nerdctl/image_remove_linux_test.go rename to cmd/nerdctl/image/image_remove_linux_test.go index 55fbc0a898b..5752aa04aa4 100644 --- a/cmd/nerdctl/image_remove_linux_test.go +++ b/cmd/nerdctl/image/image_remove_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "testing" diff --git a/cmd/nerdctl/image_save.go b/cmd/nerdctl/image/image_save.go similarity index 98% rename from cmd/nerdctl/image_save.go rename to cmd/nerdctl/image/image_save.go index 287e93c1b39..8c2ce38d309 100644 --- a/cmd/nerdctl/image_save.go +++ b/cmd/nerdctl/image/image_save.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "fmt" @@ -30,7 +30,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/image" ) -func newSaveCommand() *cobra.Command { +func NewSaveCommand() *cobra.Command { var saveCommand = &cobra.Command{ Use: "save", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/image_save_linux_test.go b/cmd/nerdctl/image/image_save_linux_test.go similarity index 51% rename from cmd/nerdctl/image_save_linux_test.go rename to cmd/nerdctl/image/image_save_linux_test.go index 0536d180983..0c7c722e97e 100644 --- a/cmd/nerdctl/image_save_linux_test.go +++ b/cmd/nerdctl/image/image_save_linux_test.go @@ -14,20 +14,17 @@ limitations under the License. */ -package main +package image import ( - "encoding/json" - "errors" - "fmt" "os" - "os/exec" "path/filepath" "strings" "testing" "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -41,7 +38,7 @@ func TestSave(t *testing.T) { archiveTarPath := filepath.Join(t.TempDir(), "a.tar") base.Cmd("save", "-o", archiveTarPath, testutil.AlpineImage).AssertOK() rootfsPath := filepath.Join(t.TempDir(), "rootfs") - err := extractDockerArchive(archiveTarPath, rootfsPath) + err := helpers.ExtractDockerArchive(archiveTarPath, rootfsPath) assert.NilError(t, err) etcOSReleasePath := filepath.Join(rootfsPath, "/etc/os-release") etcOSReleaseBytes, err := os.ReadFile(etcOSReleasePath) @@ -51,56 +48,3 @@ func TestSave(t *testing.T) { t.Log(etcOSRelease) assert.Assert(t, strings.Contains(etcOSRelease, "Alpine")) } - -func extractDockerArchive(archiveTarPath, rootfsPath string) error { - if err := os.MkdirAll(rootfsPath, 0755); err != nil { - return err - } - workDir, err := os.MkdirTemp("", "extract-docker-archive") - if err != nil { - return err - } - defer os.RemoveAll(workDir) - if err := extractTarFile(workDir, archiveTarPath); err != nil { - return err - } - manifestJSONPath := filepath.Join(workDir, "manifest.json") - manifestJSONBytes, err := os.ReadFile(manifestJSONPath) - if err != nil { - return err - } - var mani DockerArchiveManifestJSON - if err := json.Unmarshal(manifestJSONBytes, &mani); err != nil { - return err - } - if len(mani) > 1 { - return fmt.Errorf("multi-image archive cannot be extracted: contains %d images", len(mani)) - } - if len(mani) < 1 { - return errors.New("invalid archive") - } - ent := mani[0] - for _, l := range ent.Layers { - layerTarPath := filepath.Join(workDir, l) - if err := extractTarFile(rootfsPath, layerTarPath); err != nil { - return err - } - } - return nil -} - -type DockerArchiveManifestJSON []DockerArchiveManifestJSONEntry - -type DockerArchiveManifestJSONEntry struct { - Config string - RepoTags []string - Layers []string -} - -func extractTarFile(dirPath, tarFilePath string) error { - cmd := exec.Command("tar", "Cxf", dirPath, tarFilePath) - if out, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("failed to run %v: %q: %w", cmd.Args, string(out), err) - } - return nil -} diff --git a/cmd/nerdctl/image_save_test.go b/cmd/nerdctl/image/image_save_test.go similarity index 99% rename from cmd/nerdctl/image_save_test.go rename to cmd/nerdctl/image/image_save_test.go index 4b37a497b93..c8078967477 100644 --- a/cmd/nerdctl/image_save_test.go +++ b/cmd/nerdctl/image/image_save_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "path/filepath" diff --git a/cmd/nerdctl/image_tag.go b/cmd/nerdctl/image/image_tag.go similarity index 97% rename from cmd/nerdctl/image_tag.go rename to cmd/nerdctl/image/image_tag.go index 9989665d12d..4e3d5b965fc 100644 --- a/cmd/nerdctl/image_tag.go +++ b/cmd/nerdctl/image/image_tag.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package image import ( "github.com/spf13/cobra" @@ -26,7 +26,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/image" ) -func newTagCommand() *cobra.Command { +func NewTagCommand() *cobra.Command { var tagCommand = &cobra.Command{ Use: "tag [flags] SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]", Short: "Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE", diff --git a/cmd/nerdctl/image/image_test.go b/cmd/nerdctl/image/image_test.go new file mode 100644 index 00000000000..4cbba7d968f --- /dev/null +++ b/cmd/nerdctl/image/image_test.go @@ -0,0 +1,27 @@ +/* + 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 image + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/inspect.go b/cmd/nerdctl/inspect.go index 14f92c8a379..c9cf64c6949 100644 --- a/cmd/nerdctl/inspect.go +++ b/cmd/nerdctl/inspect.go @@ -24,6 +24,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + imageCmd "github.com/containerd/nerdctl/v2/cmd/nerdctl/image" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/container" @@ -115,7 +116,7 @@ func inspectAction(cmd *cobra.Command, args []string) error { var containerInspectOptions types.ContainerInspectOptions if inspectImage { platform := "" - imageInspectOptions, err = processImageInspectOptions(cmd, &platform) + imageInspectOptions, err = imageCmd.ProcessImageInspectOptions(cmd, &platform) if err != nil { return err } diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 373cbc80e20..16c8b8816a0 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -31,8 +31,10 @@ import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/builder" "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/image" "github.com/containerd/nerdctl/v2/cmd/nerdctl/ipfs" "github.com/containerd/nerdctl/v2/cmd/nerdctl/login" "github.com/containerd/nerdctl/v2/cmd/nerdctl/namespace" @@ -266,17 +268,17 @@ Config file ($NERDCTL_TOML): %s // #endregion // Build - newBuildCommand(), + builder.NewBuildCommand(), // #region Image management - newImagesCommand(), - newPullCommand(), - newPushCommand(), - newLoadCommand(), - newSaveCommand(), - newTagCommand(), - newRmiCommand(), - newHistoryCommand(), + image.NewImagesCommand(), + image.NewPullCommand(), + image.NewPushCommand(), + image.NewLoadCommand(), + image.NewSaveCommand(), + image.NewTagCommand(), + image.NewRmiCommand(), + image.NewHistoryCommand(), // #endregion // #region System @@ -294,12 +296,12 @@ Config file ($NERDCTL_TOML): %s // #region helpers.Management newContainerCommand(), - newImageCommand(), + image.NewImageCommand(), network.NewNetworkCommand(), volume.NewVolumeCommand(), newSystemCommand(), namespace.NewNamespaceCommand(), - newBuilderCommand(), + builder.NewBuilderCommand(), // #endregion // Internal diff --git a/cmd/nerdctl/system_prune.go b/cmd/nerdctl/system_prune.go index 2f446572618..cfe1cb41661 100644 --- a/cmd/nerdctl/system_prune.go +++ b/cmd/nerdctl/system_prune.go @@ -24,6 +24,7 @@ import ( "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/builder" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/cmd/nerdctl/network" "github.com/containerd/nerdctl/v2/pkg/api/types" @@ -62,7 +63,7 @@ func processSystemPruneOptions(cmd *cobra.Command) (types.SystemPruneOptions, er return types.SystemPruneOptions{}, err } - buildkitHost, err := getBuildkitHost(cmd, globalOptions.Namespace) + buildkitHost, err := builder.GetBuildkitHost(cmd, globalOptions.Namespace) if err != nil { log.L.WithError(err).Warn("BuildKit is not running. Build caches will not be pruned.") buildkitHost = "" From c115c49c4cd9c811699e65cf124fa81c63b58154 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 11:24:00 -0700 Subject: [PATCH 0728/1066] cmd/AppArmor moved to subpackage Signed-off-by: apostasie --- .../{ => apparmor}/apparmor_inspect_linux.go | 2 +- cmd/nerdctl/{ => apparmor}/apparmor_linux.go | 4 +-- cmd/nerdctl/apparmor/apparmor_linux_test.go | 27 +++++++++++++++++++ .../{ => apparmor}/apparmor_list_linux.go | 2 +- .../{ => apparmor}/apparmor_load_linux.go | 2 +- .../{ => apparmor}/apparmor_unload_linux.go | 2 +- cmd/nerdctl/main_linux.go | 3 ++- 7 files changed, 35 insertions(+), 7 deletions(-) rename cmd/nerdctl/{ => apparmor}/apparmor_inspect_linux.go (98%) rename cmd/nerdctl/{ => apparmor}/apparmor_linux.go (94%) create mode 100644 cmd/nerdctl/apparmor/apparmor_linux_test.go rename cmd/nerdctl/{ => apparmor}/apparmor_list_linux.go (99%) rename cmd/nerdctl/{ => apparmor}/apparmor_load_linux.go (98%) rename cmd/nerdctl/{ => apparmor}/apparmor_unload_linux.go (98%) diff --git a/cmd/nerdctl/apparmor_inspect_linux.go b/cmd/nerdctl/apparmor/apparmor_inspect_linux.go similarity index 98% rename from cmd/nerdctl/apparmor_inspect_linux.go rename to cmd/nerdctl/apparmor/apparmor_inspect_linux.go index 681826bf82e..acfec41a959 100644 --- a/cmd/nerdctl/apparmor_inspect_linux.go +++ b/cmd/nerdctl/apparmor/apparmor_inspect_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package apparmor import ( "fmt" diff --git a/cmd/nerdctl/apparmor_linux.go b/cmd/nerdctl/apparmor/apparmor_linux.go similarity index 94% rename from cmd/nerdctl/apparmor_linux.go rename to cmd/nerdctl/apparmor/apparmor_linux.go index c94a80258ff..d1fa8ff977a 100644 --- a/cmd/nerdctl/apparmor_linux.go +++ b/cmd/nerdctl/apparmor/apparmor_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package apparmor import ( "github.com/spf13/cobra" @@ -22,7 +22,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) -func newApparmorCommand() *cobra.Command { +func NewApparmorCommand() *cobra.Command { cmd := &cobra.Command{ Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "apparmor", diff --git a/cmd/nerdctl/apparmor/apparmor_linux_test.go b/cmd/nerdctl/apparmor/apparmor_linux_test.go new file mode 100644 index 00000000000..2cf255871ba --- /dev/null +++ b/cmd/nerdctl/apparmor/apparmor_linux_test.go @@ -0,0 +1,27 @@ +/* + 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 apparmor + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/apparmor_list_linux.go b/cmd/nerdctl/apparmor/apparmor_list_linux.go similarity index 99% rename from cmd/nerdctl/apparmor_list_linux.go rename to cmd/nerdctl/apparmor/apparmor_list_linux.go index e650e3ea21a..f1483e99db3 100644 --- a/cmd/nerdctl/apparmor_list_linux.go +++ b/cmd/nerdctl/apparmor/apparmor_list_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package apparmor import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/apparmor_load_linux.go b/cmd/nerdctl/apparmor/apparmor_load_linux.go similarity index 98% rename from cmd/nerdctl/apparmor_load_linux.go rename to cmd/nerdctl/apparmor/apparmor_load_linux.go index 0c04ae47783..ccd51f406d4 100644 --- a/cmd/nerdctl/apparmor_load_linux.go +++ b/cmd/nerdctl/apparmor/apparmor_load_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package apparmor import ( "fmt" diff --git a/cmd/nerdctl/apparmor_unload_linux.go b/cmd/nerdctl/apparmor/apparmor_unload_linux.go similarity index 98% rename from cmd/nerdctl/apparmor_unload_linux.go rename to cmd/nerdctl/apparmor/apparmor_unload_linux.go index c20aab68765..2ba93809544 100644 --- a/cmd/nerdctl/apparmor_unload_linux.go +++ b/cmd/nerdctl/apparmor/apparmor_unload_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package apparmor import ( "fmt" diff --git a/cmd/nerdctl/main_linux.go b/cmd/nerdctl/main_linux.go index 2e0c0a853e2..d1dfbeaf615 100644 --- a/cmd/nerdctl/main_linux.go +++ b/cmd/nerdctl/main_linux.go @@ -19,6 +19,7 @@ package main import ( "github.com/spf13/cobra" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/apparmor" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" ) @@ -63,7 +64,7 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { } func addApparmorCommand(rootCmd *cobra.Command) { - rootCmd.AddCommand(newApparmorCommand()) + rootCmd.AddCommand(apparmor.NewApparmorCommand()) } func addCpCommand(rootCmd *cobra.Command) { From d5a00f46d75af7b8bf622dacd0b5b3dfb49344c3 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 11:26:33 -0700 Subject: [PATCH 0729/1066] Move cmd/internal to subpackage Signed-off-by: apostasie --- cmd/nerdctl/{ => internal}/internal.go | 4 ++-- cmd/nerdctl/{ => internal}/internal_oci_hook.go | 2 +- cmd/nerdctl/main.go | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) rename cmd/nerdctl/{ => internal}/internal.go (93%) rename cmd/nerdctl/{ => internal}/internal_oci_hook.go (98%) diff --git a/cmd/nerdctl/internal.go b/cmd/nerdctl/internal/internal.go similarity index 93% rename from cmd/nerdctl/internal.go rename to cmd/nerdctl/internal/internal.go index 9f62d1ea2ae..c159452823a 100644 --- a/cmd/nerdctl/internal.go +++ b/cmd/nerdctl/internal/internal.go @@ -14,13 +14,13 @@ limitations under the License. */ -package main +package internal import ( "github.com/spf13/cobra" ) -func newInternalCommand() *cobra.Command { +func NewInternalCommand() *cobra.Command { var internalCommand = &cobra.Command{ Use: "internal", Short: "DO NOT EXECUTE MANUALLY", diff --git a/cmd/nerdctl/internal_oci_hook.go b/cmd/nerdctl/internal/internal_oci_hook.go similarity index 98% rename from cmd/nerdctl/internal_oci_hook.go rename to cmd/nerdctl/internal/internal_oci_hook.go index 4ebad5d2383..404c865804b 100644 --- a/cmd/nerdctl/internal_oci_hook.go +++ b/cmd/nerdctl/internal/internal_oci_hook.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package internal import ( "errors" diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 16c8b8816a0..f02d8867b0e 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -35,6 +35,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/cmd/nerdctl/image" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/internal" "github.com/containerd/nerdctl/v2/cmd/nerdctl/ipfs" "github.com/containerd/nerdctl/v2/cmd/nerdctl/login" "github.com/containerd/nerdctl/v2/cmd/nerdctl/namespace" @@ -305,7 +306,7 @@ Config file ($NERDCTL_TOML): %s // #endregion // Internal - newInternalCommand(), + internal.NewInternalCommand(), // login login.NewLoginCommand(), From ca637fd61b397d203cb47bf65b1aa7b993f3a5fc Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 13:57:01 -0700 Subject: [PATCH 0730/1066] Move cmd/container to subpackage Signed-off-by: apostasie --- cmd/nerdctl/compose.go | 2 +- cmd/nerdctl/{ => container}/container.go | 46 ++++++------ .../{ => container}/container_attach.go | 4 +- .../container_attach_linux_test.go | 2 +- .../{ => container}/container_commit.go | 4 +- .../container_commit_linux_test.go | 2 +- .../{ => container}/container_commit_test.go | 2 +- cmd/nerdctl/{ => container}/container_cp.go | 2 +- cmd/nerdctl/container/container_cp_freebsd.go | 23 ++++++ .../{ => container}/container_cp_linux.go | 6 +- .../container_cp_linux_test.go | 2 +- cmd/nerdctl/container/container_cp_windows.go | 23 ++++++ .../{ => container}/container_create.go | 6 +- .../container_create_linux_test.go | 2 +- .../container_create_windows_test.go | 2 +- cmd/nerdctl/{ => container}/container_diff.go | 4 +- .../container_diff_linux_test.go | 2 +- cmd/nerdctl/{ => container}/container_exec.go | 4 +- .../container_exec_linux_test.go | 2 +- .../{ => container}/container_exec_test.go | 2 +- .../{ => container}/container_inspect.go | 6 +- .../container_inspect_linux_test.go | 2 +- .../container_inspect_windows_test.go | 2 +- cmd/nerdctl/{ => container}/container_kill.go | 4 +- .../container_kill_linux_test.go | 2 +- cmd/nerdctl/{ => container}/container_list.go | 4 +- .../container_list_linux_test.go | 2 +- .../{ => container}/container_list_test.go | 2 +- .../container_list_windows_test.go | 2 +- cmd/nerdctl/{ => container}/container_logs.go | 4 +- .../{ => container}/container_logs_test.go | 2 +- .../{ => container}/container_pause.go | 4 +- cmd/nerdctl/{ => container}/container_port.go | 4 +- .../{ => container}/container_prune.go | 2 +- .../container_prune_linux_test.go | 2 +- .../{ => container}/container_remove.go | 4 +- .../container_remove_linux_test.go | 2 +- .../container_remove_windows_test.go | 2 +- .../{ => container}/container_rename.go | 4 +- .../container_rename_linux_test.go | 2 +- .../container_rename_windows_test.go | 2 +- .../{ => container}/container_restart.go | 4 +- .../container_restart_linux_test.go | 2 +- cmd/nerdctl/{ => container}/container_run.go | 4 +- .../container_run_cgroup_linux_test.go | 2 +- .../{ => container}/container_run_freebsd.go | 2 +- .../container_run_gpus_test.go | 2 +- .../{ => container}/container_run_linux.go | 2 +- .../container_run_linux_test.go | 2 +- .../container_run_log_driver_syslog_test.go | 2 +- .../container_run_mount_linux_test.go | 2 +- .../container_run_mount_windows_test.go | 2 +- .../{ => container}/container_run_network.go | 2 +- .../container_run_network_base_test.go | 2 +- .../container_run_network_linux_test.go | 2 +- .../container_run_network_windows_test.go | 2 +- .../container_run_restart_linux_test.go | 2 +- .../container_run_runtime_linux_test.go | 2 +- .../container_run_security_linux_test.go | 2 +- .../container_run_soci_linux_test.go | 2 +- .../container_run_stargz_linux_test.go | 2 +- .../container_run_systemd_linux_test.go | 2 +- .../{ => container}/container_run_test.go | 2 +- .../container_run_user_linux_test.go | 2 +- .../container_run_user_windows_test.go | 2 +- .../container_run_verify_linux_test.go | 2 +- .../{ => container}/container_run_windows.go | 2 +- .../container_run_windows_test.go | 2 +- .../{ => container}/container_start.go | 4 +- .../container_start_linux_test.go | 2 +- .../{ => container}/container_start_test.go | 2 +- .../{ => container}/container_stats.go | 4 +- .../container_stats_linux_test.go | 2 +- cmd/nerdctl/{ => container}/container_stop.go | 4 +- .../container_stop_linux_test.go | 2 +- cmd/nerdctl/container/container_test.go | 27 +++++++ cmd/nerdctl/{ => container}/container_top.go | 4 +- .../container_top_unix_test.go | 2 +- .../container_top_windows_test.go | 2 +- .../{ => container}/container_unpause.go | 4 +- .../{ => container}/container_update.go | 4 +- cmd/nerdctl/{ => container}/container_wait.go | 4 +- .../{ => container}/container_wait_test.go | 2 +- cmd/nerdctl/helpers/cobra.go | 24 +++++++ cmd/nerdctl/inspect.go | 3 +- cmd/nerdctl/main.go | 70 +++++++------------ cmd/nerdctl/main_freebsd.go | 4 -- cmd/nerdctl/main_linux.go | 4 -- cmd/nerdctl/main_windows.go | 4 -- 89 files changed, 253 insertions(+), 185 deletions(-) rename cmd/nerdctl/{ => container}/container.go (70%) rename cmd/nerdctl/{ => container}/container_attach.go (98%) rename cmd/nerdctl/{ => container}/container_attach_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_commit.go (98%) rename cmd/nerdctl/{ => container}/container_commit_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_commit_test.go (98%) rename cmd/nerdctl/{ => container}/container_cp.go (98%) create mode 100644 cmd/nerdctl/container/container_cp_freebsd.go rename cmd/nerdctl/{ => container}/container_cp_linux.go (97%) rename cmd/nerdctl/{ => container}/container_cp_linux_test.go (99%) create mode 100644 cmd/nerdctl/container/container_cp_windows.go rename cmd/nerdctl/{ => container}/container_create.go (99%) rename cmd/nerdctl/{ => container}/container_create_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_create_windows_test.go (98%) rename cmd/nerdctl/{ => container}/container_diff.go (99%) rename cmd/nerdctl/{ => container}/container_diff_linux_test.go (98%) rename cmd/nerdctl/{ => container}/container_exec.go (98%) rename cmd/nerdctl/{ => container}/container_exec_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_exec_test.go (99%) rename cmd/nerdctl/{ => container}/container_inspect.go (96%) rename cmd/nerdctl/{ => container}/container_inspect_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_inspect_windows_test.go (99%) rename cmd/nerdctl/{ => container}/container_kill.go (97%) rename cmd/nerdctl/{ => container}/container_kill_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_list.go (99%) rename cmd/nerdctl/{ => container}/container_list_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_list_test.go (98%) rename cmd/nerdctl/{ => container}/container_list_windows_test.go (99%) rename cmd/nerdctl/{ => container}/container_logs.go (98%) rename cmd/nerdctl/{ => container}/container_logs_test.go (99%) rename cmd/nerdctl/{ => container}/container_pause.go (97%) rename cmd/nerdctl/{ => container}/container_port.go (98%) rename cmd/nerdctl/{ => container}/container_prune.go (99%) rename cmd/nerdctl/{ => container}/container_prune_linux_test.go (98%) rename cmd/nerdctl/{ => container}/container_remove.go (97%) rename cmd/nerdctl/{ => container}/container_remove_linux_test.go (98%) rename cmd/nerdctl/{ => container}/container_remove_windows_test.go (99%) rename cmd/nerdctl/{ => container}/container_rename.go (97%) rename cmd/nerdctl/{ => container}/container_rename_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_rename_windows_test.go (99%) rename cmd/nerdctl/{ => container}/container_restart.go (97%) rename cmd/nerdctl/{ => container}/container_restart_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run.go (99%) rename cmd/nerdctl/{ => container}/container_run_cgroup_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_freebsd.go (98%) rename cmd/nerdctl/{ => container}/container_run_gpus_test.go (98%) rename cmd/nerdctl/{ => container}/container_run_linux.go (98%) rename cmd/nerdctl/{ => container}/container_run_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_log_driver_syslog_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_mount_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_mount_windows_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_network.go (99%) rename cmd/nerdctl/{ => container}/container_run_network_base_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_network_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_network_windows_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_restart_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_runtime_linux_test.go (98%) rename cmd/nerdctl/{ => container}/container_run_security_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_soci_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_stargz_linux_test.go (98%) rename cmd/nerdctl/{ => container}/container_run_systemd_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_user_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_user_windows_test.go (98%) rename cmd/nerdctl/{ => container}/container_run_verify_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_run_windows.go (98%) rename cmd/nerdctl/{ => container}/container_run_windows_test.go (99%) rename cmd/nerdctl/{ => container}/container_start.go (98%) rename cmd/nerdctl/{ => container}/container_start_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_start_test.go (98%) rename cmd/nerdctl/{ => container}/container_stats.go (98%) rename cmd/nerdctl/{ => container}/container_stats_linux_test.go (99%) rename cmd/nerdctl/{ => container}/container_stop.go (97%) rename cmd/nerdctl/{ => container}/container_stop_linux_test.go (99%) create mode 100644 cmd/nerdctl/container/container_test.go rename cmd/nerdctl/{ => container}/container_top.go (97%) rename cmd/nerdctl/{ => container}/container_top_unix_test.go (98%) rename cmd/nerdctl/{ => container}/container_top_windows_test.go (98%) rename cmd/nerdctl/{ => container}/container_unpause.go (97%) rename cmd/nerdctl/{ => container}/container_update.go (99%) rename cmd/nerdctl/{ => container}/container_wait.go (97%) rename cmd/nerdctl/{ => container}/container_wait_test.go (98%) diff --git a/cmd/nerdctl/compose.go b/cmd/nerdctl/compose.go index 5c3a30368c0..992889bacb7 100644 --- a/cmd/nerdctl/compose.go +++ b/cmd/nerdctl/compose.go @@ -70,7 +70,7 @@ func newComposeCommand() *cobra.Command { } func getComposeOptions(cmd *cobra.Command, debugFull, experimental bool) (composer.Options, error) { - nerdctlCmd, nerdctlArgs := globalFlags(cmd) + nerdctlCmd, nerdctlArgs := helpers.GlobalFlags(cmd) projectDirectory, err := cmd.Flags().GetString("project-directory") if err != nil { return composer.Options{}, err diff --git a/cmd/nerdctl/container.go b/cmd/nerdctl/container/container.go similarity index 70% rename from cmd/nerdctl/container.go rename to cmd/nerdctl/container/container.go index 9db284f5919..21c7f9b63b1 100644 --- a/cmd/nerdctl/container.go +++ b/cmd/nerdctl/container/container.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -22,7 +22,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) -func newContainerCommand() *cobra.Command { +func NewContainerCommand() *cobra.Command { containerCommand := &cobra.Command{ Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "container", @@ -32,35 +32,35 @@ func newContainerCommand() *cobra.Command { SilenceErrors: true, } containerCommand.AddCommand( - newCreateCommand(), - newRunCommand(), - newUpdateCommand(), - newExecCommand(), + NewCreateCommand(), + NewRunCommand(), + NewUpdateCommand(), + NewExecCommand(), containerLsCommand(), newContainerInspectCommand(), - newLogsCommand(), - newPortCommand(), - newRmCommand(), - newStopCommand(), - newStartCommand(), - newRestartCommand(), - newKillCommand(), - newPauseCommand(), - newDiffCommand(), - newWaitCommand(), - newUnpauseCommand(), - newCommitCommand(), - newRenameCommand(), + NewLogsCommand(), + NewPortCommand(), + NewRmCommand(), + NewStopCommand(), + NewStartCommand(), + NewRestartCommand(), + NewKillCommand(), + NewPauseCommand(), + NewDiffCommand(), + NewWaitCommand(), + NewUnpauseCommand(), + NewCommitCommand(), + NewRenameCommand(), newContainerPruneCommand(), - newStatsCommand(), - newAttachCommand(), + NewStatsCommand(), + NewAttachCommand(), ) - addCpCommand(containerCommand) + AddCpCommand(containerCommand) return containerCommand } func containerLsCommand() *cobra.Command { - x := newPsCommand() + x := NewPsCommand() x.Use = "ls" x.Aliases = []string{"list"} return x diff --git a/cmd/nerdctl/container_attach.go b/cmd/nerdctl/container/container_attach.go similarity index 98% rename from cmd/nerdctl/container_attach.go rename to cmd/nerdctl/container/container_attach.go index 0bcbc9830c8..e92aa44b26d 100644 --- a/cmd/nerdctl/container_attach.go +++ b/cmd/nerdctl/container/container_attach.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -29,7 +29,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/consoleutil" ) -func newAttachCommand() *cobra.Command { +func NewAttachCommand() *cobra.Command { const shortHelp = "Attach stdin, stdout, and stderr to a running container." const longHelp = `Attach stdin, stdout, and stderr to a running container. For example: diff --git a/cmd/nerdctl/container_attach_linux_test.go b/cmd/nerdctl/container/container_attach_linux_test.go similarity index 99% rename from cmd/nerdctl/container_attach_linux_test.go rename to cmd/nerdctl/container/container_attach_linux_test.go index e0b04b87d5d..71a74eae59e 100644 --- a/cmd/nerdctl/container_attach_linux_test.go +++ b/cmd/nerdctl/container/container_attach_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "bytes" diff --git a/cmd/nerdctl/container_commit.go b/cmd/nerdctl/container/container_commit.go similarity index 98% rename from cmd/nerdctl/container_commit.go rename to cmd/nerdctl/container/container_commit.go index c6ef5e1243f..e7276499ab3 100644 --- a/cmd/nerdctl/container_commit.go +++ b/cmd/nerdctl/container/container_commit.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -26,7 +26,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newCommitCommand() *cobra.Command { +func NewCommitCommand() *cobra.Command { var commitCommand = &cobra.Command{ Use: "commit [flags] CONTAINER REPOSITORY[:TAG]", Short: "Create a new image from a container's changes", diff --git a/cmd/nerdctl/container_commit_linux_test.go b/cmd/nerdctl/container/container_commit_linux_test.go similarity index 99% rename from cmd/nerdctl/container_commit_linux_test.go rename to cmd/nerdctl/container/container_commit_linux_test.go index a2cc557c4d7..24c791d4f60 100644 --- a/cmd/nerdctl/container_commit_linux_test.go +++ b/cmd/nerdctl/container/container_commit_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "strings" diff --git a/cmd/nerdctl/container_commit_test.go b/cmd/nerdctl/container/container_commit_test.go similarity index 98% rename from cmd/nerdctl/container_commit_test.go rename to cmd/nerdctl/container/container_commit_test.go index b569ebfbcc2..f9f553d9ca1 100644 --- a/cmd/nerdctl/container_commit_test.go +++ b/cmd/nerdctl/container/container_commit_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_cp.go b/cmd/nerdctl/container/container_cp.go similarity index 98% rename from cmd/nerdctl/container_cp.go rename to cmd/nerdctl/container/container_cp.go index a80135b16bd..716fc8fc5c9 100644 --- a/cmd/nerdctl/container_cp.go +++ b/cmd/nerdctl/container/container_cp.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "errors" diff --git a/cmd/nerdctl/container/container_cp_freebsd.go b/cmd/nerdctl/container/container_cp_freebsd.go new file mode 100644 index 00000000000..4e7d2cfd518 --- /dev/null +++ b/cmd/nerdctl/container/container_cp_freebsd.go @@ -0,0 +1,23 @@ +/* + 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 container + +import "github.com/spf13/cobra" + +func AddCpCommand(rootCmd *cobra.Command) { + // NOP +} diff --git a/cmd/nerdctl/container_cp_linux.go b/cmd/nerdctl/container/container_cp_linux.go similarity index 97% rename from cmd/nerdctl/container_cp_linux.go rename to cmd/nerdctl/container/container_cp_linux.go index c63d46030b6..53abf9f898b 100644 --- a/cmd/nerdctl/container_cp_linux.go +++ b/cmd/nerdctl/container/container_cp_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" @@ -127,3 +127,7 @@ func processCpOptions(cmd *cobra.Command, args []string) (types.ContainerCpOptio FollowSymLink: flagL, }, nil } + +func AddCpCommand(rootCmd *cobra.Command) { + rootCmd.AddCommand(newCpCommand()) +} diff --git a/cmd/nerdctl/container_cp_linux_test.go b/cmd/nerdctl/container/container_cp_linux_test.go similarity index 99% rename from cmd/nerdctl/container_cp_linux_test.go rename to cmd/nerdctl/container/container_cp_linux_test.go index 33f59ba45d3..a94f46561b2 100644 --- a/cmd/nerdctl/container_cp_linux_test.go +++ b/cmd/nerdctl/container/container_cp_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container/container_cp_windows.go b/cmd/nerdctl/container/container_cp_windows.go new file mode 100644 index 00000000000..4e7d2cfd518 --- /dev/null +++ b/cmd/nerdctl/container/container_cp_windows.go @@ -0,0 +1,23 @@ +/* + 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 container + +import "github.com/spf13/cobra" + +func AddCpCommand(rootCmd *cobra.Command) { + // NOP +} diff --git a/cmd/nerdctl/container_create.go b/cmd/nerdctl/container/container_create.go similarity index 99% rename from cmd/nerdctl/container_create.go rename to cmd/nerdctl/container/container_create.go index 304ae65db87..bb1c9e88256 100644 --- a/cmd/nerdctl/container_create.go +++ b/cmd/nerdctl/container/container_create.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" @@ -29,7 +29,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/containerutil" ) -func newCreateCommand() *cobra.Command { +func NewCreateCommand() *cobra.Command { shortHelp := "Create a new container. Optionally specify \"ipfs://\" or \"ipns://\" scheme to pull image from IPFS." longHelp := shortHelp switch runtime.GOOS { @@ -67,7 +67,7 @@ func processContainerCreateOptions(cmd *cobra.Command) (types.ContainerCreateOpt return opt, err } - opt.NerdctlCmd, opt.NerdctlArgs = globalFlags(cmd) + opt.NerdctlCmd, opt.NerdctlArgs = helpers.GlobalFlags(cmd) // #region for basic flags // The command `container start` doesn't support the flag `--interactive`. Set the default value of `opt.Interactive` false. diff --git a/cmd/nerdctl/container_create_linux_test.go b/cmd/nerdctl/container/container_create_linux_test.go similarity index 99% rename from cmd/nerdctl/container_create_linux_test.go rename to cmd/nerdctl/container/container_create_linux_test.go index 601326462b2..e3e2122bf80 100644 --- a/cmd/nerdctl/container_create_linux_test.go +++ b/cmd/nerdctl/container/container_create_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_create_windows_test.go b/cmd/nerdctl/container/container_create_windows_test.go similarity index 98% rename from cmd/nerdctl/container_create_windows_test.go rename to cmd/nerdctl/container/container_create_windows_test.go index f52cda49819..d80f5bb6d1d 100644 --- a/cmd/nerdctl/container_create_windows_test.go +++ b/cmd/nerdctl/container/container_create_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_diff.go b/cmd/nerdctl/container/container_diff.go similarity index 99% rename from cmd/nerdctl/container_diff.go rename to cmd/nerdctl/container/container_diff.go index 3e2025ea27e..279c1aa2c79 100644 --- a/cmd/nerdctl/container_diff.go +++ b/cmd/nerdctl/container/container_diff.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "context" @@ -43,7 +43,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/labels" ) -func newDiffCommand() *cobra.Command { +func NewDiffCommand() *cobra.Command { var diffCommand = &cobra.Command{ Use: "diff [CONTAINER]", Short: "Inspect changes to files or directories on a container's filesystem", diff --git a/cmd/nerdctl/container_diff_linux_test.go b/cmd/nerdctl/container/container_diff_linux_test.go similarity index 98% rename from cmd/nerdctl/container_diff_linux_test.go rename to cmd/nerdctl/container/container_diff_linux_test.go index 69041d82e99..7de8c302ed5 100644 --- a/cmd/nerdctl/container_diff_linux_test.go +++ b/cmd/nerdctl/container/container_diff_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_exec.go b/cmd/nerdctl/container/container_exec.go similarity index 98% rename from cmd/nerdctl/container_exec.go rename to cmd/nerdctl/container/container_exec.go index eb559b5515b..4dd596ce54c 100644 --- a/cmd/nerdctl/container_exec.go +++ b/cmd/nerdctl/container/container_exec.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "errors" @@ -32,7 +32,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newExecCommand() *cobra.Command { +func NewExecCommand() *cobra.Command { var execCommand = &cobra.Command{ Use: "exec [flags] CONTAINER COMMAND [ARG...]", Args: cobra.MinimumNArgs(2), diff --git a/cmd/nerdctl/container_exec_linux_test.go b/cmd/nerdctl/container/container_exec_linux_test.go similarity index 99% rename from cmd/nerdctl/container_exec_linux_test.go rename to cmd/nerdctl/container/container_exec_linux_test.go index 38c9a793d49..6e7d5429ede 100644 --- a/cmd/nerdctl/container_exec_linux_test.go +++ b/cmd/nerdctl/container/container_exec_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_exec_test.go b/cmd/nerdctl/container/container_exec_test.go similarity index 99% rename from cmd/nerdctl/container_exec_test.go rename to cmd/nerdctl/container/container_exec_test.go index c952aadb8d2..de58789ab77 100644 --- a/cmd/nerdctl/container_exec_test.go +++ b/cmd/nerdctl/container/container_exec_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "errors" diff --git a/cmd/nerdctl/container_inspect.go b/cmd/nerdctl/container/container_inspect.go similarity index 96% rename from cmd/nerdctl/container_inspect.go rename to cmd/nerdctl/container/container_inspect.go index e0d5ab5e35f..6dae2cbf613 100644 --- a/cmd/nerdctl/container_inspect.go +++ b/cmd/nerdctl/container/container_inspect.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" @@ -57,7 +57,7 @@ var validModeType = map[string]bool{ "dockercompat": true, } -func processContainerInspectOptions(cmd *cobra.Command) (opt types.ContainerInspectOptions, err error) { +func ProcessContainerInspectOptions(cmd *cobra.Command) (opt types.ContainerInspectOptions, err error) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return @@ -90,7 +90,7 @@ func processContainerInspectOptions(cmd *cobra.Command) (opt types.ContainerInsp } func containerInspectAction(cmd *cobra.Command, args []string) error { - opt, err := processContainerInspectOptions(cmd) + opt, err := ProcessContainerInspectOptions(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/container_inspect_linux_test.go b/cmd/nerdctl/container/container_inspect_linux_test.go similarity index 99% rename from cmd/nerdctl/container_inspect_linux_test.go rename to cmd/nerdctl/container/container_inspect_linux_test.go index a1aca0d1a3c..2fadc2b5048 100644 --- a/cmd/nerdctl/container_inspect_linux_test.go +++ b/cmd/nerdctl/container/container_inspect_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_inspect_windows_test.go b/cmd/nerdctl/container/container_inspect_windows_test.go similarity index 99% rename from cmd/nerdctl/container_inspect_windows_test.go rename to cmd/nerdctl/container/container_inspect_windows_test.go index 16c8ec4de36..8feb7fcd52d 100644 --- a/cmd/nerdctl/container_inspect_windows_test.go +++ b/cmd/nerdctl/container/container_inspect_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_kill.go b/cmd/nerdctl/container/container_kill.go similarity index 97% rename from cmd/nerdctl/container_kill.go rename to cmd/nerdctl/container/container_kill.go index dd50a24a8cd..154cec0e23f 100644 --- a/cmd/nerdctl/container_kill.go +++ b/cmd/nerdctl/container/container_kill.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -28,7 +28,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newKillCommand() *cobra.Command { +func NewKillCommand() *cobra.Command { var killCommand = &cobra.Command{ Use: "kill [flags] CONTAINER [CONTAINER, ...]", Short: "Kill one or more running containers", diff --git a/cmd/nerdctl/container_kill_linux_test.go b/cmd/nerdctl/container/container_kill_linux_test.go similarity index 99% rename from cmd/nerdctl/container_kill_linux_test.go rename to cmd/nerdctl/container/container_kill_linux_test.go index 076d8820498..0e7d3fc3f62 100644 --- a/cmd/nerdctl/container_kill_linux_test.go +++ b/cmd/nerdctl/container/container_kill_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_list.go b/cmd/nerdctl/container/container_list.go similarity index 99% rename from cmd/nerdctl/container_list.go rename to cmd/nerdctl/container/container_list.go index d92de87a5de..c9f0d3bd2bb 100644 --- a/cmd/nerdctl/container_list.go +++ b/cmd/nerdctl/container/container_list.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "bytes" @@ -33,7 +33,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/formatter" ) -func newPsCommand() *cobra.Command { +func NewPsCommand() *cobra.Command { var psCommand = &cobra.Command{ Use: "ps", Args: cobra.NoArgs, diff --git a/cmd/nerdctl/container_list_linux_test.go b/cmd/nerdctl/container/container_list_linux_test.go similarity index 99% rename from cmd/nerdctl/container_list_linux_test.go rename to cmd/nerdctl/container/container_list_linux_test.go index a4475e5c0c1..79df967332a 100644 --- a/cmd/nerdctl/container_list_linux_test.go +++ b/cmd/nerdctl/container/container_list_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "errors" diff --git a/cmd/nerdctl/container_list_test.go b/cmd/nerdctl/container/container_list_test.go similarity index 98% rename from cmd/nerdctl/container_list_test.go rename to cmd/nerdctl/container/container_list_test.go index 8b37a999ec0..a5bcd65fec7 100644 --- a/cmd/nerdctl/container_list_test.go +++ b/cmd/nerdctl/container/container_list_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_list_windows_test.go b/cmd/nerdctl/container/container_list_windows_test.go similarity index 99% rename from cmd/nerdctl/container_list_windows_test.go rename to cmd/nerdctl/container/container_list_windows_test.go index 8ad0c7ea5ef..b9559a791b8 100644 --- a/cmd/nerdctl/container_list_windows_test.go +++ b/cmd/nerdctl/container/container_list_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_logs.go b/cmd/nerdctl/container/container_logs.go similarity index 98% rename from cmd/nerdctl/container_logs.go rename to cmd/nerdctl/container/container_logs.go index 9a14d942e6d..910cbeffa03 100644 --- a/cmd/nerdctl/container_logs.go +++ b/cmd/nerdctl/container/container_logs.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" @@ -29,7 +29,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newLogsCommand() *cobra.Command { +func NewLogsCommand() *cobra.Command { const shortUsage = "Fetch the logs of a container. Expected to be used with 'nerdctl run -d'." const longUsage = `Fetch the logs of a container. diff --git a/cmd/nerdctl/container_logs_test.go b/cmd/nerdctl/container/container_logs_test.go similarity index 99% rename from cmd/nerdctl/container_logs_test.go rename to cmd/nerdctl/container/container_logs_test.go index 7f6db3831ab..ec9fbd2ce70 100644 --- a/cmd/nerdctl/container_logs_test.go +++ b/cmd/nerdctl/container/container_logs_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_pause.go b/cmd/nerdctl/container/container_pause.go similarity index 97% rename from cmd/nerdctl/container_pause.go rename to cmd/nerdctl/container/container_pause.go index cf652d51703..338652f8d96 100644 --- a/cmd/nerdctl/container_pause.go +++ b/cmd/nerdctl/container/container_pause.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -28,7 +28,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newPauseCommand() *cobra.Command { +func NewPauseCommand() *cobra.Command { var pauseCommand = &cobra.Command{ Use: "pause [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/container_port.go b/cmd/nerdctl/container/container_port.go similarity index 98% rename from cmd/nerdctl/container_port.go rename to cmd/nerdctl/container/container_port.go index 8c35bfc75e8..1b618be020b 100644 --- a/cmd/nerdctl/container_port.go +++ b/cmd/nerdctl/container/container_port.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "context" @@ -31,7 +31,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" ) -func newPortCommand() *cobra.Command { +func NewPortCommand() *cobra.Command { var portCommand = &cobra.Command{ Use: "port [flags] CONTAINER [PRIVATE_PORT[/PROTO]]", Args: cobra.RangeArgs(1, 2), diff --git a/cmd/nerdctl/container_prune.go b/cmd/nerdctl/container/container_prune.go similarity index 99% rename from cmd/nerdctl/container_prune.go rename to cmd/nerdctl/container/container_prune.go index 960542157d5..79ce0d8bb56 100644 --- a/cmd/nerdctl/container_prune.go +++ b/cmd/nerdctl/container/container_prune.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/container_prune_linux_test.go b/cmd/nerdctl/container/container_prune_linux_test.go similarity index 98% rename from cmd/nerdctl/container_prune_linux_test.go rename to cmd/nerdctl/container/container_prune_linux_test.go index 47560af3acb..8912e8fb8dd 100644 --- a/cmd/nerdctl/container_prune_linux_test.go +++ b/cmd/nerdctl/container/container_prune_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_remove.go b/cmd/nerdctl/container/container_remove.go similarity index 97% rename from cmd/nerdctl/container_remove.go rename to cmd/nerdctl/container/container_remove.go index bf2962bd87e..fd50457a179 100644 --- a/cmd/nerdctl/container_remove.go +++ b/cmd/nerdctl/container/container_remove.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -26,7 +26,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newRmCommand() *cobra.Command { +func NewRmCommand() *cobra.Command { var rmCommand = &cobra.Command{ Use: "rm [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/container_remove_linux_test.go b/cmd/nerdctl/container/container_remove_linux_test.go similarity index 98% rename from cmd/nerdctl/container_remove_linux_test.go rename to cmd/nerdctl/container/container_remove_linux_test.go index 71a060f2d41..6a304b80ebf 100644 --- a/cmd/nerdctl/container_remove_linux_test.go +++ b/cmd/nerdctl/container/container_remove_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_remove_windows_test.go b/cmd/nerdctl/container/container_remove_windows_test.go similarity index 99% rename from cmd/nerdctl/container_remove_windows_test.go rename to cmd/nerdctl/container/container_remove_windows_test.go index 7f113729000..f3b1a73f640 100644 --- a/cmd/nerdctl/container_remove_windows_test.go +++ b/cmd/nerdctl/container/container_remove_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_rename.go b/cmd/nerdctl/container/container_rename.go similarity index 97% rename from cmd/nerdctl/container_rename.go rename to cmd/nerdctl/container/container_rename.go index d70ea215960..46b48aae1ed 100644 --- a/cmd/nerdctl/container_rename.go +++ b/cmd/nerdctl/container/container_rename.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -26,7 +26,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newRenameCommand() *cobra.Command { +func NewRenameCommand() *cobra.Command { var renameCommand = &cobra.Command{ Use: "rename [flags] CONTAINER NEW_NAME", Args: helpers.IsExactArgs(2), diff --git a/cmd/nerdctl/container_rename_linux_test.go b/cmd/nerdctl/container/container_rename_linux_test.go similarity index 99% rename from cmd/nerdctl/container_rename_linux_test.go rename to cmd/nerdctl/container/container_rename_linux_test.go index ae48b82f84f..9018cc429dd 100644 --- a/cmd/nerdctl/container_rename_linux_test.go +++ b/cmd/nerdctl/container/container_rename_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_rename_windows_test.go b/cmd/nerdctl/container/container_rename_windows_test.go similarity index 99% rename from cmd/nerdctl/container_rename_windows_test.go rename to cmd/nerdctl/container/container_rename_windows_test.go index 698f6bf004f..6ebd2796049 100644 --- a/cmd/nerdctl/container_rename_windows_test.go +++ b/cmd/nerdctl/container/container_rename_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_restart.go b/cmd/nerdctl/container/container_restart.go similarity index 97% rename from cmd/nerdctl/container_restart.go rename to cmd/nerdctl/container/container_restart.go index a29ac4dac1f..b1875a77853 100644 --- a/cmd/nerdctl/container_restart.go +++ b/cmd/nerdctl/container/container_restart.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "time" @@ -27,7 +27,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newRestartCommand() *cobra.Command { +func NewRestartCommand() *cobra.Command { var restartCommand = &cobra.Command{ Use: "restart [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/container_restart_linux_test.go b/cmd/nerdctl/container/container_restart_linux_test.go similarity index 99% rename from cmd/nerdctl/container_restart_linux_test.go rename to cmd/nerdctl/container/container_restart_linux_test.go index dddaef2f40b..cd9f7754473 100644 --- a/cmd/nerdctl/container_restart_linux_test.go +++ b/cmd/nerdctl/container/container_restart_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_run.go b/cmd/nerdctl/container/container_run.go similarity index 99% rename from cmd/nerdctl/container_run.go rename to cmd/nerdctl/container/container_run.go index c069dbb1c2d..143cd16d99f 100644 --- a/cmd/nerdctl/container_run.go +++ b/cmd/nerdctl/container/container_run.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "errors" @@ -47,7 +47,7 @@ const ( tiniInitBinary = "tini" ) -func newRunCommand() *cobra.Command { +func NewRunCommand() *cobra.Command { shortHelp := "Run a command in a new container. Optionally specify \"ipfs://\" or \"ipns://\" scheme to pull image from IPFS." longHelp := shortHelp switch runtime.GOOS { diff --git a/cmd/nerdctl/container_run_cgroup_linux_test.go b/cmd/nerdctl/container/container_run_cgroup_linux_test.go similarity index 99% rename from cmd/nerdctl/container_run_cgroup_linux_test.go rename to cmd/nerdctl/container/container_run_cgroup_linux_test.go index 43c491dce55..a856bb5f732 100644 --- a/cmd/nerdctl/container_run_cgroup_linux_test.go +++ b/cmd/nerdctl/container/container_run_cgroup_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "bytes" diff --git a/cmd/nerdctl/container_run_freebsd.go b/cmd/nerdctl/container/container_run_freebsd.go similarity index 98% rename from cmd/nerdctl/container_run_freebsd.go rename to cmd/nerdctl/container/container_run_freebsd.go index e93f88cba9f..fa3c4ec5782 100644 --- a/cmd/nerdctl/container_run_freebsd.go +++ b/cmd/nerdctl/container/container_run_freebsd.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/container_run_gpus_test.go b/cmd/nerdctl/container/container_run_gpus_test.go similarity index 98% rename from cmd/nerdctl/container_run_gpus_test.go rename to cmd/nerdctl/container/container_run_gpus_test.go index fea180b732b..820acd8637e 100644 --- a/cmd/nerdctl/container_run_gpus_test.go +++ b/cmd/nerdctl/container/container_run_gpus_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_run_linux.go b/cmd/nerdctl/container/container_run_linux.go similarity index 98% rename from cmd/nerdctl/container_run_linux.go rename to cmd/nerdctl/container/container_run_linux.go index 92dace222b0..5c188aa3a25 100644 --- a/cmd/nerdctl/container_run_linux.go +++ b/cmd/nerdctl/container/container_run_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "strings" diff --git a/cmd/nerdctl/container_run_linux_test.go b/cmd/nerdctl/container/container_run_linux_test.go similarity index 99% rename from cmd/nerdctl/container_run_linux_test.go rename to cmd/nerdctl/container/container_run_linux_test.go index 04b7b851a1d..2d114e93ddb 100644 --- a/cmd/nerdctl/container_run_linux_test.go +++ b/cmd/nerdctl/container/container_run_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "bufio" diff --git a/cmd/nerdctl/container_run_log_driver_syslog_test.go b/cmd/nerdctl/container/container_run_log_driver_syslog_test.go similarity index 99% rename from cmd/nerdctl/container_run_log_driver_syslog_test.go rename to cmd/nerdctl/container/container_run_log_driver_syslog_test.go index 7e836c61149..36bf6c046d5 100644 --- a/cmd/nerdctl/container_run_log_driver_syslog_test.go +++ b/cmd/nerdctl/container/container_run_log_driver_syslog_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_run_mount_linux_test.go b/cmd/nerdctl/container/container_run_mount_linux_test.go similarity index 99% rename from cmd/nerdctl/container_run_mount_linux_test.go rename to cmd/nerdctl/container/container_run_mount_linux_test.go index ab382c7cf5f..3f4c1972ee9 100644 --- a/cmd/nerdctl/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container/container_run_mount_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_run_mount_windows_test.go b/cmd/nerdctl/container/container_run_mount_windows_test.go similarity index 99% rename from cmd/nerdctl/container_run_mount_windows_test.go rename to cmd/nerdctl/container/container_run_mount_windows_test.go index 3ad3f9506f9..b0e6afde18a 100644 --- a/cmd/nerdctl/container_run_mount_windows_test.go +++ b/cmd/nerdctl/container/container_run_mount_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_run_network.go b/cmd/nerdctl/container/container_run_network.go similarity index 99% rename from cmd/nerdctl/container_run_network.go rename to cmd/nerdctl/container/container_run_network.go index 178d277232a..f731a53aaef 100644 --- a/cmd/nerdctl/container_run_network.go +++ b/cmd/nerdctl/container/container_run_network.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "net" diff --git a/cmd/nerdctl/container_run_network_base_test.go b/cmd/nerdctl/container/container_run_network_base_test.go similarity index 99% rename from cmd/nerdctl/container_run_network_base_test.go rename to cmd/nerdctl/container/container_run_network_base_test.go index e6f5c112ca7..4e75448975b 100644 --- a/cmd/nerdctl/container_run_network_base_test.go +++ b/cmd/nerdctl/container/container_run_network_base_test.go @@ -16,7 +16,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_run_network_linux_test.go b/cmd/nerdctl/container/container_run_network_linux_test.go similarity index 99% rename from cmd/nerdctl/container_run_network_linux_test.go rename to cmd/nerdctl/container/container_run_network_linux_test.go index a9420fcfaca..8a21e54b5a1 100644 --- a/cmd/nerdctl/container_run_network_linux_test.go +++ b/cmd/nerdctl/container/container_run_network_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_run_network_windows_test.go b/cmd/nerdctl/container/container_run_network_windows_test.go similarity index 99% rename from cmd/nerdctl/container_run_network_windows_test.go rename to cmd/nerdctl/container/container_run_network_windows_test.go index e8c42559ad8..9cd8430e5d3 100644 --- a/cmd/nerdctl/container_run_network_windows_test.go +++ b/cmd/nerdctl/container/container_run_network_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_run_restart_linux_test.go b/cmd/nerdctl/container/container_run_restart_linux_test.go similarity index 99% rename from cmd/nerdctl/container_run_restart_linux_test.go rename to cmd/nerdctl/container/container_run_restart_linux_test.go index 6aeb08613b6..c3411c6aaeb 100644 --- a/cmd/nerdctl/container_run_restart_linux_test.go +++ b/cmd/nerdctl/container/container_run_restart_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_run_runtime_linux_test.go b/cmd/nerdctl/container/container_run_runtime_linux_test.go similarity index 98% rename from cmd/nerdctl/container_run_runtime_linux_test.go rename to cmd/nerdctl/container/container_run_runtime_linux_test.go index 90c61594009..ea7473f2d20 100644 --- a/cmd/nerdctl/container_run_runtime_linux_test.go +++ b/cmd/nerdctl/container/container_run_runtime_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_run_security_linux_test.go b/cmd/nerdctl/container/container_run_security_linux_test.go similarity index 99% rename from cmd/nerdctl/container_run_security_linux_test.go rename to cmd/nerdctl/container/container_run_security_linux_test.go index be1191f1d1e..aa0775bbf9c 100644 --- a/cmd/nerdctl/container_run_security_linux_test.go +++ b/cmd/nerdctl/container/container_run_security_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_run_soci_linux_test.go b/cmd/nerdctl/container/container_run_soci_linux_test.go similarity index 99% rename from cmd/nerdctl/container_run_soci_linux_test.go rename to cmd/nerdctl/container/container_run_soci_linux_test.go index a8085164168..57cf0599525 100644 --- a/cmd/nerdctl/container_run_soci_linux_test.go +++ b/cmd/nerdctl/container/container_run_soci_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "os/exec" diff --git a/cmd/nerdctl/container_run_stargz_linux_test.go b/cmd/nerdctl/container/container_run_stargz_linux_test.go similarity index 98% rename from cmd/nerdctl/container_run_stargz_linux_test.go rename to cmd/nerdctl/container/container_run_stargz_linux_test.go index 2b8a79ad975..70e3b0c7d55 100644 --- a/cmd/nerdctl/container_run_stargz_linux_test.go +++ b/cmd/nerdctl/container/container_run_stargz_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "runtime" diff --git a/cmd/nerdctl/container_run_systemd_linux_test.go b/cmd/nerdctl/container/container_run_systemd_linux_test.go similarity index 99% rename from cmd/nerdctl/container_run_systemd_linux_test.go rename to cmd/nerdctl/container/container_run_systemd_linux_test.go index e1757c3950b..065e450873c 100644 --- a/cmd/nerdctl/container_run_systemd_linux_test.go +++ b/cmd/nerdctl/container/container_run_systemd_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_run_test.go b/cmd/nerdctl/container/container_run_test.go similarity index 99% rename from cmd/nerdctl/container_run_test.go rename to cmd/nerdctl/container/container_run_test.go index d1ece634eed..8d64226198c 100644 --- a/cmd/nerdctl/container_run_test.go +++ b/cmd/nerdctl/container/container_run_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "bufio" diff --git a/cmd/nerdctl/container_run_user_linux_test.go b/cmd/nerdctl/container/container_run_user_linux_test.go similarity index 99% rename from cmd/nerdctl/container_run_user_linux_test.go rename to cmd/nerdctl/container/container_run_user_linux_test.go index 114ba251d00..73d1753a867 100644 --- a/cmd/nerdctl/container_run_user_linux_test.go +++ b/cmd/nerdctl/container/container_run_user_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_run_user_windows_test.go b/cmd/nerdctl/container/container_run_user_windows_test.go similarity index 98% rename from cmd/nerdctl/container_run_user_windows_test.go rename to cmd/nerdctl/container/container_run_user_windows_test.go index d6e45171680..e92dc595598 100644 --- a/cmd/nerdctl/container_run_user_windows_test.go +++ b/cmd/nerdctl/container/container_run_user_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_run_verify_linux_test.go b/cmd/nerdctl/container/container_run_verify_linux_test.go similarity index 99% rename from cmd/nerdctl/container_run_verify_linux_test.go rename to cmd/nerdctl/container/container_run_verify_linux_test.go index bb3556b7da6..7d12342cbb3 100644 --- a/cmd/nerdctl/container_run_verify_linux_test.go +++ b/cmd/nerdctl/container/container_run_verify_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_run_windows.go b/cmd/nerdctl/container/container_run_windows.go similarity index 98% rename from cmd/nerdctl/container_run_windows.go rename to cmd/nerdctl/container/container_run_windows.go index e93f88cba9f..fa3c4ec5782 100644 --- a/cmd/nerdctl/container_run_windows.go +++ b/cmd/nerdctl/container/container_run_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/container_run_windows_test.go b/cmd/nerdctl/container/container_run_windows_test.go similarity index 99% rename from cmd/nerdctl/container_run_windows_test.go rename to cmd/nerdctl/container/container_run_windows_test.go index d3af8a6534f..c7ec6e72aa1 100644 --- a/cmd/nerdctl/container_run_windows_test.go +++ b/cmd/nerdctl/container/container_run_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "bytes" diff --git a/cmd/nerdctl/container_start.go b/cmd/nerdctl/container/container_start.go similarity index 98% rename from cmd/nerdctl/container_start.go rename to cmd/nerdctl/container/container_start.go index 9a2443d0aa2..1bf361b8e6a 100644 --- a/cmd/nerdctl/container_start.go +++ b/cmd/nerdctl/container/container_start.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -29,7 +29,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/consoleutil" ) -func newStartCommand() *cobra.Command { +func NewStartCommand() *cobra.Command { var startCommand = &cobra.Command{ Use: "start [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/container_start_linux_test.go b/cmd/nerdctl/container/container_start_linux_test.go similarity index 99% rename from cmd/nerdctl/container_start_linux_test.go rename to cmd/nerdctl/container/container_start_linux_test.go index 91df7a1b9cb..4fe6f2d249c 100644 --- a/cmd/nerdctl/container_start_linux_test.go +++ b/cmd/nerdctl/container/container_start_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "bytes" diff --git a/cmd/nerdctl/container_start_test.go b/cmd/nerdctl/container/container_start_test.go similarity index 98% rename from cmd/nerdctl/container_start_test.go rename to cmd/nerdctl/container/container_start_test.go index 374ee77c821..60369433d24 100644 --- a/cmd/nerdctl/container_start_test.go +++ b/cmd/nerdctl/container/container_start_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "runtime" diff --git a/cmd/nerdctl/container_stats.go b/cmd/nerdctl/container/container_stats.go similarity index 98% rename from cmd/nerdctl/container_stats.go rename to cmd/nerdctl/container/container_stats.go index 985ac9cef5b..10b927a750b 100644 --- a/cmd/nerdctl/container_stats.go +++ b/cmd/nerdctl/container/container_stats.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -28,7 +28,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newStatsCommand() *cobra.Command { +func NewStatsCommand() *cobra.Command { var statsCommand = &cobra.Command{ Use: "stats", Short: "Display a live stream of container(s) resource usage statistics.", diff --git a/cmd/nerdctl/container_stats_linux_test.go b/cmd/nerdctl/container/container_stats_linux_test.go similarity index 99% rename from cmd/nerdctl/container_stats_linux_test.go rename to cmd/nerdctl/container/container_stats_linux_test.go index 6cd7ca3aaf8..5ea2017d949 100644 --- a/cmd/nerdctl/container_stats_linux_test.go +++ b/cmd/nerdctl/container/container_stats_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container_stop.go b/cmd/nerdctl/container/container_stop.go similarity index 97% rename from cmd/nerdctl/container_stop.go rename to cmd/nerdctl/container/container_stop.go index d35458d09ca..cbc533b801f 100644 --- a/cmd/nerdctl/container_stop.go +++ b/cmd/nerdctl/container/container_stop.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "time" @@ -30,7 +30,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newStopCommand() *cobra.Command { +func NewStopCommand() *cobra.Command { var stopCommand = &cobra.Command{ Use: "stop [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/container_stop_linux_test.go b/cmd/nerdctl/container/container_stop_linux_test.go similarity index 99% rename from cmd/nerdctl/container_stop_linux_test.go rename to cmd/nerdctl/container/container_stop_linux_test.go index fedd791fabd..2c0e0bc2bea 100644 --- a/cmd/nerdctl/container_stop_linux_test.go +++ b/cmd/nerdctl/container/container_stop_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/container/container_test.go b/cmd/nerdctl/container/container_test.go new file mode 100644 index 00000000000..dcd08829fcd --- /dev/null +++ b/cmd/nerdctl/container/container_test.go @@ -0,0 +1,27 @@ +/* + 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 container + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/container_top.go b/cmd/nerdctl/container/container_top.go similarity index 97% rename from cmd/nerdctl/container_top.go rename to cmd/nerdctl/container/container_top.go index bc22587287c..0f20e45a2c0 100644 --- a/cmd/nerdctl/container_top.go +++ b/cmd/nerdctl/container/container_top.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "errors" @@ -33,7 +33,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) -func newTopCommand() *cobra.Command { +func NewTopCommand() *cobra.Command { var topCommand = &cobra.Command{ Use: "top CONTAINER [ps OPTIONS]", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/container_top_unix_test.go b/cmd/nerdctl/container/container_top_unix_test.go similarity index 98% rename from cmd/nerdctl/container_top_unix_test.go rename to cmd/nerdctl/container/container_top_unix_test.go index 3e22f6f11db..d68d42302ee 100644 --- a/cmd/nerdctl/container_top_unix_test.go +++ b/cmd/nerdctl/container/container_top_unix_test.go @@ -16,7 +16,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_top_windows_test.go b/cmd/nerdctl/container/container_top_windows_test.go similarity index 98% rename from cmd/nerdctl/container_top_windows_test.go rename to cmd/nerdctl/container/container_top_windows_test.go index 93d9616ce83..690e52d50f4 100644 --- a/cmd/nerdctl/container_top_windows_test.go +++ b/cmd/nerdctl/container/container_top_windows_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/container_unpause.go b/cmd/nerdctl/container/container_unpause.go similarity index 97% rename from cmd/nerdctl/container_unpause.go rename to cmd/nerdctl/container/container_unpause.go index aaa72ce1475..8d835c9388e 100644 --- a/cmd/nerdctl/container_unpause.go +++ b/cmd/nerdctl/container/container_unpause.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -28,7 +28,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newUnpauseCommand() *cobra.Command { +func NewUnpauseCommand() *cobra.Command { var unpauseCommand = &cobra.Command{ Use: "unpause [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/container_update.go b/cmd/nerdctl/container/container_update.go similarity index 99% rename from cmd/nerdctl/container_update.go rename to cmd/nerdctl/container/container_update.go index 3ca9f9a030c..15c8e6526ef 100644 --- a/cmd/nerdctl/container_update.go +++ b/cmd/nerdctl/container/container_update.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "context" @@ -56,7 +56,7 @@ type updateResourceOptions struct { BlkioWeight uint16 } -func newUpdateCommand() *cobra.Command { +func NewUpdateCommand() *cobra.Command { var updateCommand = &cobra.Command{ Use: "update [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/container_wait.go b/cmd/nerdctl/container/container_wait.go similarity index 97% rename from cmd/nerdctl/container_wait.go rename to cmd/nerdctl/container/container_wait.go index b9af63c37ed..c28168b090d 100644 --- a/cmd/nerdctl/container_wait.go +++ b/cmd/nerdctl/container/container_wait.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "github.com/spf13/cobra" @@ -28,7 +28,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" ) -func newWaitCommand() *cobra.Command { +func NewWaitCommand() *cobra.Command { var waitCommand = &cobra.Command{ Use: "wait [flags] CONTAINER [CONTAINER, ...]", Args: cobra.MinimumNArgs(1), diff --git a/cmd/nerdctl/container_wait_test.go b/cmd/nerdctl/container/container_wait_test.go similarity index 98% rename from cmd/nerdctl/container_wait_test.go rename to cmd/nerdctl/container/container_wait_test.go index d2048dd6618..d6a3203480a 100644 --- a/cmd/nerdctl/container_wait_test.go +++ b/cmd/nerdctl/container/container_wait_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "testing" diff --git a/cmd/nerdctl/helpers/cobra.go b/cmd/nerdctl/helpers/cobra.go index b41c851bb77..eff14e69d99 100644 --- a/cmd/nerdctl/helpers/cobra.go +++ b/cmd/nerdctl/helpers/cobra.go @@ -24,6 +24,7 @@ import ( "time" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/containerd/log" ) @@ -138,3 +139,26 @@ func AddDurationFlag(cmd *cobra.Command, name string, aliases []string, value ti } } } + +func GlobalFlags(cmd *cobra.Command) (string, []string) { + args0, err := os.Executable() + if err != nil { + log.L.WithError(err).Warnf("cannot call os.Executable(), assuming the executable to be %q", os.Args[0]) + args0 = os.Args[0] + } + if len(os.Args) < 2 { + return args0, nil + } + + rootCmd := cmd.Root() + flagSet := rootCmd.Flags() + args := []string{} + flagSet.VisitAll(func(f *pflag.Flag) { + key := f.Name + val := f.Value.String() + if f.Changed { + args = append(args, "--"+key+"="+val) + } + }) + return args0, args +} diff --git a/cmd/nerdctl/inspect.go b/cmd/nerdctl/inspect.go index c9cf64c6949..751c2302475 100644 --- a/cmd/nerdctl/inspect.go +++ b/cmd/nerdctl/inspect.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/cobra" "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" + containerCmd "github.com/containerd/nerdctl/v2/cmd/nerdctl/container" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" imageCmd "github.com/containerd/nerdctl/v2/cmd/nerdctl/image" "github.com/containerd/nerdctl/v2/pkg/api/types" @@ -122,7 +123,7 @@ func inspectAction(cmd *cobra.Command, args []string) error { } } if inspectContainer { - containerInspectOptions, err = processContainerInspectOptions(cmd) + containerInspectOptions, err = containerCmd.ProcessContainerInspectOptions(cmd) if err != nil { return err } diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index f02d8867b0e..f08863d9aae 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -33,6 +33,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/builder" "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/container" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/cmd/nerdctl/image" "github.com/containerd/nerdctl/v2/cmd/nerdctl/internal" @@ -243,29 +244,29 @@ Config file ($NERDCTL_TOML): %s } rootCmd.RunE = helpers.UnknownSubcommandAction rootCmd.AddCommand( - newCreateCommand(), + container.NewCreateCommand(), // #region Run & Exec - newRunCommand(), - newUpdateCommand(), - newExecCommand(), + container.NewRunCommand(), + container.NewUpdateCommand(), + container.NewExecCommand(), // #endregion // #region Container management - newPsCommand(), - newLogsCommand(), - newPortCommand(), - newStopCommand(), - newStartCommand(), - newDiffCommand(), - newRestartCommand(), - newKillCommand(), - newRmCommand(), - newPauseCommand(), - newUnpauseCommand(), - newCommitCommand(), - newWaitCommand(), - newRenameCommand(), - newAttachCommand(), + container.NewPsCommand(), + container.NewLogsCommand(), + container.NewPortCommand(), + container.NewStopCommand(), + container.NewStartCommand(), + container.NewDiffCommand(), + container.NewRestartCommand(), + container.NewKillCommand(), + container.NewRmCommand(), + container.NewPauseCommand(), + container.NewUnpauseCommand(), + container.NewCommitCommand(), + container.NewWaitCommand(), + container.NewRenameCommand(), + container.NewAttachCommand(), // #endregion // Build @@ -292,11 +293,11 @@ Config file ($NERDCTL_TOML): %s newInspectCommand(), // stats - newTopCommand(), - newStatsCommand(), + container.NewTopCommand(), + container.NewStatsCommand(), // #region helpers.Management - newContainerCommand(), + container.NewContainerCommand(), image.NewImageCommand(), network.NewNetworkCommand(), volume.NewVolumeCommand(), @@ -321,7 +322,7 @@ Config file ($NERDCTL_TOML): %s ipfs.NewIPFSCommand(), ) addApparmorCommand(rootCmd) - addCpCommand(rootCmd) + container.AddCpCommand(rootCmd) // add aliasToBeInherited to subCommand(s) InheritedFlags for _, subCmd := range rootCmd.Commands() { @@ -330,29 +331,6 @@ Config file ($NERDCTL_TOML): %s return rootCmd, nil } -func globalFlags(cmd *cobra.Command) (string, []string) { - args0, err := os.Executable() - if err != nil { - log.L.WithError(err).Warnf("cannot call os.Executable(), assuming the executable to be %q", os.Args[0]) - args0 = os.Args[0] - } - if len(os.Args) < 2 { - return args0, nil - } - - rootCmd := cmd.Root() - flagSet := rootCmd.Flags() - args := []string{} - flagSet.VisitAll(func(f *pflag.Flag) { - key := f.Name - val := f.Value.String() - if f.Changed { - args = append(args, "--"+key+"="+val) - } - }) - return args0, args -} - // AddPersistentStringFlag is similar to AddStringFlag but persistent. // See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". func AddPersistentStringFlag(cmd *cobra.Command, name string, aliases, localAliases, persistentAliases []string, aliasToBeInherited *pflag.FlagSet, value string, env, usage string) { diff --git a/cmd/nerdctl/main_freebsd.go b/cmd/nerdctl/main_freebsd.go index 46880c81e87..391d34cfeed 100644 --- a/cmd/nerdctl/main_freebsd.go +++ b/cmd/nerdctl/main_freebsd.go @@ -27,7 +27,3 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { func addApparmorCommand(rootCmd *cobra.Command) { // NOP } - -func addCpCommand(rootCmd *cobra.Command) { - // NOP -} diff --git a/cmd/nerdctl/main_linux.go b/cmd/nerdctl/main_linux.go index d1dfbeaf615..44694688c61 100644 --- a/cmd/nerdctl/main_linux.go +++ b/cmd/nerdctl/main_linux.go @@ -66,7 +66,3 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { func addApparmorCommand(rootCmd *cobra.Command) { rootCmd.AddCommand(apparmor.NewApparmorCommand()) } - -func addCpCommand(rootCmd *cobra.Command) { - rootCmd.AddCommand(newCpCommand()) -} diff --git a/cmd/nerdctl/main_windows.go b/cmd/nerdctl/main_windows.go index 46880c81e87..391d34cfeed 100644 --- a/cmd/nerdctl/main_windows.go +++ b/cmd/nerdctl/main_windows.go @@ -27,7 +27,3 @@ func appNeedsRootlessParentMain(cmd *cobra.Command, args []string) bool { func addApparmorCommand(rootCmd *cobra.Command) { // NOP } - -func addCpCommand(rootCmd *cobra.Command) { - // NOP -} From 05074f8360c2c1b440b753c225420db94de010c7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 14:03:59 -0700 Subject: [PATCH 0731/1066] Moving cmd compose and inspect to subpackages Signed-off-by: apostasie --- cmd/nerdctl/{ => compose}/compose.go | 6 +-- cmd/nerdctl/{ => compose}/compose_build.go | 2 +- .../{ => compose}/compose_build_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_config.go | 2 +- .../{ => compose}/compose_config_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_cp.go | 2 +- .../{ => compose}/compose_cp_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_create.go | 2 +- .../compose_create_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_down.go | 2 +- .../{ => compose}/compose_down_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_exec.go | 2 +- .../{ => compose}/compose_exec_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_images.go | 2 +- .../compose_images_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_kill.go | 2 +- .../{ => compose}/compose_kill_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_logs.go | 2 +- cmd/nerdctl/{ => compose}/compose_pause.go | 2 +- .../{ => compose}/compose_pause_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_port.go | 2 +- .../{ => compose}/compose_port_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_ps.go | 2 +- .../{ => compose}/compose_ps_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_pull.go | 2 +- .../{ => compose}/compose_pull_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_push.go | 2 +- cmd/nerdctl/{ => compose}/compose_restart.go | 2 +- .../compose_restart_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_rm.go | 2 +- .../{ => compose}/compose_rm_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_run.go | 2 +- .../{ => compose}/compose_run_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_start.go | 2 +- .../{ => compose}/compose_start_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_stop.go | 2 +- .../{ => compose}/compose_stop_linux_test.go | 2 +- cmd/nerdctl/compose/compose_test.go | 27 +++++++++++++ cmd/nerdctl/{ => compose}/compose_top.go | 2 +- .../{ => compose}/compose_top_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_up.go | 2 +- .../{ => compose}/compose_up_linux_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_up_test.go | 2 +- cmd/nerdctl/{ => compose}/compose_version.go | 2 +- .../{ => compose}/compose_version_test.go | 2 +- cmd/nerdctl/helpers/cobra.go | 33 ++++++++++++++++ cmd/nerdctl/{ => inspect}/inspect.go | 4 +- cmd/nerdctl/inspect/inspect_test.go | 27 +++++++++++++ cmd/nerdctl/main.go | 39 ++----------------- 49 files changed, 139 insertions(+), 83 deletions(-) rename cmd/nerdctl/{ => compose}/compose.go (95%) rename cmd/nerdctl/{ => compose}/compose_build.go (99%) rename cmd/nerdctl/{ => compose}/compose_build_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_config.go (99%) rename cmd/nerdctl/{ => compose}/compose_config_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_cp.go (99%) rename cmd/nerdctl/{ => compose}/compose_cp_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_create.go (99%) rename cmd/nerdctl/{ => compose}/compose_create_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_down.go (99%) rename cmd/nerdctl/{ => compose}/compose_down_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_exec.go (99%) rename cmd/nerdctl/{ => compose}/compose_exec_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_images.go (99%) rename cmd/nerdctl/{ => compose}/compose_images_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_kill.go (99%) rename cmd/nerdctl/{ => compose}/compose_kill_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_logs.go (99%) rename cmd/nerdctl/{ => compose}/compose_pause.go (99%) rename cmd/nerdctl/{ => compose}/compose_pause_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_port.go (99%) rename cmd/nerdctl/{ => compose}/compose_port_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_ps.go (99%) rename cmd/nerdctl/{ => compose}/compose_ps_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_pull.go (99%) rename cmd/nerdctl/{ => compose}/compose_pull_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_push.go (99%) rename cmd/nerdctl/{ => compose}/compose_restart.go (99%) rename cmd/nerdctl/{ => compose}/compose_restart_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_rm.go (99%) rename cmd/nerdctl/{ => compose}/compose_rm_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_run.go (99%) rename cmd/nerdctl/{ => compose}/compose_run_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_start.go (99%) rename cmd/nerdctl/{ => compose}/compose_start_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_stop.go (99%) rename cmd/nerdctl/{ => compose}/compose_stop_linux_test.go (99%) create mode 100644 cmd/nerdctl/compose/compose_test.go rename cmd/nerdctl/{ => compose}/compose_top.go (99%) rename cmd/nerdctl/{ => compose}/compose_top_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_up.go (99%) rename cmd/nerdctl/{ => compose}/compose_up_linux_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_up_test.go (99%) rename cmd/nerdctl/{ => compose}/compose_version.go (99%) rename cmd/nerdctl/{ => compose}/compose_version_test.go (98%) rename cmd/nerdctl/{ => inspect}/inspect.go (98%) create mode 100644 cmd/nerdctl/inspect/inspect_test.go diff --git a/cmd/nerdctl/compose.go b/cmd/nerdctl/compose/compose.go similarity index 95% rename from cmd/nerdctl/compose.go rename to cmd/nerdctl/compose/compose.go index 992889bacb7..e85d31755f4 100644 --- a/cmd/nerdctl/compose.go +++ b/cmd/nerdctl/compose/compose.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "github.com/spf13/cobra" @@ -23,7 +23,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/composer" ) -func newComposeCommand() *cobra.Command { +func NewComposeCommand() *cobra.Command { var composeCommand = &cobra.Command{ Use: "compose [flags] COMMAND", Short: "Compose", @@ -33,7 +33,7 @@ func newComposeCommand() *cobra.Command { TraverseChildren: true, // required for global short hands like -f } // `-f` is a nonPersistentAlias, as it conflicts with `nerdctl compose logs --follow` - AddPersistentStringArrayFlag(composeCommand, "file", nil, []string{"f"}, nil, "", "Specify an alternate compose file") + helpers.AddPersistentStringArrayFlag(composeCommand, "file", nil, []string{"f"}, nil, "", "Specify an alternate compose file") composeCommand.PersistentFlags().String("project-directory", "", "Specify an alternate working directory") composeCommand.PersistentFlags().StringP("project-name", "p", "", "Specify an alternate project name") composeCommand.PersistentFlags().String("env-file", "", "Specify an alternate environment file") diff --git a/cmd/nerdctl/compose_build.go b/cmd/nerdctl/compose/compose_build.go similarity index 99% rename from cmd/nerdctl/compose_build.go rename to cmd/nerdctl/compose/compose_build.go index 2c8ad6c34a6..fbd72ff0f39 100644 --- a/cmd/nerdctl/compose_build.go +++ b/cmd/nerdctl/compose/compose_build.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/compose_build_linux_test.go b/cmd/nerdctl/compose/compose_build_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_build_linux_test.go rename to cmd/nerdctl/compose/compose_build_linux_test.go index 69046355e6a..80cc04d4c35 100644 --- a/cmd/nerdctl/compose_build_linux_test.go +++ b/cmd/nerdctl/compose/compose_build_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_config.go b/cmd/nerdctl/compose/compose_config.go similarity index 99% rename from cmd/nerdctl/compose_config.go rename to cmd/nerdctl/compose/compose_config.go index 4467d3f20df..25a3305779f 100644 --- a/cmd/nerdctl/compose_config.go +++ b/cmd/nerdctl/compose/compose_config.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_config_test.go b/cmd/nerdctl/compose/compose_config_test.go similarity index 99% rename from cmd/nerdctl/compose_config_test.go rename to cmd/nerdctl/compose/compose_config_test.go index 415a4c1e7b4..18dd728da5a 100644 --- a/cmd/nerdctl/compose_config_test.go +++ b/cmd/nerdctl/compose/compose_config_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_cp.go b/cmd/nerdctl/compose/compose_cp.go similarity index 99% rename from cmd/nerdctl/compose_cp.go rename to cmd/nerdctl/compose/compose_cp.go index 90e7cb8309e..a35078bc405 100644 --- a/cmd/nerdctl/compose_cp.go +++ b/cmd/nerdctl/compose/compose_cp.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "errors" diff --git a/cmd/nerdctl/compose_cp_linux_test.go b/cmd/nerdctl/compose/compose_cp_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_cp_linux_test.go rename to cmd/nerdctl/compose/compose_cp_linux_test.go index 1ea44db4c23..605210d8946 100644 --- a/cmd/nerdctl/compose_cp_linux_test.go +++ b/cmd/nerdctl/compose/compose_cp_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_create.go b/cmd/nerdctl/compose/compose_create.go similarity index 99% rename from cmd/nerdctl/compose_create.go rename to cmd/nerdctl/compose/compose_create.go index 14a8021460a..211cc4758f9 100644 --- a/cmd/nerdctl/compose_create.go +++ b/cmd/nerdctl/compose/compose_create.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "errors" diff --git a/cmd/nerdctl/compose_create_linux_test.go b/cmd/nerdctl/compose/compose_create_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_create_linux_test.go rename to cmd/nerdctl/compose/compose_create_linux_test.go index 9ad9ea59429..43f2dc40067 100644 --- a/cmd/nerdctl/compose_create_linux_test.go +++ b/cmd/nerdctl/compose/compose_create_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_down.go b/cmd/nerdctl/compose/compose_down.go similarity index 99% rename from cmd/nerdctl/compose_down.go rename to cmd/nerdctl/compose/compose_down.go index 9e29281282f..30552d18947 100644 --- a/cmd/nerdctl/compose_down.go +++ b/cmd/nerdctl/compose/compose_down.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/compose_down_linux_test.go b/cmd/nerdctl/compose/compose_down_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_down_linux_test.go rename to cmd/nerdctl/compose/compose_down_linux_test.go index 7b8a393b523..b995631d6b6 100644 --- a/cmd/nerdctl/compose_down_linux_test.go +++ b/cmd/nerdctl/compose/compose_down_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_exec.go b/cmd/nerdctl/compose/compose_exec.go similarity index 99% rename from cmd/nerdctl/compose_exec.go rename to cmd/nerdctl/compose/compose_exec.go index 36958da83ff..79d5da5bdcb 100644 --- a/cmd/nerdctl/compose_exec.go +++ b/cmd/nerdctl/compose/compose_exec.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "errors" diff --git a/cmd/nerdctl/compose_exec_linux_test.go b/cmd/nerdctl/compose/compose_exec_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_exec_linux_test.go rename to cmd/nerdctl/compose/compose_exec_linux_test.go index 7a1ea165a54..24e0b3a51de 100644 --- a/cmd/nerdctl/compose_exec_linux_test.go +++ b/cmd/nerdctl/compose/compose_exec_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "errors" diff --git a/cmd/nerdctl/compose_images.go b/cmd/nerdctl/compose/compose_images.go similarity index 99% rename from cmd/nerdctl/compose_images.go rename to cmd/nerdctl/compose/compose_images.go index fcb2a373ea0..30212559e1d 100644 --- a/cmd/nerdctl/compose_images.go +++ b/cmd/nerdctl/compose/compose_images.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "context" diff --git a/cmd/nerdctl/compose_images_linux_test.go b/cmd/nerdctl/compose/compose_images_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_images_linux_test.go rename to cmd/nerdctl/compose/compose_images_linux_test.go index dd4ae118b72..f9f7f475186 100644 --- a/cmd/nerdctl/compose_images_linux_test.go +++ b/cmd/nerdctl/compose/compose_images_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "encoding/json" diff --git a/cmd/nerdctl/compose_kill.go b/cmd/nerdctl/compose/compose_kill.go similarity index 99% rename from cmd/nerdctl/compose_kill.go rename to cmd/nerdctl/compose/compose_kill.go index 1166e24a371..b1adcf4c753 100644 --- a/cmd/nerdctl/compose_kill.go +++ b/cmd/nerdctl/compose/compose_kill.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/compose_kill_linux_test.go b/cmd/nerdctl/compose/compose_kill_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_kill_linux_test.go rename to cmd/nerdctl/compose/compose_kill_linux_test.go index 59e95519636..6571950a62e 100644 --- a/cmd/nerdctl/compose_kill_linux_test.go +++ b/cmd/nerdctl/compose/compose_kill_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_logs.go b/cmd/nerdctl/compose/compose_logs.go similarity index 99% rename from cmd/nerdctl/compose_logs.go rename to cmd/nerdctl/compose/compose_logs.go index c038d712866..5a6fd723cc3 100644 --- a/cmd/nerdctl/compose_logs.go +++ b/cmd/nerdctl/compose/compose_logs.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/compose_pause.go b/cmd/nerdctl/compose/compose_pause.go similarity index 99% rename from cmd/nerdctl/compose_pause.go rename to cmd/nerdctl/compose/compose_pause.go index 6250214a269..9fd02bf3fa7 100644 --- a/cmd/nerdctl/compose_pause.go +++ b/cmd/nerdctl/compose/compose_pause.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/compose_pause_linux_test.go b/cmd/nerdctl/compose/compose_pause_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_pause_linux_test.go rename to cmd/nerdctl/compose/compose_pause_linux_test.go index 34c259734c6..381e8686d6b 100644 --- a/cmd/nerdctl/compose_pause_linux_test.go +++ b/cmd/nerdctl/compose/compose_pause_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_port.go b/cmd/nerdctl/compose/compose_port.go similarity index 99% rename from cmd/nerdctl/compose_port.go rename to cmd/nerdctl/compose/compose_port.go index e654f45f9f1..2cbf14b0287 100644 --- a/cmd/nerdctl/compose_port.go +++ b/cmd/nerdctl/compose/compose_port.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_port_linux_test.go b/cmd/nerdctl/compose/compose_port_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_port_linux_test.go rename to cmd/nerdctl/compose/compose_port_linux_test.go index 39eff5c00a9..15946557ad2 100644 --- a/cmd/nerdctl/compose_port_linux_test.go +++ b/cmd/nerdctl/compose/compose_port_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_ps.go b/cmd/nerdctl/compose/compose_ps.go similarity index 99% rename from cmd/nerdctl/compose_ps.go rename to cmd/nerdctl/compose/compose_ps.go index 684428ad8c8..421731f78b7 100644 --- a/cmd/nerdctl/compose_ps.go +++ b/cmd/nerdctl/compose/compose_ps.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "context" diff --git a/cmd/nerdctl/compose_ps_linux_test.go b/cmd/nerdctl/compose/compose_ps_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_ps_linux_test.go rename to cmd/nerdctl/compose/compose_ps_linux_test.go index 5bf8e7a0358..df6f1d3cfe5 100644 --- a/cmd/nerdctl/compose_ps_linux_test.go +++ b/cmd/nerdctl/compose/compose_ps_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "encoding/json" diff --git a/cmd/nerdctl/compose_pull.go b/cmd/nerdctl/compose/compose_pull.go similarity index 99% rename from cmd/nerdctl/compose_pull.go rename to cmd/nerdctl/compose/compose_pull.go index dc90dc17843..9763377d4a5 100644 --- a/cmd/nerdctl/compose_pull.go +++ b/cmd/nerdctl/compose/compose_pull.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/compose_pull_linux_test.go b/cmd/nerdctl/compose/compose_pull_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_pull_linux_test.go rename to cmd/nerdctl/compose/compose_pull_linux_test.go index 0040a4f84d9..64e267baa24 100644 --- a/cmd/nerdctl/compose_pull_linux_test.go +++ b/cmd/nerdctl/compose/compose_pull_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_push.go b/cmd/nerdctl/compose/compose_push.go similarity index 99% rename from cmd/nerdctl/compose_push.go rename to cmd/nerdctl/compose/compose_push.go index 6aca0c64e5a..50063d556e9 100644 --- a/cmd/nerdctl/compose_push.go +++ b/cmd/nerdctl/compose/compose_push.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/compose_restart.go b/cmd/nerdctl/compose/compose_restart.go similarity index 99% rename from cmd/nerdctl/compose_restart.go rename to cmd/nerdctl/compose/compose_restart.go index 170a3fc4b62..0ee3a936cf1 100644 --- a/cmd/nerdctl/compose_restart.go +++ b/cmd/nerdctl/compose/compose_restart.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/compose_restart_linux_test.go b/cmd/nerdctl/compose/compose_restart_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_restart_linux_test.go rename to cmd/nerdctl/compose/compose_restart_linux_test.go index 4b16f136215..6d5fe1fdedc 100644 --- a/cmd/nerdctl/compose_restart_linux_test.go +++ b/cmd/nerdctl/compose/compose_restart_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_rm.go b/cmd/nerdctl/compose/compose_rm.go similarity index 99% rename from cmd/nerdctl/compose_rm.go rename to cmd/nerdctl/compose/compose_rm.go index b0c32b47c1f..d82e345db76 100644 --- a/cmd/nerdctl/compose_rm.go +++ b/cmd/nerdctl/compose/compose_rm.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_rm_linux_test.go b/cmd/nerdctl/compose/compose_rm_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_rm_linux_test.go rename to cmd/nerdctl/compose/compose_rm_linux_test.go index 22ce6f5a487..948ea9e119d 100644 --- a/cmd/nerdctl/compose_rm_linux_test.go +++ b/cmd/nerdctl/compose/compose_rm_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_run.go b/cmd/nerdctl/compose/compose_run.go similarity index 99% rename from cmd/nerdctl/compose_run.go rename to cmd/nerdctl/compose/compose_run.go index 9f1ffa76c0b..afe02895ae0 100644 --- a/cmd/nerdctl/compose_run.go +++ b/cmd/nerdctl/compose/compose_run.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "errors" diff --git a/cmd/nerdctl/compose_run_linux_test.go b/cmd/nerdctl/compose/compose_run_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_run_linux_test.go rename to cmd/nerdctl/compose/compose_run_linux_test.go index e3e3e5ea559..65b36e7ffb6 100644 --- a/cmd/nerdctl/compose_run_linux_test.go +++ b/cmd/nerdctl/compose/compose_run_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_start.go b/cmd/nerdctl/compose/compose_start.go similarity index 99% rename from cmd/nerdctl/compose_start.go rename to cmd/nerdctl/compose/compose_start.go index 08ca46b33da..ce0cde46acc 100644 --- a/cmd/nerdctl/compose_start.go +++ b/cmd/nerdctl/compose/compose_start.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "context" diff --git a/cmd/nerdctl/compose_start_linux_test.go b/cmd/nerdctl/compose/compose_start_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_start_linux_test.go rename to cmd/nerdctl/compose/compose_start_linux_test.go index 79ce8c990a8..11c1581cd92 100644 --- a/cmd/nerdctl/compose_start_linux_test.go +++ b/cmd/nerdctl/compose/compose_start_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_stop.go b/cmd/nerdctl/compose/compose_stop.go similarity index 99% rename from cmd/nerdctl/compose_stop.go rename to cmd/nerdctl/compose/compose_stop.go index 7c769276700..2f3382a9822 100644 --- a/cmd/nerdctl/compose_stop.go +++ b/cmd/nerdctl/compose/compose_stop.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "github.com/spf13/cobra" diff --git a/cmd/nerdctl/compose_stop_linux_test.go b/cmd/nerdctl/compose/compose_stop_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_stop_linux_test.go rename to cmd/nerdctl/compose/compose_stop_linux_test.go index dcb1250e8a5..e10b16ff7b2 100644 --- a/cmd/nerdctl/compose_stop_linux_test.go +++ b/cmd/nerdctl/compose/compose_stop_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose/compose_test.go b/cmd/nerdctl/compose/compose_test.go new file mode 100644 index 00000000000..efcfd184e5b --- /dev/null +++ b/cmd/nerdctl/compose/compose_test.go @@ -0,0 +1,27 @@ +/* + 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 compose + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/compose_top.go b/cmd/nerdctl/compose/compose_top.go similarity index 99% rename from cmd/nerdctl/compose_top.go rename to cmd/nerdctl/compose/compose_top.go index f6466f2329b..0bb8dadccea 100644 --- a/cmd/nerdctl/compose_top.go +++ b/cmd/nerdctl/compose/compose_top.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_top_linux_test.go b/cmd/nerdctl/compose/compose_top_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_top_linux_test.go rename to cmd/nerdctl/compose/compose_top_linux_test.go index 09c01062f03..a0474c51b0b 100644 --- a/cmd/nerdctl/compose_top_linux_test.go +++ b/cmd/nerdctl/compose/compose_top_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_up.go b/cmd/nerdctl/compose/compose_up.go similarity index 99% rename from cmd/nerdctl/compose_up.go rename to cmd/nerdctl/compose/compose_up.go index b0c8fddab5e..f2829ae1e02 100644 --- a/cmd/nerdctl/compose_up.go +++ b/cmd/nerdctl/compose/compose_up.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "errors" diff --git a/cmd/nerdctl/compose_up_linux_test.go b/cmd/nerdctl/compose/compose_up_linux_test.go similarity index 99% rename from cmd/nerdctl/compose_up_linux_test.go rename to cmd/nerdctl/compose/compose_up_linux_test.go index d17df207462..6dbd6b7cf34 100644 --- a/cmd/nerdctl/compose_up_linux_test.go +++ b/cmd/nerdctl/compose/compose_up_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_up_test.go b/cmd/nerdctl/compose/compose_up_test.go similarity index 99% rename from cmd/nerdctl/compose_up_test.go rename to cmd/nerdctl/compose/compose_up_test.go index 1941fef8c1d..63bba829fcf 100644 --- a/cmd/nerdctl/compose_up_test.go +++ b/cmd/nerdctl/compose/compose_up_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_version.go b/cmd/nerdctl/compose/compose_version.go similarity index 99% rename from cmd/nerdctl/compose_version.go rename to cmd/nerdctl/compose/compose_version.go index e847bc1343e..d4a74a4bca0 100644 --- a/cmd/nerdctl/compose_version.go +++ b/cmd/nerdctl/compose/compose_version.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "fmt" diff --git a/cmd/nerdctl/compose_version_test.go b/cmd/nerdctl/compose/compose_version_test.go similarity index 98% rename from cmd/nerdctl/compose_version_test.go rename to cmd/nerdctl/compose/compose_version_test.go index 222d41edd4d..af3028b3d65 100644 --- a/cmd/nerdctl/compose_version_test.go +++ b/cmd/nerdctl/compose/compose_version_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package compose import ( "testing" diff --git a/cmd/nerdctl/helpers/cobra.go b/cmd/nerdctl/helpers/cobra.go index eff14e69d99..4ced476ff8c 100644 --- a/cmd/nerdctl/helpers/cobra.go +++ b/cmd/nerdctl/helpers/cobra.go @@ -162,3 +162,36 @@ func GlobalFlags(cmd *cobra.Command) (string, []string) { }) return args0, args } + +// AddPersistentStringArrayFlag is similar to cmd.Flags().StringArray but supports aliases and env var and persistent. +// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". +func AddPersistentStringArrayFlag(cmd *cobra.Command, name string, aliases, nonPersistentAliases []string, value []string, env string, usage string) { + if env != "" { + usage = fmt.Sprintf("%s [$%s]", usage, env) + } + if envV, ok := os.LookupEnv(env); ok { + value = []string{envV} + } + aliasesUsage := fmt.Sprintf("Alias of --%s", name) + p := new([]string) + flags := cmd.Flags() + for _, a := range nonPersistentAliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + flags.StringArrayVarP(p, a, a, value, aliasesUsage) + } else { + flags.StringArrayVar(p, a, value, aliasesUsage) + } + } + + persistentFlags := cmd.PersistentFlags() + persistentFlags.StringArrayVar(p, name, value, usage) + for _, a := range aliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + persistentFlags.StringArrayVarP(p, a, a, value, aliasesUsage) + } else { + persistentFlags.StringArrayVar(p, a, value, aliasesUsage) + } + } +} diff --git a/cmd/nerdctl/inspect.go b/cmd/nerdctl/inspect/inspect.go similarity index 98% rename from cmd/nerdctl/inspect.go rename to cmd/nerdctl/inspect/inspect.go index 751c2302475..a91624b27f1 100644 --- a/cmd/nerdctl/inspect.go +++ b/cmd/nerdctl/inspect/inspect.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package inspect import ( "context" @@ -34,7 +34,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" ) -func newInspectCommand() *cobra.Command { +func NewInspectCommand() *cobra.Command { var inspectCommand = &cobra.Command{ Use: "inspect", Short: "Return low-level information on objects.", diff --git a/cmd/nerdctl/inspect/inspect_test.go b/cmd/nerdctl/inspect/inspect_test.go new file mode 100644 index 00000000000..18b6d6ffee5 --- /dev/null +++ b/cmd/nerdctl/inspect/inspect_test.go @@ -0,0 +1,27 @@ +/* + 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 inspect + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index f08863d9aae..f62ace3aaa2 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -33,9 +33,11 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/builder" "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/compose" "github.com/containerd/nerdctl/v2/cmd/nerdctl/container" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/cmd/nerdctl/image" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/inspect" "github.com/containerd/nerdctl/v2/cmd/nerdctl/internal" "github.com/containerd/nerdctl/v2/cmd/nerdctl/ipfs" "github.com/containerd/nerdctl/v2/cmd/nerdctl/login" @@ -290,7 +292,7 @@ Config file ($NERDCTL_TOML): %s // #endregion // Inspect - newInspectCommand(), + inspect.NewInspectCommand(), // stats container.NewTopCommand(), @@ -316,7 +318,7 @@ Config file ($NERDCTL_TOML): %s login.NewLogoutCommand(), // Compose - newComposeCommand(), + compose.NewComposeCommand(), // IPFS ipfs.NewIPFSCommand(), @@ -418,36 +420,3 @@ func AddPersistentBoolFlag(cmd *cobra.Command, name string, aliases, nonPersiste } } } - -// AddPersistentStringArrayFlag is similar to cmd.Flags().StringArray but supports aliases and env var and persistent. -// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". -func AddPersistentStringArrayFlag(cmd *cobra.Command, name string, aliases, nonPersistentAliases []string, value []string, env string, usage string) { - if env != "" { - usage = fmt.Sprintf("%s [$%s]", usage, env) - } - if envV, ok := os.LookupEnv(env); ok { - value = []string{envV} - } - aliasesUsage := fmt.Sprintf("Alias of --%s", name) - p := new([]string) - flags := cmd.Flags() - for _, a := range nonPersistentAliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - flags.StringArrayVarP(p, a, a, value, aliasesUsage) - } else { - flags.StringArrayVar(p, a, value, aliasesUsage) - } - } - - persistentFlags := cmd.PersistentFlags() - persistentFlags.StringArrayVar(p, name, value, usage) - for _, a := range aliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - persistentFlags.StringArrayVarP(p, a, a, value, aliasesUsage) - } else { - persistentFlags.StringArrayVar(p, a, value, aliasesUsage) - } - } -} From b02b8f28863932dbb53473e320996beb7c8b249a Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 30 Aug 2024 14:06:21 -0700 Subject: [PATCH 0732/1066] Move cmd/system to subpackage Signed-off-by: apostasie --- .../multi_platform_linux_test.go | 2 +- cmd/nerdctl/main.go | 7 ++--- cmd/nerdctl/{ => system}/system.go | 8 +++--- cmd/nerdctl/{ => system}/system_events.go | 4 +-- .../{ => system}/system_events_linux_test.go | 2 +- cmd/nerdctl/{ => system}/system_info.go | 4 +-- cmd/nerdctl/{ => system}/system_info_test.go | 2 +- cmd/nerdctl/{ => system}/system_prune.go | 2 +- .../{ => system}/system_prune_linux_test.go | 2 +- cmd/nerdctl/system/system_test.go | 27 +++++++++++++++++++ 10 files changed, 44 insertions(+), 16 deletions(-) rename cmd/nerdctl/{ => container}/multi_platform_linux_test.go (99%) rename cmd/nerdctl/{ => system}/system.go (91%) rename cmd/nerdctl/{ => system}/system_events.go (97%) rename cmd/nerdctl/{ => system}/system_events_linux_test.go (99%) rename cmd/nerdctl/{ => system}/system_info.go (98%) rename cmd/nerdctl/{ => system}/system_info_test.go (99%) rename cmd/nerdctl/{ => system}/system_prune.go (99%) rename cmd/nerdctl/{ => system}/system_prune_linux_test.go (99%) create mode 100644 cmd/nerdctl/system/system_test.go diff --git a/cmd/nerdctl/multi_platform_linux_test.go b/cmd/nerdctl/container/multi_platform_linux_test.go similarity index 99% rename from cmd/nerdctl/multi_platform_linux_test.go rename to cmd/nerdctl/container/multi_platform_linux_test.go index 411df72b308..3acb0e3ef87 100644 --- a/cmd/nerdctl/multi_platform_linux_test.go +++ b/cmd/nerdctl/container/multi_platform_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package container import ( "fmt" diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index f62ace3aaa2..86358ad595d 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -43,6 +43,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/login" "github.com/containerd/nerdctl/v2/cmd/nerdctl/namespace" "github.com/containerd/nerdctl/v2/cmd/nerdctl/network" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/system" "github.com/containerd/nerdctl/v2/cmd/nerdctl/volume" "github.com/containerd/nerdctl/v2/pkg/config" ncdefaults "github.com/containerd/nerdctl/v2/pkg/defaults" @@ -286,8 +287,8 @@ Config file ($NERDCTL_TOML): %s // #endregion // #region System - newEventsCommand(), - newInfoCommand(), + system.NewEventsCommand(), + system.NewInfoCommand(), newVersionCommand(), // #endregion @@ -303,7 +304,7 @@ Config file ($NERDCTL_TOML): %s image.NewImageCommand(), network.NewNetworkCommand(), volume.NewVolumeCommand(), - newSystemCommand(), + system.NewSystemCommand(), namespace.NewNamespaceCommand(), builder.NewBuilderCommand(), // #endregion diff --git a/cmd/nerdctl/system.go b/cmd/nerdctl/system/system.go similarity index 91% rename from cmd/nerdctl/system.go rename to cmd/nerdctl/system/system.go index 1119fded332..f4a41aba5ca 100644 --- a/cmd/nerdctl/system.go +++ b/cmd/nerdctl/system/system.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package system import ( "github.com/spf13/cobra" @@ -22,7 +22,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" ) -func newSystemCommand() *cobra.Command { +func NewSystemCommand() *cobra.Command { var systemCommand = &cobra.Command{ Annotations: map[string]string{helpers.Category: helpers.Management}, Use: "system", @@ -33,8 +33,8 @@ func newSystemCommand() *cobra.Command { } // versionCommand is not here systemCommand.AddCommand( - newEventsCommand(), - newInfoCommand(), + NewEventsCommand(), + NewInfoCommand(), newSystemPruneCommand(), ) return systemCommand diff --git a/cmd/nerdctl/system_events.go b/cmd/nerdctl/system/system_events.go similarity index 97% rename from cmd/nerdctl/system_events.go rename to cmd/nerdctl/system/system_events.go index bc4dcfb57f6..69832df35ce 100644 --- a/cmd/nerdctl/system_events.go +++ b/cmd/nerdctl/system/system_events.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package system import ( "github.com/spf13/cobra" @@ -25,7 +25,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/system" ) -func newEventsCommand() *cobra.Command { +func NewEventsCommand() *cobra.Command { shortHelp := `Get real time events from the server` longHelp := shortHelp + "\nNOTE: The output format is not compatible with Docker." var eventsCommand = &cobra.Command{ diff --git a/cmd/nerdctl/system_events_linux_test.go b/cmd/nerdctl/system/system_events_linux_test.go similarity index 99% rename from cmd/nerdctl/system_events_linux_test.go rename to cmd/nerdctl/system/system_events_linux_test.go index 28c442fa595..5838e710866 100644 --- a/cmd/nerdctl/system_events_linux_test.go +++ b/cmd/nerdctl/system/system_events_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package system import ( "fmt" diff --git a/cmd/nerdctl/system_info.go b/cmd/nerdctl/system/system_info.go similarity index 98% rename from cmd/nerdctl/system_info.go rename to cmd/nerdctl/system/system_info.go index 0d461c99a77..10eeed9cd21 100644 --- a/cmd/nerdctl/system_info.go +++ b/cmd/nerdctl/system/system_info.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package system import ( "github.com/spf13/cobra" @@ -25,7 +25,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/system" ) -func newInfoCommand() *cobra.Command { +func NewInfoCommand() *cobra.Command { var infoCommand = &cobra.Command{ Use: "info", Args: cobra.NoArgs, diff --git a/cmd/nerdctl/system_info_test.go b/cmd/nerdctl/system/system_info_test.go similarity index 99% rename from cmd/nerdctl/system_info_test.go rename to cmd/nerdctl/system/system_info_test.go index 7d7ec7a7c19..3a10033930d 100644 --- a/cmd/nerdctl/system_info_test.go +++ b/cmd/nerdctl/system/system_info_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package system import ( "encoding/json" diff --git a/cmd/nerdctl/system_prune.go b/cmd/nerdctl/system/system_prune.go similarity index 99% rename from cmd/nerdctl/system_prune.go rename to cmd/nerdctl/system/system_prune.go index cfe1cb41661..29a43cb187e 100644 --- a/cmd/nerdctl/system_prune.go +++ b/cmd/nerdctl/system/system_prune.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package system import ( "fmt" diff --git a/cmd/nerdctl/system_prune_linux_test.go b/cmd/nerdctl/system/system_prune_linux_test.go similarity index 99% rename from cmd/nerdctl/system_prune_linux_test.go rename to cmd/nerdctl/system/system_prune_linux_test.go index 3070cdde5fb..d792282398f 100644 --- a/cmd/nerdctl/system_prune_linux_test.go +++ b/cmd/nerdctl/system/system_prune_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package system import ( "bytes" diff --git a/cmd/nerdctl/system/system_test.go b/cmd/nerdctl/system/system_test.go new file mode 100644 index 00000000000..2c066490dd6 --- /dev/null +++ b/cmd/nerdctl/system/system_test.go @@ -0,0 +1,27 @@ +/* + 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 system + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} From 4e89ddf70d23b0a5d7aa6ba963dbd174066000a8 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 2 Sep 2024 10:50:56 -0700 Subject: [PATCH 0733/1066] Minor cleanup, post-refactoring of cmd Signed-off-by: apostasie --- cmd/nerdctl/helpers/cobra.go | 88 ++++++++++++++++ cmd/nerdctl/helpers/testing.go | 149 --------------------------- cmd/nerdctl/helpers/testing_linux.go | 146 ++++++++++++++++++++++++++ cmd/nerdctl/main.go | 103 ++---------------- cmd/nerdctl/main_unix.go | 19 ---- 5 files changed, 241 insertions(+), 264 deletions(-) delete mode 100644 cmd/nerdctl/main_unix.go diff --git a/cmd/nerdctl/helpers/cobra.go b/cmd/nerdctl/helpers/cobra.go index 4ced476ff8c..d35030ea8cf 100644 --- a/cmd/nerdctl/helpers/cobra.go +++ b/cmd/nerdctl/helpers/cobra.go @@ -195,3 +195,91 @@ func AddPersistentStringArrayFlag(cmd *cobra.Command, name string, aliases, nonP } } } + +// AddPersistentStringFlag is similar to AddStringFlag but persistent. +// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". +func AddPersistentStringFlag(cmd *cobra.Command, name string, aliases, localAliases, persistentAliases []string, aliasToBeInherited *pflag.FlagSet, value string, env, usage string) { + if env != "" { + usage = fmt.Sprintf("%s [$%s]", usage, env) + } + if envV, ok := os.LookupEnv(env); ok { + value = envV + } + aliasesUsage := fmt.Sprintf("Alias of --%s", name) + p := new(string) + + // flags is full set of flag(s) + // flags can redefine alias already used in subcommands + flags := cmd.Flags() + for _, a := range aliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + flags.StringVarP(p, a, a, value, aliasesUsage) + } else { + flags.StringVar(p, a, value, aliasesUsage) + } + // non-persistent flags are not added to the InheritedFlags, so we should add them manually + f := flags.Lookup(a) + aliasToBeInherited.AddFlag(f) + } + + // localFlags are local to the rootCmd + localFlags := cmd.LocalFlags() + for _, a := range localAliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + localFlags.StringVarP(p, a, a, value, aliasesUsage) + } else { + localFlags.StringVar(p, a, value, aliasesUsage) + } + } + + // persistentFlags cannot redefine alias already used in subcommands + persistentFlags := cmd.PersistentFlags() + persistentFlags.StringVar(p, name, value, usage) + for _, a := range persistentAliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + persistentFlags.StringVarP(p, a, a, value, aliasesUsage) + } else { + persistentFlags.StringVar(p, a, value, aliasesUsage) + } + } +} + +// AddPersistentBoolFlag is similar to AddBoolFlag but persistent. +// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". +func AddPersistentBoolFlag(cmd *cobra.Command, name string, aliases, nonPersistentAliases []string, value bool, env, usage string) { + if env != "" { + usage = fmt.Sprintf("%s [$%s]", usage, env) + } + if envV, ok := os.LookupEnv(env); ok { + var err error + value, err = strconv.ParseBool(envV) + if err != nil { + log.L.WithError(err).Warnf("Invalid boolean value for `%s`", env) + } + } + aliasesUsage := fmt.Sprintf("Alias of --%s", name) + p := new(bool) + flags := cmd.Flags() + for _, a := range nonPersistentAliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + flags.BoolVarP(p, a, a, value, aliasesUsage) + } else { + flags.BoolVar(p, a, value, aliasesUsage) + } + } + + persistentFlags := cmd.PersistentFlags() + persistentFlags.BoolVar(p, name, value, usage) + for _, a := range aliases { + if len(a) == 1 { + // pflag doesn't support short-only flags, so we have to register long one as well here + persistentFlags.BoolVarP(p, a, a, value, aliasesUsage) + } else { + persistentFlags.BoolVar(p, a, value, aliasesUsage) + } + } +} diff --git a/cmd/nerdctl/helpers/testing.go b/cmd/nerdctl/helpers/testing.go index d3197a531a5..a9c633faa13 100644 --- a/cmd/nerdctl/helpers/testing.go +++ b/cmd/nerdctl/helpers/testing.go @@ -17,165 +17,16 @@ package helpers import ( - "context" - "fmt" - "net" "os" - "os/exec" "path/filepath" - "strings" "testing" "gotest.tools/v3/assert" - - containerd "github.com/containerd/containerd/v2/client" - "github.com/containerd/containerd/v2/core/content" - - "github.com/containerd/nerdctl/v2/pkg/buildkitutil" - "github.com/containerd/nerdctl/v2/pkg/testutil" ) -func FindIPv6(output string) net.IP { - var ipv6 string - lines := strings.Split(output, "\n") - for _, line := range lines { - if strings.Contains(line, "inet6") { - fields := strings.Fields(line) - if len(fields) > 1 { - ipv6 = strings.Split(fields[1], "/")[0] - break - } - } - } - return net.ParseIP(ipv6) -} - -func RequiresStargz(base *testutil.Base) { - info := base.Info() - for _, p := range info.Plugins.Storage { - if p == "stargz" { - return - } - } - base.T.Skip("test requires stargz") -} - -type JweKeyPair struct { - Prv string - Pub string - Cleanup func() -} - -func NewJWEKeyPair(t testing.TB) *JweKeyPair { - testutil.RequireExecutable(t, "openssl") - td, err := os.MkdirTemp(t.TempDir(), "jwe-key-pair") - assert.NilError(t, err) - prv := filepath.Join(td, "mykey.pem") - pub := filepath.Join(td, "mypubkey.pem") - cmds := [][]string{ - // Exec openssl commands to ensure that nerdctl is compatible with the output of openssl commands. - // Do NOT refactor this function to use "crypto/rsa" stdlib. - {"openssl", "genrsa", "-out", prv}, - {"openssl", "rsa", "-in", prv, "-pubout", "-out", pub}, - } - for _, f := range cmds { - cmd := exec.Command(f[0], f[1:]...) - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) - } - } - return &JweKeyPair{ - Prv: prv, - Pub: pub, - Cleanup: func() { - _ = os.RemoveAll(td) - }, - } -} - -func RmiAll(base *testutil.Base) { - base.T.Logf("Pruning images") - imageIDs := base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() - // remove empty output line at the end - imageIDs = imageIDs[:len(imageIDs)-1] - // use `Run` on purpose (same below) because `rmi all` may fail on individual - // image id that has an expected running container (e.g. a registry) - base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() - - base.T.Logf("Pruning build caches") - if _, err := buildkitutil.GetBuildkitHost(testutil.Namespace); err == nil { - base.Cmd("builder", "prune", "--force").AssertOK() - } - - // For BuildKit >= 0.11, pruning cache isn't enough to remove manifest blobs that are referred by build history blobs - // https://github.com/containerd/nerdctl/pull/1833 - if base.Target == testutil.Nerdctl { - base.T.Logf("Pruning all content blobs") - addr := base.ContainerdAddress() - client, err := containerd.New(addr, containerd.WithDefaultNamespace(testutil.Namespace)) - assert.NilError(base.T, err) - cs := client.ContentStore() - ctx := context.TODO() - wf := func(info content.Info) error { - base.T.Logf("Pruning blob %+v", info) - if err := cs.Delete(ctx, info.Digest); err != nil { - base.T.Log(err) - } - return nil - } - if err := cs.Walk(ctx, wf); err != nil { - base.T.Log(err) - } - - base.T.Logf("Pruning all images (again?)") - imageIDs = base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() - base.T.Logf("pruning following images: %+v", imageIDs) - base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() - } -} - func CreateBuildContext(t *testing.T, dockerfile string) string { tmpDir := t.TempDir() err := os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644) assert.NilError(t, err) return tmpDir } - -func RequiresSoci(base *testutil.Base) { - info := base.Info() - for _, p := range info.Plugins.Storage { - if p == "soci" { - return - } - } - base.T.Skip("test requires soci") -} - -type CosignKeyPair struct { - PublicKey string - PrivateKey string - Cleanup func() -} - -func NewCosignKeyPair(t testing.TB, path string, password string) *CosignKeyPair { - td, err := os.MkdirTemp(t.TempDir(), path) - assert.NilError(t, err) - - cmd := exec.Command("cosign", "generate-key-pair") - cmd.Dir = td - cmd.Env = append(cmd.Env, fmt.Sprintf("COSIGN_PASSWORD=%s", password)) - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) - } - - publicKey := filepath.Join(td, "cosign.pub") - privateKey := filepath.Join(td, "cosign.key") - - return &CosignKeyPair{ - PublicKey: publicKey, - PrivateKey: privateKey, - Cleanup: func() { - _ = os.RemoveAll(td) - }, - } -} diff --git a/cmd/nerdctl/helpers/testing_linux.go b/cmd/nerdctl/helpers/testing_linux.go index 4aed02384bf..ec638021b11 100644 --- a/cmd/nerdctl/helpers/testing_linux.go +++ b/cmd/nerdctl/helpers/testing_linux.go @@ -17,10 +17,12 @@ package helpers import ( + "context" "encoding/json" "errors" "fmt" "io" + "net" "os" "os/exec" "path/filepath" @@ -28,10 +30,154 @@ import ( "testing" "time" + "gotest.tools/v3/assert" + + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" ) +func FindIPv6(output string) net.IP { + var ipv6 string + lines := strings.Split(output, "\n") + for _, line := range lines { + if strings.Contains(line, "inet6") { + fields := strings.Fields(line) + if len(fields) > 1 { + ipv6 = strings.Split(fields[1], "/")[0] + break + } + } + } + return net.ParseIP(ipv6) +} + +func RequiresStargz(base *testutil.Base) { + info := base.Info() + for _, p := range info.Plugins.Storage { + if p == "stargz" { + return + } + } + base.T.Skip("test requires stargz") +} + +type JweKeyPair struct { + Prv string + Pub string + Cleanup func() +} + +func NewJWEKeyPair(t testing.TB) *JweKeyPair { + testutil.RequireExecutable(t, "openssl") + td, err := os.MkdirTemp(t.TempDir(), "jwe-key-pair") + assert.NilError(t, err) + prv := filepath.Join(td, "mykey.pem") + pub := filepath.Join(td, "mypubkey.pem") + cmds := [][]string{ + // Exec openssl commands to ensure that nerdctl is compatible with the output of openssl commands. + // Do NOT refactor this function to use "crypto/rsa" stdlib. + {"openssl", "genrsa", "-out", prv}, + {"openssl", "rsa", "-in", prv, "-pubout", "-out", pub}, + } + for _, f := range cmds { + cmd := exec.Command(f[0], f[1:]...) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) + } + } + return &JweKeyPair{ + Prv: prv, + Pub: pub, + Cleanup: func() { + _ = os.RemoveAll(td) + }, + } +} + +func RequiresSoci(base *testutil.Base) { + info := base.Info() + for _, p := range info.Plugins.Storage { + if p == "soci" { + return + } + } + base.T.Skip("test requires soci") +} + +type CosignKeyPair struct { + PublicKey string + PrivateKey string + Cleanup func() +} + +func NewCosignKeyPair(t testing.TB, path string, password string) *CosignKeyPair { + td, err := os.MkdirTemp(t.TempDir(), path) + assert.NilError(t, err) + + cmd := exec.Command("cosign", "generate-key-pair") + cmd.Dir = td + cmd.Env = append(cmd.Env, fmt.Sprintf("COSIGN_PASSWORD=%s", password)) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("failed to run %v: %v (%q)", cmd.Args, err, string(out)) + } + + publicKey := filepath.Join(td, "cosign.pub") + privateKey := filepath.Join(td, "cosign.key") + + return &CosignKeyPair{ + PublicKey: publicKey, + PrivateKey: privateKey, + Cleanup: func() { + _ = os.RemoveAll(td) + }, + } +} + +func RmiAll(base *testutil.Base) { + base.T.Logf("Pruning images") + imageIDs := base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() + // remove empty output line at the end + imageIDs = imageIDs[:len(imageIDs)-1] + // use `Run` on purpose (same below) because `rmi all` may fail on individual + // image id that has an expected running container (e.g. a registry) + base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() + + base.T.Logf("Pruning build caches") + if _, err := buildkitutil.GetBuildkitHost(testutil.Namespace); err == nil { + base.Cmd("builder", "prune", "--force").AssertOK() + } + + // For BuildKit >= 0.11, pruning cache isn't enough to remove manifest blobs that are referred by build history blobs + // https://github.com/containerd/nerdctl/pull/1833 + if base.Target == testutil.Nerdctl { + base.T.Logf("Pruning all content blobs") + addr := base.ContainerdAddress() + client, err := containerd.New(addr, containerd.WithDefaultNamespace(testutil.Namespace)) + assert.NilError(base.T, err) + cs := client.ContentStore() + ctx := context.TODO() + wf := func(info content.Info) error { + base.T.Logf("Pruning blob %+v", info) + if err := cs.Delete(ctx, info.Digest); err != nil { + base.T.Log(err) + } + return nil + } + if err := cs.Walk(ctx, wf); err != nil { + base.T.Log(err) + } + + base.T.Logf("Pruning all images (again?)") + imageIDs = base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() + base.T.Logf("pruning following images: %+v", imageIDs) + base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() + } +} + func ComposeUp(t *testing.T, base *testutil.Base, dockerComposeYAML string, opts ...string) { comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 86358ad595d..1e086b910d6 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -21,7 +21,6 @@ import ( "fmt" "os" "runtime" - "strconv" "strings" "github.com/fatih/color" @@ -166,15 +165,15 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, rootCmd.PersistentFlags().Bool("debug", cfg.Debug, "debug mode") rootCmd.PersistentFlags().Bool("debug-full", cfg.DebugFull, "debug mode (with full output)") // -a is aliases (conflicts with nerdctl images -a) - AddPersistentStringFlag(rootCmd, "address", []string{"a", "H"}, nil, []string{"host"}, aliasToBeInherited, cfg.Address, "CONTAINERD_ADDRESS", `containerd address, optionally with "unix://" prefix`) + helpers.AddPersistentStringFlag(rootCmd, "address", []string{"a", "H"}, nil, []string{"host"}, aliasToBeInherited, cfg.Address, "CONTAINERD_ADDRESS", `containerd address, optionally with "unix://" prefix`) // -n is aliases (conflicts with nerdctl logs -n) - AddPersistentStringFlag(rootCmd, "namespace", []string{"n"}, nil, nil, aliasToBeInherited, cfg.Namespace, "CONTAINERD_NAMESPACE", `containerd namespace, such as "moby" for Docker, "k8s.io" for Kubernetes`) + helpers.AddPersistentStringFlag(rootCmd, "namespace", []string{"n"}, nil, nil, aliasToBeInherited, cfg.Namespace, "CONTAINERD_NAMESPACE", `containerd namespace, such as "moby" for Docker, "k8s.io" for Kubernetes`) rootCmd.RegisterFlagCompletionFunc("namespace", completion.NamespaceNames) - AddPersistentStringFlag(rootCmd, "snapshotter", nil, nil, []string{"storage-driver"}, aliasToBeInherited, cfg.Snapshotter, "CONTAINERD_SNAPSHOTTER", "containerd snapshotter") + helpers.AddPersistentStringFlag(rootCmd, "snapshotter", nil, nil, []string{"storage-driver"}, aliasToBeInherited, cfg.Snapshotter, "CONTAINERD_SNAPSHOTTER", "containerd snapshotter") rootCmd.RegisterFlagCompletionFunc("snapshotter", completion.SnapshotterNames) rootCmd.RegisterFlagCompletionFunc("storage-driver", completion.SnapshotterNames) - AddPersistentStringFlag(rootCmd, "cni-path", nil, nil, nil, aliasToBeInherited, cfg.CNIPath, "CNI_PATH", "cni plugins binary directory") - AddPersistentStringFlag(rootCmd, "cni-netconfpath", nil, nil, nil, aliasToBeInherited, cfg.CNINetConfPath, "NETCONFPATH", "cni config directory") + helpers.AddPersistentStringFlag(rootCmd, "cni-path", nil, nil, nil, aliasToBeInherited, cfg.CNIPath, "CNI_PATH", "cni plugins binary directory") + helpers.AddPersistentStringFlag(rootCmd, "cni-netconfpath", nil, nil, nil, aliasToBeInherited, cfg.CNINetConfPath, "NETCONFPATH", "cni config directory") rootCmd.PersistentFlags().String("data-root", cfg.DataRoot, "Root directory of persistent nerdctl state (managed by nerdctl, not by containerd)") rootCmd.PersistentFlags().String("cgroup-manager", cfg.CgroupManager, `Cgroup manager to use ("cgroupfs"|"systemd")`) rootCmd.RegisterFlagCompletionFunc("cgroup-manager", completion.CgroupManagerNames) @@ -182,8 +181,8 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, // hosts-dir is defined as StringSlice, not StringArray, to allow specifying "--hosts-dir=/etc/containerd/certs.d,/etc/docker/certs.d" rootCmd.PersistentFlags().StringSlice("hosts-dir", cfg.HostsDir, "A directory that contains /hosts.toml (containerd style) or /{ca.cert, cert.pem, key.pem} (docker style)") // Experimental enable experimental feature, see in https://github.com/containerd/nerdctl/blob/main/docs/experimental.md - AddPersistentBoolFlag(rootCmd, "experimental", nil, nil, cfg.Experimental, "NERDCTL_EXPERIMENTAL", "Control experimental: https://github.com/containerd/nerdctl/blob/main/docs/experimental.md") - AddPersistentStringFlag(rootCmd, "host-gateway-ip", nil, nil, nil, aliasToBeInherited, cfg.HostGatewayIP, "NERDCTL_HOST_GATEWAY_IP", "IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the host. It has no effect without setting --add-host") + helpers.AddPersistentBoolFlag(rootCmd, "experimental", nil, nil, cfg.Experimental, "NERDCTL_EXPERIMENTAL", "Control experimental: https://github.com/containerd/nerdctl/blob/main/docs/experimental.md") + helpers.AddPersistentStringFlag(rootCmd, "host-gateway-ip", nil, nil, nil, aliasToBeInherited, cfg.HostGatewayIP, "NERDCTL_HOST_GATEWAY_IP", "IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the host. It has no effect without setting --add-host") return aliasToBeInherited, nil } @@ -333,91 +332,3 @@ Config file ($NERDCTL_TOML): %s } return rootCmd, nil } - -// AddPersistentStringFlag is similar to AddStringFlag but persistent. -// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". -func AddPersistentStringFlag(cmd *cobra.Command, name string, aliases, localAliases, persistentAliases []string, aliasToBeInherited *pflag.FlagSet, value string, env, usage string) { - if env != "" { - usage = fmt.Sprintf("%s [$%s]", usage, env) - } - if envV, ok := os.LookupEnv(env); ok { - value = envV - } - aliasesUsage := fmt.Sprintf("Alias of --%s", name) - p := new(string) - - // flags is full set of flag(s) - // flags can redefine alias already used in subcommands - flags := cmd.Flags() - for _, a := range aliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - flags.StringVarP(p, a, a, value, aliasesUsage) - } else { - flags.StringVar(p, a, value, aliasesUsage) - } - // non-persistent flags are not added to the InheritedFlags, so we should add them manually - f := flags.Lookup(a) - aliasToBeInherited.AddFlag(f) - } - - // localFlags are local to the rootCmd - localFlags := cmd.LocalFlags() - for _, a := range localAliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - localFlags.StringVarP(p, a, a, value, aliasesUsage) - } else { - localFlags.StringVar(p, a, value, aliasesUsage) - } - } - - // persistentFlags cannot redefine alias already used in subcommands - persistentFlags := cmd.PersistentFlags() - persistentFlags.StringVar(p, name, value, usage) - for _, a := range persistentAliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - persistentFlags.StringVarP(p, a, a, value, aliasesUsage) - } else { - persistentFlags.StringVar(p, a, value, aliasesUsage) - } - } -} - -// AddPersistentBoolFlag is similar to AddBoolFlag but persistent. -// See https://github.com/spf13/cobra/blob/main/user_guide.md#persistent-flags to learn what is "persistent". -func AddPersistentBoolFlag(cmd *cobra.Command, name string, aliases, nonPersistentAliases []string, value bool, env, usage string) { - if env != "" { - usage = fmt.Sprintf("%s [$%s]", usage, env) - } - if envV, ok := os.LookupEnv(env); ok { - var err error - value, err = strconv.ParseBool(envV) - if err != nil { - log.L.WithError(err).Warnf("Invalid boolean value for `%s`", env) - } - } - aliasesUsage := fmt.Sprintf("Alias of --%s", name) - p := new(bool) - flags := cmd.Flags() - for _, a := range nonPersistentAliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - flags.BoolVarP(p, a, a, value, aliasesUsage) - } else { - flags.BoolVar(p, a, value, aliasesUsage) - } - } - - persistentFlags := cmd.PersistentFlags() - persistentFlags.BoolVar(p, name, value, usage) - for _, a := range aliases { - if len(a) == 1 { - // pflag doesn't support short-only flags, so we have to register long one as well here - persistentFlags.BoolVarP(p, a, a, value, aliasesUsage) - } else { - persistentFlags.BoolVar(p, a, value, aliasesUsage) - } - } -} diff --git a/cmd/nerdctl/main_unix.go b/cmd/nerdctl/main_unix.go deleted file mode 100644 index e29c3c6075c..00000000000 --- a/cmd/nerdctl/main_unix.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build unix - -/* - 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 From 9657f2c21c38f9c0beb8597d0e010467eb1508b2 Mon Sep 17 00:00:00 2001 From: Justin Alvarez Date: Tue, 3 Sep 2024 10:47:08 -0400 Subject: [PATCH 0734/1066] chore: update runc to v1.1.14 Signed-off-by: Justin Alvarez --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index dce181d775d..15f2f859148 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v2.0.0-rc.4 -ARG RUNC_VERSION=v1.1.13 +ARG RUNC_VERSION=v1.1.14 ARG CNI_PLUGINS_VERSION=v1.5.1 # Extra deps: Build From 04cc74bd6c5ee63ce6a1401ad805163abad4db3d Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 11 Aug 2024 13:46:50 -0700 Subject: [PATCH 0735/1066] Auth code refactor: credstore and registry URL Signed-off-by: apostasie --- cmd/nerdctl/login/login_linux_test.go | 437 +++++++++++++----- cmd/nerdctl/login/logout.go | 62 +-- pkg/cmd/login/login.go | 131 ++---- pkg/cmd/logout/logout.go | 46 ++ .../dockerconfigresolver/credentialsstore.go | 174 +++++++ .../credentialsstore_test.go | 381 +++++++++++++++ pkg/imgutil/dockerconfigresolver/defaults.go | 51 ++ .../dockerconfigresolver.go | 97 +--- .../dockerconfigresolver_util.go | 50 -- .../dockerconfigresolver/registryurl.go | 134 ++++++ .../dockerconfigresolver/registryurl_test.go | 189 ++++++++ .../testregistry/testregistry_linux.go | 28 +- pkg/testutil/testutil.go | 2 +- 13 files changed, 1397 insertions(+), 385 deletions(-) create mode 100644 pkg/cmd/logout/logout.go create mode 100644 pkg/imgutil/dockerconfigresolver/credentialsstore.go create mode 100644 pkg/imgutil/dockerconfigresolver/credentialsstore_test.go create mode 100644 pkg/imgutil/dockerconfigresolver/defaults.go delete mode 100644 pkg/imgutil/dockerconfigresolver/dockerconfigresolver_util.go create mode 100644 pkg/imgutil/dockerconfigresolver/registryurl.go create mode 100644 pkg/imgutil/dockerconfigresolver/registryurl_test.go diff --git a/cmd/nerdctl/login/login_linux_test.go b/cmd/nerdctl/login/login_linux_test.go index ef65e9868fd..13a68c4900a 100644 --- a/cmd/nerdctl/login/login_linux_test.go +++ b/cmd/nerdctl/login/login_linux_test.go @@ -14,11 +14,13 @@ limitations under the License. */ +// https://docs.docker.com/reference/cli/dockerd/#insecure-registries +// Local registries, whose IP address falls in the 127.0.0.0/8 range, are automatically marked as insecure as of Docker 1.3.2. +// It isn't recommended to rely on this, as it may change in the future. +// "--insecure" means that either the certificates are untrusted, or that the protocol is plain http package login import ( - "crypto/rand" - "encoding/base64" "fmt" "net" "os" @@ -27,20 +29,12 @@ import ( "gotest.tools/v3/icmd" + "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/testca" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) -func safeRandomString(n int) string { - b := make([]byte, n) - _, _ = rand.Read(b) - // XXX WARNING there is something in the registry (or more likely in the way we generate htpasswd files) - // that is broken and does not resist truly random strings - // return string(b) - return base64.URLEncoding.EncodeToString(b) -} - type Client struct { args []string configPath string @@ -57,269 +51,486 @@ func (ag *Client) WithHostsDir(hostDirs string) *Client { } func (ag *Client) WithCredentials(username, password string) *Client { - ag.args = append(ag.args, "--username", username, "--password", password) + if username != "" { + ag.args = append(ag.args, "--username", username) + } + if password != "" { + ag.args = append(ag.args, "--password", password) + } + return ag +} + +func (ag *Client) WithConfigPath(value string) *Client { + ag.configPath = value return ag } +func (ag *Client) GetConfigPath() string { + return ag.configPath +} + func (ag *Client) Run(base *testutil.Base, host string) *testutil.Cmd { if ag.configPath == "" { ag.configPath, _ = os.MkdirTemp(base.T.TempDir(), "docker-config") } - args := append([]string{"--debug-full", "login"}, ag.args...) + args := []string{"login"} + if base.Target == "nerdctl" { + args = append(args, "--debug-full") + } + args = append(args, ag.args...) icmdCmd := icmd.Command(base.Binary, append(base.Args, append(args, host)...)...) icmdCmd.Env = append(base.Env, "HOME="+os.Getenv("HOME"), "DOCKER_CONFIG="+ag.configPath) + return &testutil.Cmd{ Cmd: icmdCmd, Base: base, } } -func TestLogin(t *testing.T) { +func TestLoginPersistence(t *testing.T) { + base := testutil.NewBase(t) + t.Parallel() + + // Retrieve from the store + testCases := []struct { + auth string + }{ + { + "basic", + }, + { + "token", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(fmt.Sprintf("Server %s", tc.auth), func(t *testing.T) { + t.Parallel() + + username := testregistry.SafeRandomString(30) + "∞" + password := testregistry.SafeRandomString(30) + ":∞" + + // Add the requested authentication + var auth testregistry.Auth + var dependentCleanup func(error) + + auth = &testregistry.NoAuth{} + if tc.auth == "basic" { + auth = &testregistry.BasicAuth{ + Username: username, + Password: password, + } + } else if tc.auth == "token" { + authCa := testca.New(base.T) + as := testregistry.NewAuthServer(base, authCa, 0, username, password, false) + auth = &testregistry.TokenAuth{ + Address: as.Scheme + "://" + net.JoinHostPort(as.IP.String(), strconv.Itoa(as.Port)), + CertPath: as.CertPath, + } + dependentCleanup = as.Cleanup + } + + // Start the registry with the requested options + reg := testregistry.NewRegistry(base, nil, 0, auth, dependentCleanup) + + // Register registry cleanup + t.Cleanup(func() { + reg.Cleanup(nil) + }) + + // First, login successfully + c := (&Client{}). + WithCredentials(username, password) + + c.Run(base, fmt.Sprintf("localhost:%d", reg.Port)). + AssertOK() + + // Now, log in successfully without passing any explicit credentials + nc := (&Client{}). + WithConfigPath(c.GetConfigPath()) + nc.Run(base, fmt.Sprintf("localhost:%d", reg.Port)). + AssertOK() + + // Now fail while using invalid credentials + nc.WithCredentials("invalid", "invalid"). + Run(base, fmt.Sprintf("localhost:%d", reg.Port)). + AssertFail() + + // And login again without, reverting to the last saved good state + nc = (&Client{}). + WithConfigPath(c.GetConfigPath()) + + nc.Run(base, fmt.Sprintf("localhost:%d", reg.Port)). + AssertOK() + }) + } +} + +/* +func TestAgainstNoAuth(t *testing.T) { + base := testutil.NewBase(t) + t.Parallel() + + // Start the registry with the requested options + reg := testregistry.NewRegistry(base, nil, 0, &testregistry.NoAuth{}, nil) + + // Register registry cleanup + t.Cleanup(func() { + reg.Cleanup(nil) + }) + + c := (&Client{}). + WithCredentials("invalid", "invalid") + + c.Run(base, fmt.Sprintf("localhost:%d", reg.Port)). + AssertOK() + + content, _ := os.ReadFile(filepath.Join(c.configPath, "config.json")) + fmt.Println(string(content)) + + c.Run(base, fmt.Sprintf("localhost:%d", reg.Port)). + AssertFail() + +} + +*/ + +func TestLoginAgainstVariants(t *testing.T) { // Skip docker, because Docker doesn't have `--hosts-dir` nor `insecure-registry` option + // This will test access to a wide variety of servers, with or without TLS, with basic or token authentication testutil.DockerIncompatible(t) base := testutil.NewBase(t) t.Parallel() - testregistry.EnsureImages(base) - testCases := []struct { - port int - tls bool - auth string - insecure bool + port int + tls bool + auth string }{ + // Basic auth, no TLS { 80, false, "basic", - true, }, { 443, false, "basic", - true, }, { 0, false, "basic", - true, }, + // Token auth, no TLS { 80, - true, - "basic", false, + "token", }, { 443, - true, - "basic", false, + "token", }, { 0, - true, - "basic", false, + "token", }, + // Basic auth, with TLS { 80, - false, - "token", true, + "basic", }, { 443, - false, - "token", true, + "basic", }, { 0, - false, - "token", true, + "basic", }, + // Token auth, with TLS { 80, true, "token", - false, }, { 443, true, "token", - false, }, { 0, true, "token", - false, }, } + // Iterate through all cases, that will present a variety of port (80, 443, random), TLS (yes or no), and authentication (basic, token) type combinations for _, tc := range testCases { - // Since we have a lock mechanism for acquiring ports, we can just parallelize everything - t.Run(fmt.Sprintf("Login against registry with tls: %t port: %d auth: %s", tc.tls, tc.port, tc.auth), func(t *testing.T) { + port := tc.port + tls := tc.tls + auth := tc.auth + + t.Run(fmt.Sprintf("Login against `tls: %t port: %d auth: %s`", tls, port, auth), func(t *testing.T) { // Tests with fixed ports should not be parallelized (although the port locking mechanism will prevent conflicts) - // as their children are, and this might deadlock given how Parallel works - if tc.port == 0 { + // as their children tests are parallelized, and this might deadlock given the way `Parallel` works + if port == 0 { t.Parallel() } - // Generate credentials so that we never cross hit another test registry (spiced up with unicode) - // Note that the grammar for basic auth does not allow colons in usernames, while token auth allows it - username := safeRandomString(30) + "∞" - password := safeRandomString(30) + ":∞" + // Generate credentials that are specific to each registry, so that we never cross hit another one + username := testregistry.SafeRandomString(30) + "∞" + password := testregistry.SafeRandomString(30) + ":∞" // Get a CA if we want TLS var ca *testca.CA - if tc.tls { + if tls { ca = testca.New(base.T) } - // Add the requested authentication - var auth testregistry.Auth - auth = &testregistry.NoAuth{} + // Add the requested authenticator + var authenticator testregistry.Auth var dependentCleanup func(error) - if tc.auth == "basic" { - auth = &testregistry.BasicAuth{ + + authenticator = &testregistry.NoAuth{} + if auth == "basic" { + authenticator = &testregistry.BasicAuth{ Username: username, Password: password, } - } else if tc.auth == "token" { + } else if auth == "token" { authCa := ca - // We could be on !tls - still need a ca to sign jwt + // We could be on !tls, meaning no ca - but we still need a CA to sign jwt tokens if authCa == nil { authCa = testca.New(base.T) } - as := testregistry.NewAuthServer(base, authCa, 0, username, password, tc.tls) - auth = &testregistry.TokenAuth{ + as := testregistry.NewAuthServer(base, authCa, 0, username, password, tls) + authenticator = &testregistry.TokenAuth{ Address: as.Scheme + "://" + net.JoinHostPort(as.IP.String(), strconv.Itoa(as.Port)), CertPath: as.CertPath, } dependentCleanup = as.Cleanup } - // Start the registry - reg := testregistry.NewRegistry(base, ca, tc.port, auth, dependentCleanup) + // Start the registry with the requested options + reg := testregistry.NewRegistry(base, ca, port, authenticator, dependentCleanup) - // Attach our cleanup function + // Register registry cleanup t.Cleanup(func() { reg.Cleanup(nil) }) + // Any registry is reachable through its ip+port, and localhost variants regHosts := []string{ net.JoinHostPort(reg.IP.String(), strconv.Itoa(reg.Port)), + net.JoinHostPort("localhost", strconv.Itoa(reg.Port)), + net.JoinHostPort("127.0.0.1", strconv.Itoa(reg.Port)), + // TODO: ipv6 + // net.JoinHostPort("::1", strconv.Itoa(reg.Port)), } - // XXX seems like omitting ports is broken on main currently - // (plus the hosts.toml resolution is not good either) - // XXX we should also add hostname here (maybe use the container name?) - // Obviously also need to add localhost to the mix once we fix behavior - /* - if reg.Port == 443 || reg.Port == 80 { - regHosts = append(regHosts, reg.IP.String()) - } - */ + // Registries that use port 443 also allow access without specifying a port + if reg.Port == 443 { + regHosts = append(regHosts, reg.IP.String()) + regHosts = append(regHosts, "localhost") + regHosts = append(regHosts, "127.0.0.1") + // TODO: ipv6 + // regHosts = append(regHosts, "::1") + } + // Iterate through these hosts access points, and create a test per-variant for _, value := range regHosts { regHost := value t.Run(regHost, func(t *testing.T) { t.Parallel() - t.Run("Valid credentials (no certs) ", func(t *testing.T) { + // 1. test with valid credentials but no access to the CA + t.Run("1. valid credentials (no CA) ", func(t *testing.T) { t.Parallel() + c := (&Client{}). WithCredentials(username, password) - // Fail without insecure - c.Run(base, regHost).AssertFail() + rl, _ := dockerconfigresolver.Parse(regHost) + // a. Insecure flag not being set + // TODO: remove specialization when we fix the localhost mess + if rl.IsLocalhost() && !tls { + c.Run(base, regHost). + AssertOK() + } else { + c.Run(base, regHost). + AssertFail() + } - // Succeed with insecure - c.WithInsecure(true). - Run(base, regHost).AssertOK() + // b. Insecure flag set to false + // TODO: remove specialization when we fix the localhost mess + if !rl.IsLocalhost() { + (&Client{}). + WithCredentials(username, password). + WithInsecure(false). + Run(base, regHost). + AssertFail() + } + + // c. Insecure flag set to true + // TODO: remove specialization when we fix the localhost mess + if !rl.IsLocalhost() || !tls { + (&Client{}). + WithCredentials(username, password). + WithInsecure(true). + Run(base, regHost). + AssertOK() + } }) - t.Run("Valid credentials (with certs)", func(t *testing.T) { + // 2. test with valid credentials AND access to the CA + t.Run("2. valid credentials (with access to server CA)", func(t *testing.T) { t.Parallel() + + rl, _ := dockerconfigresolver.Parse(regHost) + + // a. Insecure flag not being set c := (&Client{}). WithCredentials(username, password). WithHostsDir(reg.HostsDir) - if tc.insecure { - c.Run(base, regHost).AssertFail() + if tls || rl.IsLocalhost() { + c.Run(base, regHost). + AssertOK() } else { - c.Run(base, regHost).AssertOK() + c.Run(base, regHost). + AssertFail() } + // b. Insecure flag set to false + if tls { + c.WithInsecure(false). + Run(base, regHost). + AssertOK() + } else { + // TODO: remove specialization when we fix the localhost mess + if !rl.IsLocalhost() { + c.WithInsecure(false). + Run(base, regHost). + AssertFail() + } + } + + // c. Insecure flag set to true c.WithInsecure(true). - Run(base, regHost).AssertOK() + Run(base, regHost). + AssertOK() }) - t.Run("Valid credentials (with certs), any variant", func(t *testing.T) { + t.Run("3. valid credentials, any url variant, should always succeed", func(t *testing.T) { t.Parallel() c := (&Client{}). WithCredentials(username, password). WithHostsDir(reg.HostsDir). // Just use insecure here for all servers - it does not matter for what we are testing here + // in this case, which is whether we can successfully log in against any of these variants WithInsecure(true) - c.Run(base, "http://"+regHost).AssertOK() - c.Run(base, "https://"+regHost).AssertOK() - c.Run(base, "http://"+regHost+"/whatever?foo=bar;foo:bar#foo=bar").AssertOK() - c.Run(base, "https://"+regHost+"/whatever?foo=bar&bar=foo;foo=foo+bar:bar#foo=bar").AssertOK() + // TODO: remove specialization when we fix the localhost mess + rl, _ := dockerconfigresolver.Parse(regHost) + if !rl.IsLocalhost() || !tls { + c.Run(base, "http://"+regHost).AssertOK() + c.Run(base, "https://"+regHost).AssertOK() + c.Run(base, "http://"+regHost+"/whatever?foo=bar;foo:bar#foo=bar").AssertOK() + c.Run(base, "https://"+regHost+"/whatever?foo=bar&bar=foo;foo=foo+bar:bar#foo=bar").AssertOK() + } }) - t.Run("Wrong pass (no certs)", func(t *testing.T) { + t.Run("4. wrong password should always fail", func(t *testing.T) { t.Parallel() - c := (&Client{}). - WithCredentials(username, "invalid") - c.Run(base, regHost).AssertFail() + (&Client{}). + WithCredentials(username, "invalid"). + WithHostsDir(reg.HostsDir). + Run(base, regHost). + AssertFail() - c.WithInsecure(true). - Run(base, regHost).AssertFail() - }) + (&Client{}). + WithCredentials(username, "invalid"). + WithHostsDir(reg.HostsDir). + WithInsecure(false). + Run(base, regHost). + AssertFail() - t.Run("Wrong user (no certs)", func(t *testing.T) { - t.Parallel() - c := (&Client{}). - WithCredentials("invalid", password) + (&Client{}). + WithCredentials(username, "invalid"). + WithHostsDir(reg.HostsDir). + WithInsecure(true). + Run(base, regHost). + AssertFail() - c.Run(base, regHost).AssertFail() + (&Client{}). + WithCredentials(username, "invalid"). + Run(base, regHost). + AssertFail() - c.WithInsecure(true). - Run(base, regHost).AssertFail() + (&Client{}). + WithCredentials(username, "invalid"). + WithInsecure(false). + Run(base, regHost). + AssertFail() + + (&Client{}). + WithCredentials(username, "invalid"). + WithInsecure(true). + Run(base, regHost). + AssertFail() }) - t.Run("Wrong pass (with certs)", func(t *testing.T) { + t.Run("5. wrong username should always fail", func(t *testing.T) { t.Parallel() - c := (&Client{}). - WithCredentials(username, "invalid"). - WithHostsDir(reg.HostsDir) - c.Run(base, regHost).AssertFail() + (&Client{}). + WithCredentials("invalid", password). + WithHostsDir(reg.HostsDir). + Run(base, regHost). + AssertFail() - c.WithInsecure(true). - Run(base, regHost).AssertFail() - }) + (&Client{}). + WithCredentials("invalid", password). + WithHostsDir(reg.HostsDir). + WithInsecure(false). + Run(base, regHost). + AssertFail() - t.Run("Wrong user (with certs)", func(t *testing.T) { - t.Parallel() - c := (&Client{}). + (&Client{}). WithCredentials("invalid", password). - WithHostsDir(reg.HostsDir) + WithHostsDir(reg.HostsDir). + WithInsecure(true). + Run(base, regHost). + AssertFail() - c.Run(base, regHost).AssertFail() + (&Client{}). + WithCredentials("invalid", password). + Run(base, regHost). + AssertFail() - c.WithInsecure(true). - Run(base, regHost).AssertFail() + (&Client{}). + WithCredentials("invalid", password). + WithInsecure(false). + Run(base, regHost). + AssertFail() + + (&Client{}). + WithCredentials("invalid", password). + WithInsecure(true). + Run(base, regHost). + AssertFail() }) }) } diff --git a/cmd/nerdctl/login/logout.go b/cmd/nerdctl/login/logout.go index 17019c6a485..f43643b791f 100644 --- a/cmd/nerdctl/login/logout.go +++ b/cmd/nerdctl/login/logout.go @@ -17,16 +17,15 @@ package login import ( - "fmt" - - dockercliconfig "github.com/docker/cli/cli/config" "github.com/spf13/cobra" - "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" + "github.com/containerd/log" + + "github.com/containerd/nerdctl/v2/pkg/cmd/logout" ) func NewLogoutCommand() *cobra.Command { - var logoutCommand = &cobra.Command{ + return &cobra.Command{ Use: "logout [flags] [SERVER]", Args: cobra.MaximumNArgs(1), Short: "Log out from a container registry", @@ -35,62 +34,33 @@ func NewLogoutCommand() *cobra.Command { SilenceUsage: true, SilenceErrors: true, } - return logoutCommand } -// code inspired from XXX func logoutAction(cmd *cobra.Command, args []string) error { - serverAddress := dockerconfigresolver.IndexServer - isDefaultRegistry := true - if len(args) >= 1 { - serverAddress = args[0] - isDefaultRegistry = false - } - - var ( - regsToLogout = []string{serverAddress} - hostnameAddress = serverAddress - ) - - if !isDefaultRegistry { - hostnameAddress = dockerconfigresolver.ConvertToHostname(serverAddress) - // the tries below are kept for backward compatibility where a user could have - // saved the registry in one of the following format. - regsToLogout = append(regsToLogout, hostnameAddress, "http://"+hostnameAddress, "https://"+hostnameAddress) + logoutServer := "" + if len(args) > 0 { + logoutServer = args[0] } - fmt.Fprintf(cmd.OutOrStdout(), "Removing login credentials for %s\n", hostnameAddress) - - dockerConfigFile, err := dockercliconfig.Load("") + errGroup, err := logout.Logout(cmd.Context(), logoutServer) if err != nil { - return err + log.L.WithError(err).Errorf("Failed to erase credentials for: %s", logoutServer) } - errs := make(map[string]error) - for _, r := range regsToLogout { - if err := dockerConfigFile.GetCredentialsStore(r).Erase(r); err != nil { - errs[r] = err + if errGroup != nil { + log.L.Error("None of the following entries could be found") + for _, v := range errGroup { + log.L.Errorf("%s", v) } } - // if at least one removal succeeded, report success. Otherwise report errors - if len(errs) == len(regsToLogout) { - fmt.Fprintln(cmd.ErrOrStderr(), "WARNING: could not erase credentials:") - for k, v := range errs { - fmt.Fprintf(cmd.OutOrStdout(), "%s: %s\n", k, v) - } - } - - return nil + return err } func logoutShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - dockerConfigFile, err := dockercliconfig.Load("") + candidates, err := logout.ShellCompletion() if err != nil { return nil, cobra.ShellCompDirectiveError } - candidates := []string{} - for key := range dockerConfigFile.AuthConfigs { - candidates = append(candidates, key) - } + return candidates, cobra.ShellCompDirectiveNoFileComp } diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 3ca7c9e35c1..6d5f5a026d4 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -27,9 +27,6 @@ import ( "os" "strings" - dockercliconfig "github.com/docker/cli/cli/config" - dockercliconfigtypes "github.com/docker/cli/cli/config/types" - "github.com/docker/docker/api/types/registry" "golang.org/x/net/context/ctxhttp" "golang.org/x/term" @@ -48,106 +45,64 @@ Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store ` -type isFileStore interface { - IsFileStore() bool - GetFilename() string -} - func Login(ctx context.Context, options types.LoginCommandOptions, stdout io.Writer) error { - var serverAddress string - if options.ServerAddress == "" || options.ServerAddress == "docker.io" || options.ServerAddress == "index.docker.io" || options.ServerAddress == "registry-1.docker.io" { - serverAddress = dockerconfigresolver.IndexServer - } else { - serverAddress = options.ServerAddress + registryURL, err := dockerconfigresolver.Parse(options.ServerAddress) + if err != nil { + return err + } + + credStore, err := dockerconfigresolver.NewCredentialsStore("") + if err != nil { + return err } var responseIdentityToken string - isDefaultRegistry := serverAddress == dockerconfigresolver.IndexServer - authConfig, err := GetDefaultAuthConfig(options.Username == "" && options.Password == "", serverAddress, isDefaultRegistry) - if authConfig == nil { - authConfig = ®istry.AuthConfig{ServerAddress: serverAddress} - } - if err == nil && authConfig.Username != "" && authConfig.Password != "" { - // login With StoreCreds - responseIdentityToken, err = loginClientSide(ctx, options.GOptions, *authConfig) + credentials, err := credStore.Retrieve(registryURL, options.Username == "" && options.Password == "") + credentials.IdentityToken = "" + + if err == nil && credentials.Username != "" && credentials.Password != "" { + responseIdentityToken, err = loginClientSide(ctx, options.GOptions, registryURL, credentials) } - if err != nil || authConfig.Username == "" || authConfig.Password == "" { - err = ConfigureAuthentication(authConfig, options.Username, options.Password) + if err != nil || credentials.Username == "" || credentials.Password == "" { + err = configureAuthentication(credentials, options.Username, options.Password) if err != nil { return err } - responseIdentityToken, err = loginClientSide(ctx, options.GOptions, *authConfig) + responseIdentityToken, err = loginClientSide(ctx, options.GOptions, registryURL, credentials) if err != nil { return err } } if responseIdentityToken != "" { - authConfig.Password = "" - authConfig.IdentityToken = responseIdentityToken - } - - dockerConfigFile, err := dockercliconfig.Load("") - if err != nil { - return err + credentials.Password = "" + credentials.IdentityToken = responseIdentityToken } - creds := dockerConfigFile.GetCredentialsStore(serverAddress) - - store, isFile := creds.(isFileStore) // Display a warning if we're storing the users password (not a token) and credentials store type is file. - if isFile && authConfig.Password != "" { - _, err = fmt.Fprintln(stdout, fmt.Sprintf(unencryptedPasswordWarning, store.GetFilename())) + storageFileLocation := credStore.FileStorageLocation(registryURL) + if storageFileLocation != "" && credentials.Password != "" { + _, err = fmt.Fprintln(stdout, fmt.Sprintf(unencryptedPasswordWarning, storageFileLocation)) if err != nil { return err } } - if err := creds.Store(dockercliconfigtypes.AuthConfig(*(authConfig))); err != nil { + err = credStore.Store(registryURL, credentials) + if err != nil { return fmt.Errorf("error saving credentials: %w", err) } - fmt.Fprintln(stdout, "Login Succeeded") - - return nil -} + _, err = fmt.Fprintln(stdout, "Login Succeeded") -// GetDefaultAuthConfig gets the default auth config given a serverAddress. -// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it. -// Code from github.com/docker/cli/cli/command (v20.10.3). -func GetDefaultAuthConfig(checkCredStore bool, serverAddress string, isDefaultRegistry bool) (*registry.AuthConfig, error) { - if !isDefaultRegistry { - var err error - serverAddress, err = convertToHostname(serverAddress) - if err != nil { - return nil, err - } - } - authconfig := dockercliconfigtypes.AuthConfig{} - if checkCredStore { - dockerConfigFile, err := dockercliconfig.Load("") - if err != nil { - return nil, err - } - authconfig, err = dockerConfigFile.GetAuthConfig(serverAddress) - if err != nil { - return nil, err - } - } - authconfig.ServerAddress = serverAddress - authconfig.IdentityToken = "" - res := registry.AuthConfig(authconfig) - return &res, nil + return err } -func loginClientSide(ctx context.Context, globalOptions types.GlobalCommandOptions, auth registry.AuthConfig) (string, error) { - host, err := convertToHostname(auth.ServerAddress) - if err != nil { - return "", err - } +func loginClientSide(ctx context.Context, globalOptions types.GlobalCommandOptions, registryURL *dockerconfigresolver.RegistryURL, credentials *dockerconfigresolver.Credentials) (string, error) { + host := registryURL.Host var dOpts []dockerconfigresolver.Opt if globalOptions.InsecureRegistry { log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", host) @@ -157,12 +112,12 @@ func loginClientSide(ctx context.Context, globalOptions types.GlobalCommandOptio authCreds := func(acArg string) (string, string, error) { if acArg == host { - if auth.RegistryToken != "" { + if credentials.RegistryToken != "" { // Even containerd/CRI does not support RegistryToken as of v1.4.3, // so, nobody is actually using RegistryToken? log.G(ctx).Warnf("RegistryToken (for %q) is not supported yet (FIXME)", host) } - return auth.Username, auth.Password, nil + return credentials.Username, credentials.Password, nil } return "", "", fmt.Errorf("expected acArg to be %q, got %q", host, acArg) } @@ -251,10 +206,9 @@ func tryLoginWithRegHost(ctx context.Context, rh docker.RegistryHost) error { return errors.New("too many 401 (probably)") } -func ConfigureAuthentication(authConfig *registry.AuthConfig, username, password string) error { - authConfig.Username = strings.TrimSpace(authConfig.Username) +func configureAuthentication(credentials *dockerconfigresolver.Credentials, username, password string) error { if username = strings.TrimSpace(username); username == "" { - username = authConfig.Username + username = credentials.Username } if username == "" { fmt.Print("Enter Username: ") @@ -281,8 +235,8 @@ func ConfigureAuthentication(authConfig *registry.AuthConfig, username, password return fmt.Errorf("error: Password is Required") } - authConfig.Username = username - authConfig.Password = password + credentials.Username = username + credentials.Password = password return nil } @@ -304,22 +258,3 @@ func readUsername() (string, error) { return username, nil } - -func convertToHostname(serverAddress string) (string, error) { - // Ensure that URL contains scheme for a good parsing process - if strings.Contains(serverAddress, "://") { - u, err := url.Parse(serverAddress) - if err != nil { - return "", err - } - serverAddress = u.Host - } else { - u, err := url.Parse("https://" + serverAddress) - if err != nil { - return "", err - } - serverAddress = u.Host - } - - return serverAddress, nil -} diff --git a/pkg/cmd/logout/logout.go b/pkg/cmd/logout/logout.go new file mode 100644 index 00000000000..99a4b77f852 --- /dev/null +++ b/pkg/cmd/logout/logout.go @@ -0,0 +1,46 @@ +/* + 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 logout + +import ( + "context" + + "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" +) + +func Logout(ctx context.Context, logoutServer string) (map[string]error, error) { + reg, err := dockerconfigresolver.Parse(logoutServer) + if err != nil { + return nil, err + } + + credentialsStore, err := dockerconfigresolver.NewCredentialsStore("") + if err != nil { + return nil, err + } + + return credentialsStore.Erase(reg) +} + +func ShellCompletion() ([]string, error) { + credentialsStore, err := dockerconfigresolver.NewCredentialsStore("") + if err != nil { + return nil, err + } + + return credentialsStore.ShellCompletion(), nil +} diff --git a/pkg/imgutil/dockerconfigresolver/credentialsstore.go b/pkg/imgutil/dockerconfigresolver/credentialsstore.go new file mode 100644 index 00000000000..86e5393a20f --- /dev/null +++ b/pkg/imgutil/dockerconfigresolver/credentialsstore.go @@ -0,0 +1,174 @@ +/* + 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 dockerconfigresolver + +import ( + "errors" + "fmt" + "strings" + + "github.com/docker/cli/cli/config" + "github.com/docker/cli/cli/config/configfile" + "github.com/docker/cli/cli/config/types" +) + +type Credentials = types.AuthConfig + +// NewCredentialsStore returns a CredentialsStore from a directory +// If path is left empty, the default docker `~/.docker/config.json` will be used +// In case the docker call fails, we wrap the error with ErrUnableToInstantiate +func NewCredentialsStore(path string) (*CredentialsStore, error) { + dockerConfigFile, err := config.Load(path) + if err != nil { + return nil, errors.Join(ErrUnableToInstantiate, err) + } + + return &CredentialsStore{ + dockerConfigFile: dockerConfigFile, + }, nil +} + +// CredentialsStore is an abstraction in front of docker config API manipulation +// exposing just the limited functions we need and hiding away url normalization / identifiers magic, and handling of +// backward compatibility +type CredentialsStore struct { + dockerConfigFile *configfile.ConfigFile +} + +// Erase will remove any and all stored credentials for that registry namespace (including all legacy variants) +// If we do not find at least ONE variant matching the namespace, this will error with ErrUnableToErase +func (cs *CredentialsStore) Erase(registryURL *RegistryURL) (map[string]error, error) { + // Get all associated identifiers for that registry including legacy ones and variants + logoutList := registryURL.AllIdentifiers() + + // Iterate through and delete them one by one + errs := make(map[string]error) + for _, serverAddress := range logoutList { + if err := cs.dockerConfigFile.GetCredentialsStore(serverAddress).Erase(serverAddress); err != nil { + errs[serverAddress] = err + } + } + + // If we succeeded removing at least one, it is a success. + // The only error condition is if we failed removing anything - meaning there was no such credential information + // in whatever format - or the store is broken. + if len(errs) == len(logoutList) { + return errs, ErrUnableToErase + } + + return nil, nil +} + +// Store will save credentials for a given registry +// On error, ErrUnableToStore +func (cs *CredentialsStore) Store(registryURL *RegistryURL, credentials *Credentials) error { + // We just overwrite the server property here with the host + // Whether it was one of the variants, or was not set at all (see for example Amazon ECR, https://github.com/containerd/nerdctl/issues/733 + // - which is likely a bug in docker) it doesn't matter. + // This is the credentials that were returned for that host, by the docker credentials store. + if registryURL.Namespace != nil { + credentials.ServerAddress = fmt.Sprintf("%s%s?%s", registryURL.Host, registryURL.Path, registryURL.RawQuery) + } else { + credentials.ServerAddress = registryURL.Host + } + + // XXX future namespaced url likely require special handling here + if err := cs.dockerConfigFile.GetCredentialsStore(registryURL.CanonicalIdentifier()).Store(*(credentials)); err != nil { + return errors.Join(ErrUnableToStore, err) + } + + return nil +} + +// ShellCompletion will return candidate strings for nerdctl logout +func (cs *CredentialsStore) ShellCompletion() []string { + candidates := []string{} + for key := range cs.dockerConfigFile.AuthConfigs { + candidates = append(candidates, key) + } + + return candidates +} + +// FileStorageLocation will return the file where credentials are stored for a given registry, or the empty string +// if it is stored / to be stored in a different place (like an OS keychain, with docker credential helpers) +func (cs *CredentialsStore) FileStorageLocation(registryURL *RegistryURL) string { + if store, isFile := (cs.dockerConfigFile.GetCredentialsStore(registryURL.CanonicalIdentifier())).(isFileStore); isFile { + return store.GetFilename() + } + + return "" +} + +// Retrieve gets existing credentials from the store for a certain registry. +// If none are found, an empty Credentials struct is returned. +// If we hard-fail reading from the store, indicative of a broken system, we wrap the error with ErrUnableToRetrieve +func (cs *CredentialsStore) Retrieve(registryURL *RegistryURL, checkCredStore bool) (*Credentials, error) { + var err error + returnedCredentials := &Credentials{} + + // As long as we depend on .ServerAddress, make sure it is populated correctly + // It does not matter what was stored - the docker cli clearly has issues with this + // What matters is that the credentials retrieved from the docker credentials store are *for that registryURL* + // and that is what ServerAddress should point to + defer func() { + if registryURL.Namespace != nil { + returnedCredentials.ServerAddress = fmt.Sprintf("%s%s?%s", registryURL.Host, registryURL.Path, registryURL.RawQuery) + } else { + returnedCredentials.ServerAddress = registryURL.Host + } + }() + + if !checkCredStore { + return returnedCredentials, nil + } + + // Get the legacy variants (w/o scheme or port), and iterate over until we find one with credentials + variants := registryURL.AllIdentifiers() + + for _, identifier := range variants { + var credentials types.AuthConfig + // Note that Get does not raise an error on ENOENT + credentials, err = cs.dockerConfigFile.GetCredentialsStore(identifier).Get(identifier) + if err != nil { + continue + } + returnedCredentials = &credentials + // Clean-up the username + returnedCredentials.Username = strings.TrimSpace(returnedCredentials.Username) + // Stop here if we found credentials with this variant + if returnedCredentials.IdentityToken != "" || + returnedCredentials.Username != "" || + returnedCredentials.Password != "" || + returnedCredentials.RegistryToken != "" { + break + } + } + + // (Last non nil) credential store error gets wrapped into ErrUnableToRetrieve + if err != nil { + err = errors.Join(ErrUnableToRetrieve, err) + } + + return returnedCredentials, err +} + +// isFileStore is an internal mock interface purely meant to help identify that the docker credential backend is a filesystem one +type isFileStore interface { + IsFileStore() bool + GetFilename() string +} diff --git a/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go b/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go new file mode 100644 index 00000000000..38bf4a29e35 --- /dev/null +++ b/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go @@ -0,0 +1,381 @@ +/* + 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 dockerconfigresolver + +import ( + "encoding/base64" + "fmt" + "os" + "path/filepath" + "runtime" + "testing" + + "gotest.tools/v3/assert" +) + +func createTempDir(t *testing.T, mode os.FileMode) string { + tmpDir, err := os.MkdirTemp(t.TempDir(), "docker-config") + if err != nil { + t.Fatal(err) + } + err = os.Chmod(tmpDir, mode) + if err != nil { + t.Fatal(err) + } + return tmpDir +} + +func TestBrokenCredentialsStore(t *testing.T) { + if runtime.GOOS == "freebsd" { + // It is unclear why these tests are failing on FreeBSD, and if it is a problem with Vagrant or differences + // with FreeBSD + // Anyhow, this test is about extreme cases & conditions (filesystem errors wrt credentials loading). + t.Skip("skipping broken credential store tests for freebsd") + } + + testCases := []struct { + description string + setup func() string + errorNew error + errorRead error + errorWrite error + }{ + { + description: "Pointing DOCKER_CONFIG at a non-existent directory inside an unreadable directory will prevent instantiation", + setup: func() string { + tmpDir := createTempDir(t, 0000) + return filepath.Join(tmpDir, "doesnotexistcantcreate") + }, + errorNew: ErrUnableToInstantiate, + }, + { + description: "Pointing DOCKER_CONFIG at a non-existent directory inside a read-only directory will prevent saving credentials", + setup: func() string { + tmpDir := createTempDir(t, 0500) + return filepath.Join(tmpDir, "doesnotexistcantcreate") + }, + errorWrite: ErrUnableToStore, + }, + { + description: "Pointing DOCKER_CONFIG at an unreadable directory will prevent instantiation", + setup: func() string { + return createTempDir(t, 0000) + }, + errorNew: ErrUnableToInstantiate, + }, + { + description: "Pointing DOCKER_CONFIG at a read-only directory will prevent saving credentials", + setup: func() string { + return createTempDir(t, 0500) + }, + errorWrite: ErrUnableToStore, + }, + { + description: "Pointing DOCKER_CONFIG at a directory containing am unparsable `config.json` will prevent instantiation", + setup: func() string { + tmpDir := createTempDir(t, 0700) + err := os.WriteFile(filepath.Join(tmpDir, "config.json"), []byte("porked"), 0600) + if err != nil { + t.Fatal(err) + } + return tmpDir + }, + errorNew: ErrUnableToInstantiate, + }, + { + description: "Pointing DOCKER_CONFIG at a file instead of a directory will prevent instantiation", + setup: func() string { + tmpDir := createTempDir(t, 0700) + fd, err := os.OpenFile(filepath.Join(tmpDir, "isafile"), os.O_CREATE, 0600) + if err != nil { + t.Fatal(err) + } + err = fd.Close() + if err != nil { + t.Fatal(err) + } + return filepath.Join(tmpDir, "isafile") + }, + errorNew: ErrUnableToInstantiate, + }, + { + description: "Pointing DOCKER_CONFIG at a directory containing a `config.json` directory will prevent instantiation", + setup: func() string { + tmpDir := createTempDir(t, 0700) + err := os.Mkdir(filepath.Join(tmpDir, "config.json"), 0600) + if err != nil { + t.Fatal(err) + } + return tmpDir + }, + errorNew: ErrUnableToInstantiate, + }, + { + description: "Pointing DOCKER_CONFIG at a directory containing a `config.json` dangling symlink will still work", + setup: func() string { + tmpDir := createTempDir(t, 0700) + err := os.Symlink("doesnotexist", filepath.Join(tmpDir, "config.json")) + if err != nil { + t.Fatal(err) + } + return tmpDir + }, + }, + { + description: "Pointing DOCKER_CONFIG at a directory containing an unreadable, valid `config.json` file will prevent instantiation", + setup: func() string { + tmpDir := createTempDir(t, 0700) + err := os.WriteFile(filepath.Join(tmpDir, "config.json"), []byte("{}"), 0600) + if err != nil { + t.Fatal(err) + } + err = os.Chmod(filepath.Join(tmpDir, "config.json"), 0000) + if err != nil { + t.Fatal(err) + } + return tmpDir + }, + errorNew: ErrUnableToInstantiate, + }, + { + description: "Pointing DOCKER_CONFIG at a directory containing a read-only, valid `config.json` file will NOT prevent saving credentials", + setup: func() string { + tmpDir := createTempDir(t, 0700) + err := os.WriteFile(filepath.Join(tmpDir, "config.json"), []byte("{}"), 0600) + if err != nil { + t.Fatal(err) + } + err = os.Chmod(filepath.Join(tmpDir, "config.json"), 0400) + if err != nil { + t.Fatal(err) + } + return tmpDir + }, + }, + } + + t.Run("Broken Docker Config testing", func(t *testing.T) { + registryURL, err := Parse("registry") + if err != nil { + t.Fatal(err) + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + directory := tc.setup() + cs, err := NewCredentialsStore(directory) + assert.ErrorIs(t, err, tc.errorNew) + if err != nil { + return + } + + var af *Credentials + af, err = cs.Retrieve(registryURL, true) + assert.ErrorIs(t, err, tc.errorRead) + + err = cs.Store(registryURL, af) + assert.ErrorIs(t, err, tc.errorWrite) + }) + } + }) +} + +func writeContent(t *testing.T, content string) string { + t.Helper() + tmpDir := createTempDir(t, 0700) + err := os.WriteFile(filepath.Join(tmpDir, "config.json"), []byte(content), 0600) + if err != nil { + t.Fatal(err) + } + return tmpDir +} + +func TestWorkingCredentialsStore(t *testing.T) { + testCases := []struct { + description string + setup func() string + username string + password string + }{ + { + description: "Reading credentials from `auth` using canonical identifier", + username: "username", + password: "password", + setup: func() string { + content := fmt.Sprintf(`{ + "auths": { + "registry.example:443": { + "auth": %q + } + } + }`, base64.StdEncoding.EncodeToString([]byte("username:password"))) + return writeContent(t, content) + }, + }, + { + description: "Reading from legacy / alternative identifiers: registry.example", + username: "username", + setup: func() string { + content := `{ + "auths": { + "registry.example": { + "username": "username" + } + } + }` + return writeContent(t, content) + }, + }, + { + description: "Reading from legacy / alternative identifiers: http://registry.example", + username: "username", + setup: func() string { + content := `{ + "auths": { + "http://registry.example": { + "username": "username" + } + } + }` + return writeContent(t, content) + }, + }, + { + description: "Reading from legacy / alternative identifiers: https://registry.example", + username: "username", + setup: func() string { + content := `{ + "auths": { + "https://registry.example": { + "username": "username" + } + } + }` + return writeContent(t, content) + }, + }, + { + description: "Reading from legacy / alternative identifiers: http://registry.example:443", + username: "username", + setup: func() string { + content := `{ + "auths": { + "http://registry.example:443": { + "username": "username" + } + } + }` + return writeContent(t, content) + }, + }, + { + description: "Reading from legacy / alternative identifiers: https://registry.example:443", + username: "username", + setup: func() string { + content := `{ + "auths": { + "https://registry.example:443": { + "username": "username" + } + } + }` + return writeContent(t, content) + }, + }, + { + description: "Canonical form is preferred over legacy forms", + username: "pick", + setup: func() string { + content := `{ + "auths": { + "http://registry.example:443": { + "username": "ignore" + }, + "https://registry.example:443": { + "username": "ignore" + }, + "registry.example": { + "username": "ignore" + }, + "registry.example:443": { + "serveraddress": "bla", + "username": "pick" + }, + "http://registry.example": { + "username": "ignore" + }, + "https://registry.example": { + "username": "ignore" + } + } +}` + return writeContent(t, content) + }, + }, + } + + t.Run("Working credentials store", func(t *testing.T) { + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + registryURL, err := Parse("registry.example") + if err != nil { + t.Fatal(err) + } + cs, err := NewCredentialsStore(tc.setup()) + if err != nil { + t.Fatal(err) + } + + var af *Credentials + af, err = cs.Retrieve(registryURL, true) + assert.ErrorIs(t, err, nil) + assert.Equal(t, af.Username, tc.username) + assert.Equal(t, af.ServerAddress, "registry.example:443") + assert.Equal(t, af.Password, tc.password) + }) + } + }) + + t.Run("Namespaced host", func(t *testing.T) { + server := "host.example/path?ns=namespace.example" + registryURL, err := Parse(server) + if err != nil { + t.Fatal(err) + } + + content := `{ + "auths": { + "nerdctl-experimental://namespace.example:443/host/host.example:443/path": { + "username": "username" + } + } + }` + dir := writeContent(t, content) + cs, err := NewCredentialsStore(dir) + if err != nil { + t.Fatal(err) + } + + var af *Credentials + af, err = cs.Retrieve(registryURL, true) + assert.ErrorIs(t, err, nil) + assert.Equal(t, af.Username, "username") + assert.Equal(t, af.ServerAddress, "host.example:443/path?ns=namespace.example") + + }) +} diff --git a/pkg/imgutil/dockerconfigresolver/defaults.go b/pkg/imgutil/dockerconfigresolver/defaults.go new file mode 100644 index 00000000000..db78f3f70f7 --- /dev/null +++ b/pkg/imgutil/dockerconfigresolver/defaults.go @@ -0,0 +1,51 @@ +/* + 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 dockerconfigresolver + +import "errors" + +type scheme string + +const ( + standardHTTPSPort = "443" + schemeHTTP scheme = "http" + schemeHTTPS scheme = "https" + // schemeNerdctlExperimental is currently provisional, to unlock namespace based host authentication + // This may change or break without notice, and you should have no expectations that credentials saved like that + // will be supported in the future + schemeNerdctlExperimental scheme = "nerdctl-experimental" + // See https://github.com/moby/moby/blob/v27.1.1/registry/config.go#L42-L48 + //nolint:misspell + // especially Sebastiaan comments on future domain consolidation + dockerIndexServer = "https://index.docker.io/v1/" + // The query parameter that containerd will slap on namespaced hosts + namespaceQueryParameter = "ns" +) + +// Errors returned by the credentials store +var ( + ErrUnableToInstantiate = errors.New("unable to instantiate docker credentials store") + ErrUnableToErase = errors.New("unable to erase credentials") + ErrUnableToStore = errors.New("unable to store credentials") + ErrUnableToRetrieve = errors.New("unable to retrieve credentials") +) + +// Errors returned by `Parse` +var ( + ErrUnparsableURL = errors.New("unparsable registry URL") + ErrUnsupportedScheme = errors.New("unsupported scheme in registry URL") +) diff --git a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go index 935c6035da2..47a7be13c29 100644 --- a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go +++ b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go @@ -20,13 +20,8 @@ import ( "context" "crypto/tls" "errors" - "fmt" "os" - dockercliconfig "github.com/docker/cli/cli/config" - "github.com/docker/cli/cli/config/credentials" - dockercliconfigtypes "github.com/docker/cli/cli/config/types" - "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/containerd/v2/core/remotes/docker" dockerconfig "github.com/containerd/containerd/v2/core/remotes/docker/config" @@ -170,85 +165,35 @@ type AuthCreds func(string) (string, string, error) // NewAuthCreds returns AuthCreds that uses $DOCKER_CONFIG/config.json . // AuthCreds can be nil. func NewAuthCreds(refHostname string) (AuthCreds, error) { - // Load does not raise an error on ENOENT - dockerConfigFile, err := dockercliconfig.Load("") + // Note: does not raise an error on ENOENT + credStore, err := NewCredentialsStore("") if err != nil { return nil, err } - // DefaultHost converts "docker.io" to "registry-1.docker.io", - // which is wanted by credFunc . - credFuncExpectedHostname, err := docker.DefaultHost(refHostname) - if err != nil { - return nil, err - } + credFunc := func(host string) (string, string, error) { + rHost, err := Parse(host) + if err != nil { + return "", "", err + } - var credFunc AuthCreds + ac, err := credStore.Retrieve(rHost, true) + if err != nil { + return "", "", err + } - authConfigHostnames := []string{refHostname} - if refHostname == "docker.io" || refHostname == "registry-1.docker.io" { - // "docker.io" appears as ""https://index.docker.io/v1/" in ~/.docker/config.json . - // Unlike other registries, we have to pass the full URL to GetAuthConfig. - authConfigHostnames = append([]string{IndexServer}, refHostname) - } + if ac.IdentityToken != "" { + return "", ac.IdentityToken, nil + } - for _, authConfigHostname := range authConfigHostnames { - // GetAuthConfig does not raise an error on ENOENT - ac, err := dockerConfigFile.GetAuthConfig(authConfigHostname) - if err != nil { - log.L.WithError(err).Warnf("cannot get auth config for authConfigHostname=%q (refHostname=%q)", - authConfigHostname, refHostname) - } else { - // When refHostname is "docker.io": - // - credFuncExpectedHostname: "registry-1.docker.io" - // - credFuncArg: "registry-1.docker.io" - // - authConfigHostname: "https://index.docker.io/v1/" (IndexServer) - // - ac.ServerAddress: "https://index.docker.io/v1/". - if !isAuthConfigEmpty(ac) { - if ac.ServerAddress == "" { - // This can happen with Amazon ECR: https://github.com/containerd/nerdctl/issues/733 - log.L.Debugf("failed to get ac.ServerAddress for authConfigHostname=%q (refHostname=%q)", - authConfigHostname, refHostname) - } else if authConfigHostname == IndexServer { - if ac.ServerAddress != IndexServer { - return nil, fmt.Errorf("expected ac.ServerAddress (%q) to be %q", ac.ServerAddress, IndexServer) - } - } else { - acsaHostname := credentials.ConvertToHostname(ac.ServerAddress) - if acsaHostname != authConfigHostname { - return nil, fmt.Errorf("expected the hostname part of ac.ServerAddress (%q) to be authConfigHostname=%q, got %q", - ac.ServerAddress, authConfigHostname, acsaHostname) - } - } - - if ac.RegistryToken != "" { - // Even containerd/CRI does not support RegistryToken as of v1.4.3, - // so, nobody is actually using RegistryToken? - log.L.Warnf("ac.RegistryToken (for %q) is not supported yet (FIXME)", authConfigHostname) - } - - credFunc = func(credFuncArg string) (string, string, error) { - // credFuncArg should be like "registry-1.docker.io" - if credFuncArg != credFuncExpectedHostname { - return "", "", fmt.Errorf("expected credFuncExpectedHostname=%q (refHostname=%q), got credFuncArg=%q", - credFuncExpectedHostname, refHostname, credFuncArg) - } - if ac.IdentityToken != "" { - return "", ac.IdentityToken, nil - } - return ac.Username, ac.Password, nil - } - break - } + if ac.RegistryToken != "" { + // Even containerd/CRI does not support RegistryToken as of v1.4.3, + // so, nobody is actually using RegistryToken? + log.L.Warnf("ac.RegistryToken (for %q) is not supported yet (FIXME)", rHost.Host) } - } - // credsFunc can be nil here - return credFunc, nil -} -func isAuthConfigEmpty(ac dockercliconfigtypes.AuthConfig) bool { - if ac.IdentityToken != "" || ac.Username != "" || ac.Password != "" || ac.RegistryToken != "" { - return false + return ac.Username, ac.Password, nil } - return true + + return credFunc, nil } diff --git a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver_util.go b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver_util.go deleted file mode 100644 index b452425e7ba..00000000000 --- a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver_util.go +++ /dev/null @@ -1,50 +0,0 @@ -/* - 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. -*/ - -/* - Portions from https://github.com/moby/moby/blob/v20.10.18/registry/auth.go#L154-L167 - Copyright (C) Docker/Moby authors. - Licensed under the Apache License, Version 2.0 - NOTICE: https://github.com/moby/moby/blob/v20.10.18/NOTICE -*/ - -package dockerconfigresolver - -import ( - "strings" -) - -// IndexServer is used for user auth and image search -// -// From https://github.com/moby/moby/blob/v20.10.18/registry/config.go#L36-L39 -const IndexServer = "https://index.docker.io/v1/" - -// ConvertToHostname converts a registry url which has http|https prepended -// to just an hostname. -// -// From https://github.com/moby/moby/blob/v20.10.18/registry/auth.go#L154-L167 -func ConvertToHostname(url string) string { - stripped := url - if strings.HasPrefix(url, "http://") { - stripped = strings.TrimPrefix(url, "http://") - } else if strings.HasPrefix(url, "https://") { - stripped = strings.TrimPrefix(url, "https://") - } - - nameParts := strings.SplitN(stripped, "/", 2) - - return nameParts[0] -} diff --git a/pkg/imgutil/dockerconfigresolver/registryurl.go b/pkg/imgutil/dockerconfigresolver/registryurl.go new file mode 100644 index 00000000000..57566aee58d --- /dev/null +++ b/pkg/imgutil/dockerconfigresolver/registryurl.go @@ -0,0 +1,134 @@ +/* + 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 dockerconfigresolver + +import ( + "errors" + "fmt" + "net" + "net/url" + "strings" +) + +// Parse will return a normalized Docker Registry url from the provided string address +func Parse(address string) (*RegistryURL, error) { + var err error + // No address or address as docker.io? Default to standardized index + if address == "" || address == "docker.io" { + address = dockerIndexServer + } + // If it has no scheme, slap one just so we can parse + if !strings.Contains(address, "://") { + address = fmt.Sprintf("%s://%s", schemeHTTPS, address) + } + // Parse it + u, err := url.Parse(address) + if err != nil { + return nil, errors.Join(ErrUnparsableURL, err) + } + sch := scheme(u.Scheme) + // Scheme is entirely disregarded anyhow, so, just drop it all and set to https + if sch == schemeHTTP { + u.Scheme = string(schemeHTTPS) + } else if sch != schemeHTTPS && sch != schemeNerdctlExperimental { + // Docker is wildly buggy when it comes to non-http schemes. Being more defensive. + return nil, ErrUnsupportedScheme + } + // If it has no port, add the standard port explicitly + if u.Port() == "" { + u.Host = u.Hostname() + ":" + standardHTTPSPort + } + reg := &RegistryURL{URL: *u} + queryParams := u.Query() + nsQuery := queryParams.Get(namespaceQueryParameter) + if nsQuery != "" { + reg.Namespace, err = Parse(nsQuery) + if err != nil { + return nil, err + } + } + return reg, nil +} + +// RegistryURL is a struct that represents a registry namespace or host, meant specifically to deal with +// credentials storage and retrieval inside Docker config file. +type RegistryURL struct { + url.URL + Namespace *RegistryURL +} + +// CanonicalIdentifier returns the identifier expected to be used to save credentials to docker auth config +func (rn *RegistryURL) CanonicalIdentifier() string { + // If it is the docker index over https, port 443, on the /v1/ path, we use the docker fully qualified identifier + if rn.Scheme == string(schemeHTTPS) && rn.Hostname() == "index.docker.io" && rn.Path == "/v1/" && rn.Port() == standardHTTPSPort || + rn.URL.String() == dockerIndexServer { + return dockerIndexServer + } + // Otherwise, for anything else, we use the hostname+port part + identifier := rn.Host + // If this is a namespaced entry, wrap it, and slap the path as well, as hosts are allowed to be non-compliant + if rn.Namespace != nil { + identifier = fmt.Sprintf("%s://%s/host/%s%s", schemeNerdctlExperimental, rn.Namespace.CanonicalIdentifier(), identifier, rn.Path) + } + return identifier +} + +// AllIdentifiers returns a list of identifiers that may have been used to save credentials, +// accounting for legacy formats including scheme, with and without ports +func (rn *RegistryURL) AllIdentifiers() []string { + canonicalID := rn.CanonicalIdentifier() + fullList := []string{ + // This is rn.Host, and always have a port (see parsing) + canonicalID, + } + // If the canonical identifier points to Docker Hub, or is one of our experimental ids, there is no alternative / legacy id + if canonicalID == dockerIndexServer || rn.Namespace != nil { + return fullList + } + + // Docker behavior: if the domain was index.docker.io over 443, we are allowed to additionally read the canonical + // docker credentials + if rn.Hostname() == "index.docker.io" && rn.Port() == standardHTTPSPort { + fullList = append(fullList, dockerIndexServer) + } + + // Add legacy variants + fullList = append(fullList, + fmt.Sprintf("%s://%s", schemeHTTPS, rn.Host), + fmt.Sprintf("%s://%s", schemeHTTP, rn.Host), + ) + + // Note that docker does not try to be smart wrt explicit port vs. implied port + // If standard port, allow retrieving credentials from the variant without a port as well + if rn.Port() == standardHTTPSPort { + fullList = append( + fullList, + rn.Hostname(), + fmt.Sprintf("%s://%s", schemeHTTPS, rn.Hostname()), + fmt.Sprintf("%s://%s", schemeHTTP, rn.Hostname()), + ) + } + + return fullList +} + +func (rn *RegistryURL) IsLocalhost() bool { + // Containerd exposes both a IsLocalhost and a MatchLocalhost method + // There does not seem to be a clear reason for the duplication, nor the differences in implementation. + // Either way, they both reparse the host with net.SplitHostPort, which is unnecessary here + return rn.Hostname() == "localhost" || net.ParseIP(rn.Hostname()).IsLoopback() +} diff --git a/pkg/imgutil/dockerconfigresolver/registryurl_test.go b/pkg/imgutil/dockerconfigresolver/registryurl_test.go new file mode 100644 index 00000000000..02bb0eb64c4 --- /dev/null +++ b/pkg/imgutil/dockerconfigresolver/registryurl_test.go @@ -0,0 +1,189 @@ +/* + 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 dockerconfigresolver + +import ( + "testing" + + "gotest.tools/v3/assert" +) + +func TestURLParsingAndID(t *testing.T) { + tests := []struct { + address string + error error + identifier string + allIDs []string + isLocalhost bool + }{ + { + address: "∞://", + error: ErrUnparsableURL, + }, + { + address: "whatever://", + error: ErrUnsupportedScheme, + }, + { + address: "https://index.docker.io/v1/", + identifier: "https://index.docker.io/v1/", + allIDs: []string{"https://index.docker.io/v1/"}, + }, + { + address: "index.docker.io", + identifier: "index.docker.io:443", + allIDs: []string{ + "index.docker.io:443", + "https://index.docker.io/v1/", + "https://index.docker.io:443", "http://index.docker.io:443", + "index.docker.io", "https://index.docker.io", "http://index.docker.io", + }, + }, + { + address: "index.docker.io/whatever", + identifier: "index.docker.io:443", + allIDs: []string{ + "index.docker.io:443", + "https://index.docker.io/v1/", + "https://index.docker.io:443", "http://index.docker.io:443", + "index.docker.io", "https://index.docker.io", "http://index.docker.io", + }, + }, + { + address: "http://index.docker.io", + identifier: "index.docker.io:443", + allIDs: []string{ + "index.docker.io:443", + "https://index.docker.io/v1/", + "https://index.docker.io:443", "http://index.docker.io:443", + "index.docker.io", "https://index.docker.io", "http://index.docker.io", + }, + }, + { + address: "index.docker.io:80", + identifier: "index.docker.io:80", + allIDs: []string{ + "index.docker.io:80", + "https://index.docker.io:80", "http://index.docker.io:80", + }, + }, + { + address: "index.docker.io:8080", + identifier: "index.docker.io:8080", + allIDs: []string{ + "index.docker.io:8080", + "https://index.docker.io:8080", "http://index.docker.io:8080", + }, + }, + { + address: "foo.docker.io", + identifier: "foo.docker.io:443", + allIDs: []string{ + "foo.docker.io:443", "https://foo.docker.io:443", "http://foo.docker.io:443", + "foo.docker.io", "https://foo.docker.io", "http://foo.docker.io", + }, + }, + { + address: "docker.io", + identifier: "https://index.docker.io/v1/", + allIDs: []string{"https://index.docker.io/v1/"}, + }, + { + address: "docker.io/whatever", + identifier: "docker.io:443", + allIDs: []string{ + "docker.io:443", "https://docker.io:443", "http://docker.io:443", + "docker.io", "https://docker.io", "http://docker.io", + }, + }, + { + address: "http://docker.io", + identifier: "docker.io:443", + allIDs: []string{ + "docker.io:443", "https://docker.io:443", "http://docker.io:443", + "docker.io", "https://docker.io", "http://docker.io", + }, + }, + { + address: "docker.io:80", + identifier: "docker.io:80", + allIDs: []string{ + "docker.io:80", + "https://docker.io:80", "http://docker.io:80", + }, + }, + { + address: "docker.io:8080", + identifier: "docker.io:8080", + allIDs: []string{ + "docker.io:8080", + "https://docker.io:8080", "http://docker.io:8080", + }, + }, + { + address: "anything/whatever?u=v&w=y;foo=bar#frag=o", + identifier: "anything:443", + allIDs: []string{ + "anything:443", "https://anything:443", "http://anything:443", + "anything", "https://anything", "http://anything", + }, + }, + { + address: "https://registry-host.com/subpath/something?bar=bar&ns=registry-namespace.com&foo=foo", + identifier: "nerdctl-experimental://registry-namespace.com:443/host/registry-host.com:443/subpath/something", + allIDs: []string{ + "nerdctl-experimental://registry-namespace.com:443/host/registry-host.com:443/subpath/something", + }, + }, + { + address: "localhost:1234", + identifier: "localhost:1234", + allIDs: []string{ + "localhost:1234", "https://localhost:1234", "http://localhost:1234", + }, + }, + { + address: "127.0.0.1:1234", + identifier: "127.0.0.1:1234", + allIDs: []string{ + "127.0.0.1:1234", "https://127.0.0.1:1234", "http://127.0.0.1:1234", + }, + }, + { + address: "[::1]:1234", + identifier: "[::1]:1234", + allIDs: []string{ + "[::1]:1234", "https://[::1]:1234", "http://[::1]:1234", + }, + }, + } + + for _, tc := range tests { + t.Run(tc.address, func(t *testing.T) { + reg, err := Parse(tc.address) + assert.ErrorIs(t, err, tc.error) + if err == nil { + assert.Equal(t, reg.CanonicalIdentifier(), tc.identifier) + allIDs := reg.AllIdentifiers() + assert.Equal(t, len(allIDs), len(tc.allIDs)) + for k, v := range tc.allIDs { + assert.Equal(t, allIDs[k], v) + } + } + }) + } +} diff --git a/pkg/testutil/testregistry/testregistry_linux.go b/pkg/testutil/testregistry/testregistry_linux.go index 811176c4c3c..61342b1a28f 100644 --- a/pkg/testutil/testregistry/testregistry_linux.go +++ b/pkg/testutil/testregistry/testregistry_linux.go @@ -17,6 +17,8 @@ package testregistry import ( + "crypto/rand" + "encoding/base64" "fmt" "net" "os" @@ -68,6 +70,8 @@ func EnsureImages(base *testutil.Base) { } func NewAuthServer(base *testutil.Base, ca *testca.CA, port int, user, pass string, tls bool) *TokenAuthServer { + EnsureImages(base) + name := testutil.Identifier(base.T) // listen on 0.0.0.0 to enable 127.0.0.1 listenIP := net.ParseIP("0.0.0.0") @@ -339,7 +343,7 @@ func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundC var cert *testca.Cert if ca != nil { scheme = "https" - cert = ca.NewCert(hostIP.String(), "127.0.0.1") + cert = ca.NewCert(hostIP.String(), "127.0.0.1", "localhost", "::1") args = append(args, "--env", "REGISTRY_HTTP_TLS_CERTIFICATE=/registry/domain.crt", "--env", "REGISTRY_HTTP_TLS_KEY=/registry/domain.key", @@ -394,6 +398,10 @@ func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundC if err != nil { return "", err } + err = generateCertsd(hDir, ca.CertPath, "localhost", port) + if err != nil { + return "", err + } if port == 443 { err = generateCertsd(hDir, ca.CertPath, hostIP.String(), 0) if err != nil { @@ -403,6 +411,10 @@ func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundC if err != nil { return "", err } + err = generateCertsd(hDir, ca.CertPath, "localhost", 0) + if err != nil { + return "", err + } } } @@ -468,3 +480,17 @@ func NewWithBasicAuth(base *testutil.Base, user, pass string, port int, tls bool } return NewRegistry(base, ca, port, auth, nil) } + +func SafeRandomString(n int) string { + b := make([]byte, n) + l, err := rand.Read(b) + if err != nil { + panic(err) + } + if l != n { + panic(fmt.Errorf("expected %d bytes, got %d bytes", n, l)) + } + // XXX WARNING there is something in the registry (or more likely in the way we generate htpasswd files) + // that is broken and does not resist truly random strings + return base64.URLEncoding.EncodeToString(b) +} diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 8b3653b82fd..a7237ad6c82 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -401,7 +401,7 @@ func (c *Cmd) AssertOK() { func (c *Cmd) AssertFail() { c.Base.T.Helper() res := c.runIfNecessary() - assert.Assert(c.Base.T, res.ExitCode != 0) + assert.Assert(c.Base.T, res.ExitCode != 0, res) } func (c *Cmd) AssertExitCode(exitCode int) { From 92188e112bba3308a7ab45bf2a9fed083086f811 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 27 Aug 2024 17:49:44 -0700 Subject: [PATCH 0736/1066] Add generic filestore Signed-off-by: apostasie --- pkg/store/filestore.go | 384 +++++++++++++++++++++++++++++++++ pkg/store/filestore_test.go | 220 +++++++++++++++++++ pkg/store/filestore_unix.go | 43 ++++ pkg/store/filestore_windows.go | 45 ++++ pkg/store/store.go | 98 +++++++++ 5 files changed, 790 insertions(+) create mode 100644 pkg/store/filestore.go create mode 100644 pkg/store/filestore_test.go create mode 100644 pkg/store/filestore_unix.go create mode 100644 pkg/store/filestore_windows.go create mode 100644 pkg/store/store.go diff --git a/pkg/store/filestore.go b/pkg/store/filestore.go new file mode 100644 index 00000000000..ec0d98b3585 --- /dev/null +++ b/pkg/store/filestore.go @@ -0,0 +1,384 @@ +/* + 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 store + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "strings" + "sync" + + "github.com/containerd/nerdctl/v2/pkg/lockutil" +) + +// TODO: implement a read-lock in lockutil, in addition to the current exclusive write-lock +// This might improve performance in case of (mostly read) massively parallel concurrent scenarios + +const ( + // Default filesystem permissions to use when creating dir or files + defaultFilePerm = 0o600 + defaultDirPerm = 0o700 +) + +// New returns a filesystem based Store implementation that satisfies both Manager and Locker +// Note that atomicity is "guaranteed" by `os.Rename`, which arguably is not *always* atomic. +// In particular, operating-system crashes may break that promise, and windows behavior is probably questionable. +// That being said, this is still a much better solution than writing directly to the destination file. +func New(rootPath string, dirPerm os.FileMode, filePerm os.FileMode) (Store, error) { + if rootPath == "" { + return nil, errors.Join(ErrInvalidArgument, fmt.Errorf("FileStore rootPath cannot be empty")) + } + + if dirPerm == 0 { + dirPerm = defaultDirPerm + } + + if filePerm == 0 { + filePerm = defaultFilePerm + } + + if err := os.MkdirAll(rootPath, dirPerm); err != nil { + return nil, errors.Join(ErrSystemFailure, err) + } + + return &fileStore{ + dir: rootPath, + dirPerm: dirPerm, + filePerm: filePerm, + }, nil +} + +type fileStore struct { + mutex sync.RWMutex + dir string + locked *os.File + dirPerm os.FileMode + filePerm os.FileMode +} + +func (vs *fileStore) Lock() error { + vs.mutex.Lock() + + dirFile, err := lockutil.Lock(vs.dir) + if err != nil { + return errors.Join(ErrLockFailure, err) + } + + vs.locked = dirFile + + return nil +} + +func (vs *fileStore) Release() error { + if vs.locked == nil { + return errors.Join(ErrFaultyImplementation, fmt.Errorf("cannot unlock already unlocked volume store %q", vs.dir)) + } + + defer vs.mutex.Unlock() + + defer func() { + vs.locked = nil + }() + + if err := lockutil.Unlock(vs.locked); err != nil { + return errors.Join(ErrLockFailure, err) + } + + return nil +} + +func (vs *fileStore) WithLock(fun func() error) (err error) { + if err = vs.Lock(); err != nil { + return err + } + + defer func() { + err = errors.Join(vs.Release(), err) + }() + + return fun() +} + +func (vs *fileStore) Get(key ...string) ([]byte, error) { + if vs.locked == nil { + return nil, errors.Join(ErrFaultyImplementation, fmt.Errorf("operations on the store must use locking")) + } + + if err := validateAllPathComponents(key...); err != nil { + return nil, err + } + + path := filepath.Join(append([]string{vs.dir}, key...)...) + + st, err := os.Stat(path) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil, errors.Join(ErrNotFound, fmt.Errorf("%q does not exist", filepath.Join(key...))) + } + + return nil, errors.Join(ErrSystemFailure, err) + } + + if st.IsDir() { + return nil, errors.Join(ErrFaultyImplementation, fmt.Errorf("%q is a directory and cannot be read as a file", path)) + } + + content, err := os.ReadFile(filepath.Join(append([]string{vs.dir}, key...)...)) + if err != nil { + return nil, errors.Join(ErrSystemFailure, err) + } + + return content, nil +} + +func (vs *fileStore) Exists(key ...string) (bool, error) { + if err := validateAllPathComponents(key...); err != nil { + return false, err + } + + path := filepath.Join(append([]string{vs.dir}, key...)...) + + _, err := os.Stat(filepath.Join(path)) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return false, nil + } + + return false, errors.Join(ErrSystemFailure, err) + } + + return true, nil +} + +func (vs *fileStore) Set(data []byte, key ...string) error { + if vs.locked == nil { + return errors.Join(ErrFaultyImplementation, fmt.Errorf("operations on the store must use locking")) + } + + if err := validateAllPathComponents(key...); err != nil { + return err + } + + fileName := key[len(key)-1] + parent := vs.dir + + if len(key) > 1 { + parent = filepath.Join(append([]string{parent}, key[0:len(key)-1]...)...) + err := os.MkdirAll(parent, vs.dirPerm) + if err != nil { + return errors.Join(ErrSystemFailure, err) + } + } + + dest := filepath.Join(parent, fileName) + st, err := os.Stat(dest) + if err == nil { + if st.IsDir() { + return errors.Join(ErrFaultyImplementation, fmt.Errorf("%q is a directory and cannot be written to", dest)) + } + } + + return atomicWrite(parent, fileName, vs.filePerm, data) +} + +func (vs *fileStore) List(key ...string) ([]string, error) { + if vs.locked == nil { + return nil, errors.Join(ErrFaultyImplementation, fmt.Errorf("operations on the store must use locking")) + } + + // Unlike Get, Set and Delete, List can have zero length key + for _, k := range key { + if err := validatePathComponent(k); err != nil { + return nil, err + } + } + + path := filepath.Join(append([]string{vs.dir}, key...)...) + + st, err := os.Stat(path) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil, errors.Join(ErrNotFound, err) + } + + return nil, errors.Join(ErrSystemFailure, err) + } + + if !st.IsDir() { + return nil, errors.Join(ErrFaultyImplementation, fmt.Errorf("%q is not a directory and cannot be enumerated", path)) + } + + dirEntries, err := os.ReadDir(path) + if err != nil { + return nil, errors.Join(ErrSystemFailure, err) + } + + entries := []string{} + for _, dirEntry := range dirEntries { + entries = append(entries, dirEntry.Name()) + } + + return entries, nil +} + +func (vs *fileStore) Delete(key ...string) error { + if vs.locked == nil { + return errors.Join(ErrFaultyImplementation, fmt.Errorf("operations on the store must use locking")) + } + + if err := validateAllPathComponents(key...); err != nil { + return err + } + + path := filepath.Join(append([]string{vs.dir}, key...)...) + + _, err := os.Stat(path) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return errors.Join(ErrNotFound, err) + } + + return errors.Join(ErrSystemFailure, err) + } + + if err = os.RemoveAll(path); err != nil { + return errors.Join(ErrSystemFailure, err) + } + + return nil +} + +func (vs *fileStore) Location(key ...string) (string, error) { + if err := validateAllPathComponents(key...); err != nil { + return "", err + } + + return filepath.Join(append([]string{vs.dir}, key...)...), nil +} + +func (vs *fileStore) GroupEnsure(key ...string) error { + if vs.locked == nil { + return errors.Join(ErrFaultyImplementation, fmt.Errorf("operations on the store must use locking")) + } + + if err := validateAllPathComponents(key...); err != nil { + return err + } + + path := filepath.Join(append([]string{vs.dir}, key...)...) + + if err := os.MkdirAll(path, vs.dirPerm); err != nil { + return errors.Join(ErrSystemFailure, err) + } + + return nil +} + +func (vs *fileStore) GroupSize(key ...string) (int64, error) { + if vs.locked == nil { + return 0, errors.Join(ErrFaultyImplementation, fmt.Errorf("operations on the store must use locking")) + } + + if err := validateAllPathComponents(key...); err != nil { + return 0, err + } + + path := filepath.Join(append([]string{vs.dir}, key...)...) + + st, err := os.Stat(path) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return 0, errors.Join(ErrNotFound, err) + } + + return 0, errors.Join(ErrSystemFailure, err) + } + + if !st.IsDir() { + return 0, errors.Join(ErrFaultyImplementation, fmt.Errorf("%q is not a directory", path)) + } + + var size int64 + var walkFn = func(_ string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() { + size += info.Size() + } + return err + } + + err = filepath.Walk(path, walkFn) + if err != nil { + return 0, err + } + + return size, nil +} + +// validatePathComponent will enforce os specific filename restrictions on a single path component +func validatePathComponent(pathComponent string) error { + // https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits + if len(pathComponent) > 255 { + return errors.Join(ErrInvalidArgument, errors.New("identifiers must be stricly shorter than 256 characters")) + } + + if strings.TrimSpace(pathComponent) == "" { + return errors.Join(ErrInvalidArgument, errors.New("identifier cannot be empty")) + } + + if err := validatePlatformSpecific(pathComponent); err != nil { + return errors.Join(ErrInvalidArgument, err) + } + + return nil +} + +// validateAllPathComponents will enforce validation for a slice of components +func validateAllPathComponents(pathComponent ...string) error { + if len(pathComponent) == 0 { + return errors.Join(ErrInvalidArgument, errors.New("you must specify an identifier")) + } + + for _, key := range pathComponent { + if err := validatePathComponent(key); err != nil { + return err + } + } + + return nil +} + +func atomicWrite(parent string, fileName string, perm os.FileMode, data []byte) error { + dest := filepath.Join(parent, fileName) + temp := filepath.Join(parent, ".temp."+fileName) + + err := os.WriteFile(temp, data, perm) + if err != nil { + return errors.Join(ErrSystemFailure, err) + } + + err = os.Rename(temp, dest) + if err != nil { + return errors.Join(ErrSystemFailure, err) + } + + return nil +} diff --git a/pkg/store/filestore_test.go b/pkg/store/filestore_test.go new file mode 100644 index 00000000000..2496b96cbb1 --- /dev/null +++ b/pkg/store/filestore_test.go @@ -0,0 +1,220 @@ +/* + 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 store + +import ( + "testing" + "time" + + "gotest.tools/v3/assert" +) + +func TestFileStoreBasics(t *testing.T) { + tempDir := t.TempDir() + + // Creation + tempStore, err := New(tempDir, 0, 0) + assert.NilError(t, err, "temporary store creation should succeed") + + // Lock acquisition + err = tempStore.Lock() + assert.NilError(t, err, "acquiring a lock should succeed") + err = tempStore.Release() + assert.NilError(t, err, "releasing a lock should succeed") + + // Non-existent keys + _ = tempStore.Lock() + defer tempStore.Release() + + _, err = tempStore.Get("nonexistent") + assert.ErrorIs(t, err, ErrNotFound, "getting a non existent key should ErrNotFound") + + err = tempStore.Delete("nonexistent") + assert.ErrorIs(t, err, ErrNotFound, "deleting a non existent key should ErrNotFound") + + _, err = tempStore.List("nonexistent") + assert.ErrorIs(t, err, ErrNotFound, "listing a non existent key should ErrNotFound") + + doesExist, err := tempStore.Exists("nonexistent") + assert.NilError(t, err, "exist should not error") + assert.Assert(t, !doesExist, "should not exist") + + // Listing empty store + result, err := tempStore.List() + assert.NilError(t, err, "listing store root should succeed") + assert.Assert(t, len(result) == 0, "list empty store return zero length slice") + + // Invalid keys + _, err = tempStore.Get("..") + assert.ErrorIs(t, err, ErrInvalidArgument, "unsupported characters or patterns should return ErrInvalidArgument") + + err = tempStore.Set([]byte("foo"), "..") + assert.ErrorIs(t, err, ErrInvalidArgument, "unsupported characters or patterns should return ErrInvalidArgument") + + err = tempStore.Delete("..") + assert.ErrorIs(t, err, ErrInvalidArgument, "unsupported characters or patterns should return ErrInvalidArgument") + + _, err = tempStore.List("..") + assert.ErrorIs(t, err, ErrInvalidArgument, "unsupported characters or patterns should return ErrInvalidArgument") + + // Writing, reading, listing, deleting + err = tempStore.Set([]byte("foo"), "something") + assert.NilError(t, err, "write should be successful") + + doesExist, err = tempStore.Exists("something") + assert.NilError(t, err, "exist should not error") + assert.Assert(t, doesExist, "should exist") + + data, err := tempStore.Get("something") + assert.NilError(t, err, "read should be successful") + assert.Assert(t, string(data) == "foo", "written data should be read back") + + result, err = tempStore.List() + assert.NilError(t, err, "listing store root should succeed") + assert.Assert(t, len(result) == 1, "list store with one element should return it") + + // Read from the list key obtained + data, err = tempStore.Get(result[0]) + assert.NilError(t, err, "read should be successful") + assert.Assert(t, string(data) == "foo", "written data should be read back") + + err = tempStore.Delete("something") + assert.NilError(t, err, "delete should be successful") + + doesExist, err = tempStore.Exists("something") + assert.NilError(t, err, "exist should not error") + assert.Assert(t, !doesExist, "should not exist") + + result, err = tempStore.List() + assert.NilError(t, err, "listing store root should succeed") + assert.Assert(t, len(result) == 0, "list store should return it empty slice") +} + +func TestFileStoreGroups(t *testing.T) { + tempDir := t.TempDir() + + // Creation + tempStore, err := New(tempDir, 0, 0) + assert.NilError(t, err, "temporary store creation should succeed") + + _ = tempStore.Lock() + defer tempStore.Release() + + err = tempStore.Set([]byte("foo"), "group", "subgroup", "actualkey") + assert.NilError(t, err, "write should be successful") + + doesExist, err := tempStore.Exists("group", "subgroup", "actualkey") + assert.NilError(t, err, "exist should not error") + assert.Assert(t, doesExist, "should exist") + + data, err := tempStore.Get("group", "subgroup", "actualkey") + assert.NilError(t, err, "read should be successful") + assert.Assert(t, string(data) == "foo", "written data should be read back") + + result, err := tempStore.List() + assert.NilError(t, err, "listing store root should succeed") + assert.Assert(t, len(result) == 1) + assert.Assert(t, result[0] == "group") + + result, err = tempStore.List("group") + assert.NilError(t, err, "listing store root should succeed") + assert.Assert(t, len(result) == 1) + assert.Assert(t, result[0] == "subgroup") + + result, err = tempStore.List("group", "subgroup") + assert.NilError(t, err, "listing store root should succeed") + assert.Assert(t, len(result) == 1) + assert.Assert(t, result[0] == "actualkey") + + err = tempStore.Delete("group", "subgroup", "actualkey") + assert.NilError(t, err, "delete should be successful") + + doesExist, err = tempStore.Exists("group", "subgroup", "actualkey") + assert.NilError(t, err, "exist should not error") + assert.Assert(t, !doesExist, "should not exist") + + doesExist, err = tempStore.Exists("group", "subgroup") + assert.NilError(t, err, "exist should not error") + assert.Assert(t, doesExist, "should exist") + + err = tempStore.Delete("group", "subgroup") + assert.NilError(t, err, "delete should be successful") + + doesExist, err = tempStore.Exists("group", "subgroup") + assert.NilError(t, err, "exist should not error") + assert.Assert(t, !doesExist, "should not exist") + +} + +func TestFileStoreConcurrent(t *testing.T) { + tempDir := t.TempDir() + + // Creation + tempStore, err := New(tempDir, 0, 0) + assert.NilError(t, err, "temporary store creation should succeed") + + go func() { + lErr := tempStore.WithLock(func() error { + err := tempStore.Set([]byte("routine 1"), "concurrentkey") + assert.NilError(t, err, "writing should not error") + time.Sleep(1 * time.Second) + result, err := tempStore.Get("concurrentkey") + assert.NilError(t, err, "reading should not error") + assert.Assert(t, string(result) == "routine 1") + return nil + }) + assert.NilError(t, lErr, "locking should not error") + }() + + go func() { + time.Sleep(500 * time.Millisecond) + lErr := tempStore.WithLock(func() error { + err := tempStore.Set([]byte("routine 2"), "concurrentkey") + assert.NilError(t, err, "writing should not error") + time.Sleep(1 * time.Second) + result, err := tempStore.Get("concurrentkey") + assert.NilError(t, err, "reading should not error") + assert.Assert(t, string(result) == "routine 2") + return nil + }) + assert.NilError(t, lErr, "locking should not error") + }() + + lErr := tempStore.WithLock(func() error { + err := tempStore.Set([]byte("main routine 1"), "concurrentkey") + assert.NilError(t, err, "writing should not error") + time.Sleep(1 * time.Second) + result, err := tempStore.Get("concurrentkey") + assert.NilError(t, err, "reading should not error") + assert.Assert(t, string(result) == "main routine 1") + return nil + }) + assert.NilError(t, lErr, "locking should not error") + + time.Sleep(750 * time.Millisecond) + + lErr = tempStore.WithLock(func() error { + err := tempStore.Set([]byte("main routine 2"), "concurrentkey") + assert.NilError(t, err, "writing should not error") + time.Sleep(1 * time.Second) + result, err := tempStore.Get("concurrentkey") + assert.NilError(t, err, "reading should not error") + assert.Assert(t, string(result) == "main routine 2") + return nil + }) + assert.NilError(t, lErr, "locking should not error") +} diff --git a/pkg/store/filestore_unix.go b/pkg/store/filestore_unix.go new file mode 100644 index 00000000000..b694b6fc744 --- /dev/null +++ b/pkg/store/filestore_unix.go @@ -0,0 +1,43 @@ +//go:build unix + +/* + 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 store + +import ( + "fmt" + "regexp" +) + +// Note that Darwin has different restrictions - though, we do not support Darwin at this point... +// https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names +var ( + disallowedKeywords = regexp.MustCompile(`^([.]|[.][.])$`) + reservedCharacters = regexp.MustCompile(`[\x{0}/]`) +) + +func validatePlatformSpecific(pathComponent string) error { + if reservedCharacters.MatchString(pathComponent) { + return fmt.Errorf("identifier %q cannot contain any of the following characters: %q", pathComponent, reservedCharacters) + } + + if disallowedKeywords.MatchString(pathComponent) { + return fmt.Errorf("identifier %q cannot be any of the reserved keywords: %q", pathComponent, disallowedKeywords) + } + + return nil +} diff --git a/pkg/store/filestore_windows.go b/pkg/store/filestore_windows.go new file mode 100644 index 00000000000..9fbfe3e575a --- /dev/null +++ b/pkg/store/filestore_windows.go @@ -0,0 +1,45 @@ +/* + 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 store + +import ( + "fmt" + "regexp" +) + +// See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file +// https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names +var ( + disallowedKeywords = regexp.MustCompile(`(?i)^(con|prn|nul|aux|com[1-9¹²³]|lpt[1-9¹²³])([.].*)?`) + reservedCharacters = regexp.MustCompile(`[\x{0}-\x{1f}<>:"/\\|?*]`) +) + +func validatePlatformSpecific(pathComponent string) error { + if reservedCharacters.MatchString(pathComponent) { + return fmt.Errorf("identifier %q cannot contain any of the following characters: %q", pathComponent, reservedCharacters) + } + + if disallowedKeywords.MatchString(pathComponent) { + return fmt.Errorf("identifier %q cannot be any of the reserved keywords: %q", pathComponent, disallowedKeywords) + } + + if pathComponent[len(pathComponent)-1:] == "." || pathComponent[len(pathComponent)-1:] == " " { + return fmt.Errorf("identifier %q cannot end with a space of dot", pathComponent) + } + + return nil +} diff --git a/pkg/store/store.go b/pkg/store/store.go new file mode 100644 index 00000000000..78b977dfaf9 --- /dev/null +++ b/pkg/store/store.go @@ -0,0 +1,98 @@ +/* + 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 store provides a concurrency-safe lightweight storage solution with a simple interface. +// Embedders should call `Lock` and `defer Release` (or WithLock(func()error)) to wrap operations, +// or series of operations, to ensure secure use. +// Furthermore, a Store implementation must do atomic writes, providing guarantees that interrupted partial writes +// never get committed. +// The Store interface itself is meant to be generic, and alternative stores (memory based, or content-addressable) +// may be implemented that satisfies it. +// This package also provides the default, file based implementation that we are using. +package store + +import ( + "errors" + + "github.com/containerd/errdefs" +) + +var ( + // ErrInvalidArgument may be returned by Get, Set, List, or Delete by specific SafeStore implementations + // (eg: filesystem), when they want to impose implementation dependent restrictions on the identifiers + // (filesystems typically do). + ErrInvalidArgument = errdefs.ErrInvalidArgument + // ErrNotFound may be returned by Get or Delete when the requested key is not present in the store + ErrNotFound = errdefs.ErrNotFound + // ErrSystemFailure may be returned by implementations when an internal failure occurs. + // For example, for a filesystem implementation, failure to create a file will be wrapped by this error. + ErrSystemFailure = errors.New("system failure") + // ErrLockFailure may be returned by ReadLock, WriteLock, or Unlock, when the underlying locking mechanism fails. + // In the case of the filesystem implementation, inability to lock the directory will return it. + ErrLockFailure = errors.New("lock failure") + // ErrFaultyImplementation may be returned by Get or Set when the target key exists and is a dir, + // or by List when the target key is a file + // This is indicative the code using the store is not consistent with what it treats as group, and what it treats as key + // and is definitely a bug in that code + // Missing lock will also trigger this when detected. + ErrFaultyImplementation = errors.New("code needs to be fixed") +) + +// Store represents a store that is able to grant an exclusive lock (ensuring concurrency safety, +// both between go routines and across multiple binaries invocations), and is performing atomic operations. +// Note that Store allows manipulating nested objects: +// - Set([]byte("mykeyvalue"), "group", "subgroup", "my key1") +// - Set([]byte("mykeyvalue"), "group", "subgroup", "my key2") +// - Get("group", "subgroup", "my key1") +// - List("group", "subgroup") +// Note that both Delete and Exists can be applied indifferently to specific keys, or groups. +type Store interface { + Locker + Manager +} + +// Manager describes operations that can be performed on the store +type Manager interface { + // List will return a slice of all subgroups (eg: subdirectories), or keys (eg: files), under a specific group (eg: dir) + // Note that `key...` may be omitted, in which case, all objects' names at the root of the store are returned. + // Example, in the volumestore, List() will return all existing volumes names + List(key ...string) ([]string, error) + // Exists checks that a given key exists + // Example: Exists("meta.json") + Exists(key ...string) (bool, error) + // Get returns the content of a key + Get(key ...string) ([]byte, error) + // Set saves bytes to a key + Set(data []byte, key ...string) error + // Delete removes a key or a group + Delete(key ...string) error + // Location returns the absolute path to a certain resource + // Note that this technically "leaks" (filesystem) implementation details up. + // It is necessary though when we are going to pass these filepath to containerd for eg. + Location(key ...string) (string, error) + + // GroupSize will return the combined size of all objects stored under the group (eg: dir) + GroupSize(key ...string) (int64, error) + // GroupEnsure ensures that a given group (eg: directory) exists + GroupEnsure(key ...string) error +} + +// Locker describes a locking mechanism that can be used to encapsulate operations in a safe way +type Locker interface { + Lock() error + Release() error + WithLock(fun func() error) (err error) +} From c9756a942e3f51fd4e47112d44effe9578442868 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 27 Aug 2024 19:36:52 -0700 Subject: [PATCH 0737/1066] Remove mock for mountutil tests Signed-off-by: apostasie --- pkg/mountutil/mountutil_linux_test.go | 31 ---- pkg/mountutil/mountutil_test.go | 37 +++++ pkg/mountutil/mountutil_windows_test.go | 31 ---- pkg/mountutil/mountutilmock/os.mock.go | 56 -------- .../mountutilmock/volumestore.mock.go | 132 ------------------ 5 files changed, 37 insertions(+), 250 deletions(-) create mode 100644 pkg/mountutil/mountutil_test.go delete mode 100644 pkg/mountutil/mountutilmock/os.mock.go delete mode 100644 pkg/mountutil/mountutilmock/volumestore.mock.go diff --git a/pkg/mountutil/mountutil_linux_test.go b/pkg/mountutil/mountutil_linux_test.go index faa10511e71..80e21542cea 100644 --- a/pkg/mountutil/mountutil_linux_test.go +++ b/pkg/mountutil/mountutil_linux_test.go @@ -22,15 +22,11 @@ import ( "testing" "github.com/opencontainers/runtime-spec/specs-go" - "go.uber.org/mock/gomock" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/containerd/v2/pkg/oci" - - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - mocks "github.com/containerd/nerdctl/v2/pkg/mountutil/mountutilmock" ) // TestParseVolumeOptions tests volume options are parsed as expected. @@ -265,23 +261,6 @@ func TestProcessFlagV(t *testing.T) { }, } - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockVolumeStore := mocks.NewMockVolumeStore(ctrl) - mockVolumeStore. - EXPECT(). - Get(gomock.Any(), false). - Return(&native.Volume{Name: "test_volume", Mountpoint: "/test/volume", Size: 1024}, nil). - AnyTimes() - mockVolumeStore. - EXPECT(). - Create(gomock.Any(), nil). - Return(&native.Volume{Name: "test_volume", Mountpoint: "/test/volume"}, nil).AnyTimes() - - mockOs := mocks.NewMockOs(ctrl) - mockOs.EXPECT().Stat(gomock.Any()).Return(nil, nil).AnyTimes() - for _, tt := range tests { t.Run(tt.rawSpec, func(t *testing.T) { processedVolSpec, err := ProcessFlagV(tt.rawSpec, mockVolumeStore, false) @@ -347,16 +326,6 @@ func TestProcessFlagVAnonymousVolumes(t *testing.T) { }, } - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockVolumeStore := mocks.NewMockVolumeStore(ctrl) - mockVolumeStore. - EXPECT(). - Create(gomock.Any(), []string{}). - Return(&native.Volume{Name: "test_volume", Mountpoint: "/test/volume"}, nil). - AnyTimes() - for _, tt := range tests { t.Run(tt.rawSpec, func(t *testing.T) { processedVolSpec, err := ProcessFlagV(tt.rawSpec, mockVolumeStore, true) diff --git a/pkg/mountutil/mountutil_test.go b/pkg/mountutil/mountutil_test.go new file mode 100644 index 00000000000..619f4269c66 --- /dev/null +++ b/pkg/mountutil/mountutil_test.go @@ -0,0 +1,37 @@ +/* + 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 mountutil + +import ( + "runtime" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" +) + +type MockVolumeStore struct { + volumestore.VolumeStore +} + +func (mv *MockVolumeStore) CreateWithoutLock(name string, labels []string) (*native.Volume, error) { + if runtime.GOOS == "windows" { + return &native.Volume{Name: "test_volume", Mountpoint: "C:\\test\\directory"}, nil + } + return &native.Volume{Name: "test_volume", Mountpoint: "/test/volume"}, nil +} + +var mockVolumeStore = &MockVolumeStore{} diff --git a/pkg/mountutil/mountutil_windows_test.go b/pkg/mountutil/mountutil_windows_test.go index 8ee4725a2cb..661c45c0f5a 100644 --- a/pkg/mountutil/mountutil_windows_test.go +++ b/pkg/mountutil/mountutil_windows_test.go @@ -22,12 +22,8 @@ import ( "testing" "github.com/opencontainers/runtime-spec/specs-go" - "go.uber.org/mock/gomock" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" - - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - mocks "github.com/containerd/nerdctl/v2/pkg/mountutil/mountutilmock" ) func TestParseVolumeOptions(t *testing.T) { @@ -268,23 +264,6 @@ func TestProcessFlagV(t *testing.T) { }, } - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockVolumeStore := mocks.NewMockVolumeStore(ctrl) - mockVolumeStore. - EXPECT(). - Get(gomock.Any(), false). - Return(&native.Volume{Name: "test_volume", Mountpoint: "C:\\test\\directory", Size: 1024}, nil). - AnyTimes() - mockVolumeStore. - EXPECT(). - Create(gomock.Any(), nil). - Return(&native.Volume{Name: "test_volume", Mountpoint: "C:\\test\\directory"}, nil).AnyTimes() - - mockOs := mocks.NewMockOs(ctrl) - mockOs.EXPECT().Stat(gomock.Any()).Return(nil, nil).AnyTimes() - for _, tt := range tests { t.Run(tt.rawSpec, func(t *testing.T) { processedVolSpec, err := ProcessFlagV(tt.rawSpec, mockVolumeStore, true) @@ -342,16 +321,6 @@ func TestProcessFlagVAnonymousVolumes(t *testing.T) { }, } - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockVolumeStore := mocks.NewMockVolumeStore(ctrl) - mockVolumeStore. - EXPECT(). - Create(gomock.Any(), []string{}). - Return(&native.Volume{Name: "test_volume", Mountpoint: "C:\\test\\directory"}, nil). - AnyTimes() - for _, tt := range tests { t.Run(tt.rawSpec, func(t *testing.T) { processedVolSpec, err := ProcessFlagV(tt.rawSpec, mockVolumeStore, true) diff --git a/pkg/mountutil/mountutilmock/os.mock.go b/pkg/mountutil/mountutilmock/os.mock.go deleted file mode 100644 index 3cc1718e5bd..00000000000 --- a/pkg/mountutil/mountutilmock/os.mock.go +++ /dev/null @@ -1,56 +0,0 @@ -/* - 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 mountutilmock - -import ( - "os" - "reflect" - - "go.uber.org/mock/gomock" -) - -type MockOs struct { - ctrl *gomock.Controller - recorder *MockOsMockRecorder -} - -type MockOsMockRecorder struct { - mock *MockOs -} - -func NewMockOs(ctrl *gomock.Controller) *MockOs { - mock := &MockOs{ctrl: ctrl} - mock.recorder = &MockOsMockRecorder{mock} - return mock -} - -func (m *MockOs) EXPECT() *MockOsMockRecorder { - return m.recorder -} - -func (m *MockOs) Stat(name string) (os.FileInfo, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Stat", name) - ret0, _ := ret[0].(os.FileInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -func (m *MockOsMockRecorder) Stat(name any) *gomock.Call { - m.mock.ctrl.T.Helper() - return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Stat", reflect.TypeOf((*MockOs)(nil).Stat), name) -} diff --git a/pkg/mountutil/mountutilmock/volumestore.mock.go b/pkg/mountutil/mountutilmock/volumestore.mock.go deleted file mode 100644 index f4a57f26d7b..00000000000 --- a/pkg/mountutil/mountutilmock/volumestore.mock.go +++ /dev/null @@ -1,132 +0,0 @@ -/* - 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 mountutilmock - -import ( - "reflect" - - "go.uber.org/mock/gomock" - - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" -) - -// MockVolumeStore is a mock of VolumeStore interface -type MockVolumeStore struct { - ctrl *gomock.Controller - recorder *MockVolumeStoreMockRecorder -} - -// MockVolumeStoreMockRecorder is the mock recorder for MockVolumeStore -type MockVolumeStoreMockRecorder struct { - mock *MockVolumeStore -} - -// NewMockVolumeStore creates a new mock instance -func NewMockVolumeStore(ctrl *gomock.Controller) *MockVolumeStore { - mock := &MockVolumeStore{ctrl: ctrl} - mock.recorder = &MockVolumeStoreMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockVolumeStore) EXPECT() *MockVolumeStoreMockRecorder { - return m.recorder -} - -// Create mocks the Create method of VolumeStore -func (m *MockVolumeStore) Create(name string, labels []string) (*native.Volume, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Create", name, labels) - ret0, _ := ret[0].(*native.Volume) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Create indicates an expected call of Create -func (m *MockVolumeStoreMockRecorder) Create(name any, labels any) *gomock.Call { - m.mock.ctrl.T.Helper() - return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Create", reflect.TypeOf((*MockVolumeStore)(nil).Create), name, labels) -} - -// Get mocks the Get method of VolumeStore -func (m *MockVolumeStore) Get(name string, size bool) (*native.Volume, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", name, size) - ret0, _ := ret[0].(*native.Volume) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Get indicates an expected call of Get -func (m *MockVolumeStoreMockRecorder) Get(name any, size any) *gomock.Call { - m.mock.ctrl.T.Helper() - return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Get", reflect.TypeOf((*MockVolumeStore)(nil).Get), name, size) -} - -// List mocks the List method of VolumeStore -func (m *MockVolumeStore) List(size bool) (map[string]native.Volume, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "List", size) - ret0, _ := ret[0].(map[string]native.Volume) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// List indicates an expected call of List -func (m *MockVolumeStoreMockRecorder) List(size any) *gomock.Call { - m.mock.ctrl.T.Helper() - return m.mock.ctrl.RecordCallWithMethodType(m.mock, "List", reflect.TypeOf((*MockVolumeStore)(nil).List), size) -} - -// Remove mocks the Remove method of VolumeStore -func (m *MockVolumeStore) Remove(names []string) (removed []string, warns []error, err error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Remove", names) - ret0, _ := ret[0].([]string) - ret1, _ := ret[1].(error) - return ret0, []error{}, ret1 -} - -// Remove indicates an expected call of Remove -func (m *MockVolumeStoreMockRecorder) Remove(names any) *gomock.Call { - m.mock.ctrl.T.Helper() - return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Remove", reflect.TypeOf((*MockVolumeStore)(nil).Remove), names) -} - -// Lock mocks the Lock method of VolumeStore -func (m *MockVolumeStore) Lock() error { - m.ctrl.T.Helper() - return nil -} - -// Lock indicates an expected call of Lock -func (m *MockVolumeStoreMockRecorder) Lock() *gomock.Call { - m.mock.ctrl.T.Helper() - return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Lock", reflect.TypeOf((*MockVolumeStore)(nil).Lock)) -} - -// Unlock mocks the Unlock method of VolumeStore -func (m *MockVolumeStore) Unlock() error { - m.ctrl.T.Helper() - return nil -} - -// Unlock indicates an expected call of Unlock -func (m *MockVolumeStoreMockRecorder) Unlock() *gomock.Call { - m.mock.ctrl.T.Helper() - return m.mock.ctrl.RecordCallWithMethodType(m.mock, "Unlock", reflect.TypeOf((*MockVolumeStore)(nil).Unlock)) -} From bf89c084719237ea3f7aca1fa0d64bcb9f2f7df4 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 27 Aug 2024 19:39:36 -0700 Subject: [PATCH 0738/1066] Refactor filestores using store.Store Signed-off-by: apostasie --- cmd/nerdctl/namespace/namespace.go | 8 +- pkg/cmd/compose/compose.go | 11 +- pkg/cmd/container/create.go | 9 +- pkg/cmd/container/remove.go | 31 +- pkg/cmd/container/rename.go | 6 +- pkg/cmd/container/run_mount.go | 2 +- pkg/cmd/volume/prune.go | 72 ++- pkg/cmd/volume/rm.go | 39 +- pkg/composer/down.go | 1 + pkg/composer/up_volume.go | 6 +- .../container_network_manager.go | 36 +- .../container_network_manager_linux.go | 8 +- pkg/dnsutil/hostsstore/hostsstore.go | 344 +++++++++---- pkg/dnsutil/hostsstore/updater.go | 137 ------ pkg/dnsutil/hostsstore/updater_test.go | 3 +- pkg/identifiers/validate.go | 4 - pkg/identifiers/validate_other.go | 23 - pkg/identifiers/validate_windows.go | 41 -- pkg/inspecttypes/dockercompat/dockercompat.go | 7 +- pkg/mountutil/mountutil.go | 4 +- pkg/mountutil/volumestore/volumestore.go | 459 ++++++++++-------- pkg/namestore/namestore.go | 194 +++++--- pkg/ocihook/ocihook.go | 63 ++- pkg/ocihook/state/state.go | 135 +++--- 24 files changed, 876 insertions(+), 767 deletions(-) delete mode 100644 pkg/identifiers/validate_other.go delete mode 100644 pkg/identifiers/validate_windows.go diff --git a/cmd/nerdctl/namespace/namespace.go b/cmd/nerdctl/namespace/namespace.go index f83cc956862..6885619d341 100644 --- a/cmd/nerdctl/namespace/namespace.go +++ b/cmd/nerdctl/namespace/namespace.go @@ -18,7 +18,6 @@ package namespace import ( "fmt" - "os" "sort" "strings" "text/tabwriter" @@ -120,13 +119,10 @@ func namespaceLsAction(cmd *cobra.Command, args []string) error { if err != nil { log.L.Warn(err) } else { - volEnts, err := volStore.List(false) + numVolumes, err = volStore.Count() if err != nil { - if !os.IsNotExist(err) { - log.L.Warn(err) - } + log.L.Warn(err) } - numVolumes = len(volEnts) } labels, err := client.NamespaceService().Labels(ctx, ns) diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 7afbd74e0b1..a37013e2aff 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -77,15 +77,8 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op if err != nil { return nil, err } - options.VolumeExists = func(volName string) (bool, error) { - _, volGetErr := volStore.Get(volName, false) - if volGetErr == nil { - return true, nil - } else if errors.Is(volGetErr, errdefs.ErrNotFound) { - return false, nil - } - return false, volGetErr - } + // FIXME: this is racy. See note in up_volume.go + options.VolumeExists = volStore.Exists options.ImageExists = func(ctx context.Context, rawRef string) (bool, error) { refNamed, err := referenceutil.ParseAny(rawRef) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index ff7a3cd52a3..328fe7e6f6a 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -59,12 +59,14 @@ import ( "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/store" "github.com/containerd/nerdctl/v2/pkg/strutil" ) // Create will create a container. func Create(ctx context.Context, client *containerd.Client, args []string, netManager containerutil.NetworkOptionsManager, options types.ContainerCreateOptions) (containerd.Container, func(), error) { - // Acquire an exclusive lock on the volume store until we are done to avoid being raced by other volume operations + // Acquire an exclusive lock on the volume store until we are done to avoid being raced by any other + // volume operations (or any other operation involving volume manipulation) volStore, err := volume.Store(options.GOptions.Namespace, options.GOptions.DataRoot, options.GOptions.Address) if err != nil { return nil, nil, err @@ -73,7 +75,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa if err != nil { return nil, nil, err } - defer volStore.Unlock() + defer volStore.Release() // simulate the behavior of double dash newArg := []string{} @@ -840,7 +842,8 @@ func generateGcFunc(ctx context.Context, container containerd.Container, ns, id, if containerNameStore, errE = namestore.New(dataStore, ns); errE != nil { log.G(ctx).WithError(errE).Warnf("failed to instantiate container name store during cleanup for container %q", id) } - if errE = containerNameStore.Release(name, id); errE != nil { + // Double-releasing may happen with containers started with --rm, so, ignore NotFound errors + if errE := containerNameStore.Release(name, id); errE != nil && !errors.Is(errE, store.ErrNotFound) { log.G(ctx).WithError(errE).Warnf("failed to release container name store for container %q (%s)", name, id) } } diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 93bd16c0255..0445953be73 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -32,13 +32,14 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" - "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/mountutil/volumestore" "github.com/containerd/nerdctl/v2/pkg/namestore" + "github.com/containerd/nerdctl/v2/pkg/store" ) var _ error = ErrContainerStatus{} @@ -128,18 +129,10 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions return err } // Get volume store - volStore, err := volume.Store(globalOptions.Namespace, globalOptions.DataRoot, globalOptions.Address) + volStore, err := volumestore.New(dataStore, globalOptions.Namespace) if err != nil { return err } - // Note: technically, it is not strictly necessary to acquire an exclusive lock on the volume store here. - // Worst case scenario, we would fail removing anonymous volumes later on, which is a soft error, and which would - // only happen if we concurrently tried to remove the same container. - err = volStore.Lock() - if err != nil { - return err - } - defer volStore.Unlock() // Decode IPC ipc, err := ipcutil.DecodeIPCLabel(containerLabels[labels.IPC]) if err != nil { @@ -212,24 +205,34 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions // Enforce release name here in case the poststop hook name release fails - soft failure if name != "" { - if err = nameStore.Release(name, id); err != nil { + // Double-releasing may happen with containers started with --rm, so, ignore NotFound errors + if err := nameStore.Release(name, id); err != nil && !errors.Is(err, store.ErrNotFound) { log.G(ctx).WithError(err).Warnf("failed to release container name %s", name) } } - // De-allocate hosts file - soft failure - if err = hostsstore.DeallocHostsFile(dataStore, containerNamespace, id); err != nil { + hs, err := hostsstore.New(dataStore, containerNamespace) + if err != nil { + log.G(ctx).WithError(err).Warnf("failed to instantiate hostsstore for %q", containerNamespace) + } else if err = hs.DeallocHostsFile(id); err != nil { + // De-allocate hosts file - soft failure log.G(ctx).WithError(err).Warnf("failed to remove hosts file for container %q", id) } // Volume removal is not handled by the poststop hook lifecycle because it depends on removeAnonVolumes option + // Note that the anonymous volume list has been obtained earlier, without locking the volume store. + // Technically, a concurrent operation MAY have deleted these anonymous volumes already at this point, which + // would make this operation here "soft fail". + // This is not a problem per-se, though we will output a warning in that case. if anonVolumesJSON, ok := containerLabels[labels.AnonymousVolumes]; ok && removeAnonVolumes { var anonVolumes []string if err = json.Unmarshal([]byte(anonVolumesJSON), &anonVolumes); err != nil { log.G(ctx).WithError(err).Warnf("failed to unmarshall anonvolume information for container %q", id) } else { var errs []error - _, errs, err = volStore.Remove(anonVolumes) + _, errs, err = volStore.Remove(func() ([]string, []error, error) { + return anonVolumes, nil, nil + }) if err != nil || len(errs) > 0 { log.G(ctx).WithError(err).Warnf("failed to remove anonymous volumes %v", anonVolumes) } diff --git a/pkg/cmd/container/rename.go b/pkg/cmd/container/rename.go index 6c967243b79..ca9ba6828e8 100644 --- a/pkg/cmd/container/rename.go +++ b/pkg/cmd/container/rename.go @@ -44,7 +44,7 @@ func Rename(ctx context.Context, client *containerd.Client, containerID, newCont if err != nil { return err } - hostst, err := hostsstore.NewStore(dataStore) + hostst, err := hostsstore.New(dataStore, options.GOptions.Namespace) if err != nil { return err } @@ -84,7 +84,7 @@ func renameContainer(ctx context.Context, container containerd.Container, newNam labels.Name: name, } namst.Rename(newName, id, name) - hostst.Update(ns, id, name) + hostst.Update(id, name) container.SetLabels(ctx, lbls) } }() @@ -93,7 +93,7 @@ func renameContainer(ctx context.Context, container containerd.Container, newNam return err } if runtime.GOOS == "linux" { - if err = hostst.Update(ns, id, newName); err != nil { + if err = hostst.Update(id, newName); err != nil { log.G(ctx).WithError(err).Warn("failed to update host networking definitions " + "- if your container is using network 'none', this is expected - otherwise, please report this as a bug") } diff --git a/pkg/cmd/container/run_mount.go b/pkg/cmd/container/run_mount.go index b6d0c989bc9..eb9be3aefb2 100644 --- a/pkg/cmd/container/run_mount.go +++ b/pkg/cmd/container/run_mount.go @@ -258,7 +258,7 @@ func generateMountOpts(ctx context.Context, client *containerd.Client, ensuredIm log.G(ctx).Debugf("creating anonymous volume %q, for \"VOLUME %s\"", anonVolName, imgVolRaw) - anonVol, err := volStore.Create(anonVolName, []string{}) + anonVol, err := volStore.CreateWithoutLock(anonVolName, []string{}) if err != nil { return nil, nil, nil, err } diff --git a/pkg/cmd/volume/prune.go b/pkg/cmd/volume/prune.go index f159b99757a..71e6d20e779 100644 --- a/pkg/cmd/volume/prune.go +++ b/pkg/cmd/volume/prune.go @@ -19,10 +19,12 @@ package volume import ( "context" "fmt" + "strings" containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/labels" ) @@ -33,60 +35,50 @@ func Prune(ctx context.Context, client *containerd.Client, options types.VolumeP if err != nil { return err } - err = volStore.Lock() - if err != nil { - return err - } - defer volStore.Unlock() - // Get containers and see which volumes are used - containers, err := client.Containers(ctx) - if err != nil { - return err - } + var toRemove []string // nolint: prealloc - usedVolumesList, err := usedVolumes(ctx, containers) - if err != nil { - return err - } - var removeNames []string // nolint: prealloc - - // Get the list of known volumes from the store - volumes, err := volStore.List(false) - if err != nil { - return err - } + err = volStore.Prune(func(volumes []*native.Volume) ([]string, error) { + // Get containers and see which volumes are used + containers, err := client.Containers(ctx) + if err != nil { + return nil, err + } - // Iterate through the known volumes, making sure we do not remove in-use volumes - // but capture as well anon volumes (if --all was passed) - for _, volume := range volumes { - if _, ok := usedVolumesList[volume.Name]; ok { - continue + usedVolumesList, err := usedVolumes(ctx, containers) + if err != nil { + return nil, err } - if !options.All { - if volume.Labels == nil { + + for _, volume := range volumes { + if _, ok := usedVolumesList[volume.Name]; ok { continue } - val, ok := (*volume.Labels)[labels.AnonymousVolumes] - //skip the named volume and only remove the anonymous volume - if !ok || val != "" { - continue + if !options.All { + if volume.Labels == nil { + continue + } + val, ok := (*volume.Labels)[labels.AnonymousVolumes] + // skip the named volume and only remove the anonymous volume + if !ok || val != "" { + continue + } } + toRemove = append(toRemove, volume.Name) } - removeNames = append(removeNames, volume.Name) - } - // Remove the volumes from that list - removedNames, _, err := volStore.Remove(removeNames) + return toRemove, nil + }) + if err != nil { return err } - if len(removedNames) > 0 { + + if len(toRemove) > 0 { fmt.Fprintln(options.Stdout, "Deleted Volumes:") - for _, name := range removedNames { - fmt.Fprintln(options.Stdout, name) - } + fmt.Fprintln(options.Stdout, strings.Join(toRemove, "\n")) fmt.Fprintln(options.Stdout, "") } + return nil } diff --git a/pkg/cmd/volume/rm.go b/pkg/cmd/volume/rm.go index a7864a801a0..4b01564c009 100644 --- a/pkg/cmd/volume/rm.go +++ b/pkg/cmd/volume/rm.go @@ -33,45 +33,38 @@ import ( ) func Remove(ctx context.Context, client *containerd.Client, volumes []string, options types.VolumeRemoveOptions) error { - // Get the volume store and lock it until we are done. - // This will prevent racing new containers from being created or removed until we are done with the cleanup of volumes volStore, err := Store(options.GOptions.Namespace, options.GOptions.DataRoot, options.GOptions.Address) if err != nil { return err } - err = volStore.Lock() - if err != nil { - return err - } - defer volStore.Unlock() - // Get containers and see which volumes are used containers, err := client.Containers(ctx) if err != nil { return err } - usedVolumesList, err := usedVolumes(ctx, containers) - if err != nil { - return err - } - - volumeNames := []string{} - cannotRemove := []error{} + // Note: to avoid racy behavior, this is called by volStore.Remove *inside a lock* + removableVolumes := func() (volumeNames []string, cannotRemove []error, err error) { + usedVolumesList, err := usedVolumes(ctx, containers) + if err != nil { + return nil, nil, err + } - for _, name := range volumes { - if _, ok := usedVolumesList[name]; ok { - cannotRemove = append(cannotRemove, fmt.Errorf("volume %q is in use (%w)", name, errdefs.ErrFailedPrecondition)) - continue + for _, name := range volumes { + if _, ok := usedVolumesList[name]; ok { + cannotRemove = append(cannotRemove, fmt.Errorf("volume %q is in use (%w)", name, errdefs.ErrFailedPrecondition)) + continue + } + volumeNames = append(volumeNames, name) } - volumeNames = append(volumeNames, name) + + return volumeNames, cannotRemove, nil } - // if err is set, this is a hard filesystem error - removedNames, warns, err := volStore.Remove(volumeNames) + + removedNames, cannotRemove, err := volStore.Remove(removableVolumes) if err != nil { return err } - cannotRemove = append(cannotRemove, warns...) // Otherwise, output on stdout whatever was successful for _, name := range removedNames { fmt.Fprintln(options.Stdout, name) diff --git a/pkg/composer/down.go b/pkg/composer/down.go index 4ebd0d1d09b..d02cf613082 100644 --- a/pkg/composer/down.go +++ b/pkg/composer/down.go @@ -128,6 +128,7 @@ func (c *Composer) downVolume(ctx context.Context, shortName string) error { } // shortName is like "db_data", fullName is like "compose-wordpress_db_data" fullName := vol.Name + // FIXME: this is racy. See note in up_volume.go volExists, err := c.VolumeExists(fullName) if err != nil { return err diff --git a/pkg/composer/up_volume.go b/pkg/composer/up_volume.go index 929d96f40cb..0ab0db1fd7a 100644 --- a/pkg/composer/up_volume.go +++ b/pkg/composer/up_volume.go @@ -42,9 +42,9 @@ func (c *Composer) upVolume(ctx context.Context, shortName string) error { // shortName is like "db_data", fullName is like "compose-wordpress_db_data" fullName := vol.Name - // FIXME: this is racy. By the time we get below to creating the volume, there is no guarantee that things are still fine - // Furthermore, volStore.Get no longer errors if the volume already exists (docker behavior), so, the purpose of this - // call needs to be assessed (it might still error if the name is malformed, or if there is a filesystem error) + // FIXME: this is racy. By the time we get below to creating the volume, there is no guarantee that things are still fine. + // Furthermore, by the time we are done creating all the volumes, they may very well have been destroyed. + // This cannot be fixed without getting rid of the whole "shell-out" approach entirely. volExists, err := c.VolumeExists(fullName) if err != nil { return err diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index fa303ad3e9c..72b6dbb4ad0 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -230,10 +230,18 @@ func (m *containerNetworkManager) getContainerNetworkFilePaths(containerID strin if err != nil { return "", "", "", err } + hostsStore, err := hostsstore.New(dataStore, m.globalOptions.Namespace) + if err != nil { + return "", "", "", err + } hostnamePath := filepath.Join(conStateDir, "hostname") resolvConfPath := filepath.Join(conStateDir, "resolv.conf") - etcHostsPath := hostsstore.HostsPath(dataStore, m.globalOptions.Namespace, containerID) + + etcHostsPath, err := hostsStore.HostsPath(containerID) + if err != nil { + return "", "", "", err + } return hostnamePath, resolvConfPath, etcHostsPath, nil } @@ -380,7 +388,7 @@ func (m *hostNetworkManager) SetupNetworking(ctx context.Context, containerID st } // Get the hostsStore - hs, err := hostsstore.NewStore(dataStore) + hs, err := hostsstore.New(dataStore, container.Labels[labels.Namespace]) if err != nil { return err } @@ -401,7 +409,6 @@ func (m *hostNetworkManager) SetupNetworking(ctx context.Context, containerID st // Prep the meta hsMeta := hostsstore.Meta{ - Namespace: container.Labels[labels.Namespace], ID: container.ID, Hostname: container.Labels[labels.Hostname], ExtraHosts: hosts, @@ -425,20 +432,20 @@ func (m *hostNetworkManager) CleanupNetworking(ctx context.Context, container co return err } - // Get the hostsStore - hs, err := hostsstore.NewStore(dataStore) + // Get labels + lbls, err := container.Labels(ctx) if err != nil { return err } - // Get labels - lbls, err := container.Labels(ctx) + // Get the hostsStore + hs, err := hostsstore.New(dataStore, lbls[labels.Namespace]) if err != nil { return err } // Release - if err = hs.Release(lbls[labels.Namespace], container.ID()); err != nil { + if err = hs.Release(container.ID()); err != nil { return err } @@ -503,11 +510,20 @@ func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containe resolvConfPath := filepath.Join(stateDir, "resolv.conf") copyFileContent("/etc/resolv.conf", resolvConfPath) - etcHostsPath, err := hostsstore.AllocHostsFile(dataStore, m.globalOptions.Namespace, containerID) + hs, err := hostsstore.New(dataStore, m.globalOptions.Namespace) + if err != nil { + return nil, nil, err + } + + content, err := os.ReadFile("/etc/hosts") + if err != nil { + return nil, nil, err + } + + etcHostsPath, err := hs.AllocHostsFile(containerID, content) if err != nil { return nil, nil, err } - copyFileContent("/etc/hosts", etcHostsPath) specs := []oci.SpecOpts{ oci.WithHostNamespace(specs.NetworkNamespace), diff --git a/pkg/containerutil/container_network_manager_linux.go b/pkg/containerutil/container_network_manager_linux.go index 11004f81c85..0afe793781e 100644 --- a/pkg/containerutil/container_network_manager_linux.go +++ b/pkg/containerutil/container_network_manager_linux.go @@ -99,10 +99,16 @@ func (m *cniNetworkManager) ContainerNetworkingOpts(_ context.Context, container } // the content of /etc/hosts is created in OCI Hook - etcHostsPath, err := hostsstore.AllocHostsFile(dataStore, m.globalOptions.Namespace, containerID) + hs, err := hostsstore.New(dataStore, m.globalOptions.Namespace) if err != nil { return nil, nil, err } + + etcHostsPath, err := hs.AllocHostsFile(containerID, []byte("")) + if err != nil { + return nil, nil, err + } + opts = append(opts, withCustomResolvConf(resolvConfPath), withCustomHosts(etcHostsPath)) if m.netOpts.UTSNamespace != UtsNamespaceHost { diff --git a/pkg/dnsutil/hostsstore/hostsstore.go b/pkg/dnsutil/hostsstore/hostsstore.go index 63ce4e9beec..7e32e561468 100644 --- a/pkg/dnsutil/hostsstore/hostsstore.go +++ b/pkg/dnsutil/hostsstore/hostsstore.go @@ -14,89 +14,69 @@ limitations under the License. */ -// Package hostsstore provides the interface for /var/lib/nerdctl//etchosts . -// Prioritize simplicity over scalability. +// Package hostsstore provides the interface for /var/lib/nerdctl//etchosts +// Prioritizes simplicity over scalability. +// All methods perform atomic writes and are safe to use concurrently. +// Note that locking is done per namespace. +// hostsstore is currently by container rename, remove, network managers, and ocihooks +// Finally, NOTE: +// Since we will write to the hosts file after it is mounted in the container, we cannot use our atomic write method +// as the inode would change on rename. +// Henceforth, hosts file mutation uses filesystem methods instead, making it the one exception that has to bypass +// the Store implementation. package hostsstore import ( + "bytes" "encoding/json" "errors" + "fmt" "os" "path/filepath" + "strings" types100 "github.com/containernetworking/cni/pkg/types/100" "github.com/containerd/errdefs" + "github.com/containerd/log" - "github.com/containerd/nerdctl/v2/pkg/lockutil" + "github.com/containerd/nerdctl/v2/pkg/store" ) const ( // hostsDirBasename is the base name of /var/lib/nerdctl//etchosts hostsDirBasename = "etchosts" - // metaJSON is stored as /var/lib/nerdctl//etchosts///meta.json + // metaJSON is stored as hostsDirBasename///meta.json metaJSON = "meta.json" + // hostsFile is stored as hostsDirBasename///hosts + hostsFile = "hosts" ) -// HostsPath returns "/var/lib/nerdctl//etchosts///hosts" -func HostsPath(dataStore, ns, id string) string { - if dataStore == "" || ns == "" || id == "" { - panic(errdefs.ErrInvalidArgument) - } - return filepath.Join(dataStore, hostsDirBasename, ns, id, "hosts") -} +// ErrHostsStore will wrap all errors here +var ErrHostsStore = errors.New("hosts-store error") -// ensureFile ensures a file with permission 0644. -// The file is initialized with no content. -// The dir (if not exists) is created with permission 0700. -func ensureFile(path string) error { - if path == "" { - return errdefs.ErrInvalidArgument - } - dir := filepath.Dir(path) - if err := os.MkdirAll(dir, 0700); err != nil { - return err - } - return os.WriteFile(path, []byte{}, 0644) -} +func New(dataStore string, namespace string) (retStore Store, err error) { + defer func() { + if err != nil { + err = errors.Join(ErrHostsStore, err) + } + }() -// AllocHostsFile is used for creating mount-bindable /etc/hosts file. -// The file is initialized with no content. -func AllocHostsFile(dataStore, ns, id string) (string, error) { - lockDir := filepath.Join(dataStore, hostsDirBasename) - if err := os.MkdirAll(lockDir, 0700); err != nil { - return "", err + if dataStore == "" || namespace == "" { + return nil, store.ErrInvalidArgument } - path := HostsPath(dataStore, ns, id) - fn := func() error { - return ensureFile(path) - } - err := lockutil.WithDirLock(lockDir, fn) - return path, err -} -func DeallocHostsFile(dataStore, ns, id string) error { - lockDir := filepath.Join(dataStore, hostsDirBasename) - if err := os.MkdirAll(lockDir, 0700); err != nil { - return err + st, err := store.New(filepath.Join(dataStore, hostsDirBasename, namespace), 0, 0o644) + if err != nil { + return nil, err } - dirToBeRemoved := filepath.Dir(HostsPath(dataStore, ns, id)) - fn := func() error { - return os.RemoveAll(dirToBeRemoved) - } - return lockutil.WithDirLock(lockDir, fn) -} -func NewStore(dataStore string) (Store, error) { - store := &store{ - dataStore: dataStore, - hostsDirectory: filepath.Join(dataStore, hostsDirBasename), - } - return store, os.MkdirAll(store.hostsDirectory, 0700) + return &hostsStore{ + safeStore: st, + }, nil } type Meta struct { - Namespace string ID string Networks map[string]*types100.Result Hostname string @@ -106,76 +86,254 @@ type Meta struct { type Store interface { Acquire(Meta) error - Release(ns, id string) error - Update(ns, id, newName string) error + Release(id string) error + Update(id, newName string) error + HostsPath(id string) (location string, err error) + DeallocHostsFile(id string) (err error) + AllocHostsFile(id string, content []byte) (location string, err error) } -type store struct { - // dataStore is /var/lib/nerdctl/ - dataStore string - // hostsDirectory is /var/lib/nerdctl//etchosts - hostsDirectory string +type hostsStore struct { + safeStore store.Store } -func (x *store) Acquire(meta Meta) error { - fn := func() error { - hostsPath := HostsPath(x.dataStore, meta.Namespace, meta.ID) - if err := ensureFile(hostsPath); err != nil { +func (x *hostsStore) Acquire(meta Meta) (err error) { + defer func() { + if err != nil { + err = errors.Join(ErrHostsStore, err) + } + }() + + return x.safeStore.WithLock(func() error { + var loc string + loc, err = x.safeStore.Location(meta.ID, hostsFile) + if err != nil { return err } - metaB, err := json.Marshal(meta) + + if err = os.WriteFile(loc, []byte{}, 0o644); err != nil { + return errors.Join(store.ErrSystemFailure, err) + } + + var content []byte + content, err = json.Marshal(meta) if err != nil { return err } - metaPath := filepath.Join(x.hostsDirectory, meta.Namespace, meta.ID, metaJSON) - if err := os.WriteFile(metaPath, metaB, 0644); err != nil { + + if err = x.safeStore.Set(content, meta.ID, metaJSON); err != nil { return err } - return newUpdater(meta.ID, x.hostsDirectory).update() - } - return lockutil.WithDirLock(x.hostsDirectory, fn) + + return x.updateAllHosts() + }) } // Release is triggered by Poststop hooks. // It is called after the containerd task is deleted but before the delete operation returns. -func (x *store) Release(ns, id string) error { - fn := func() error { - metaPath := filepath.Join(x.hostsDirectory, ns, id, metaJSON) - if _, err := os.Stat(metaPath); errors.Is(err, os.ErrNotExist) { - return nil - } - // We remove "meta.json" but we still retain the "hosts" file - // because it is needed for restarting. The "hosts" is removed on - // `nerdctl rm`. - // https://github.com/rootless-containers/rootlesskit/issues/220#issuecomment-783224610 - if err := os.RemoveAll(metaPath); err != nil { +func (x *hostsStore) Release(id string) (err error) { + // We remove "meta.json" but we still retain the "hosts" file + // because it is needed for restarting. The "hosts" is removed on + // `nerdctl rm`. + // https://github.com/rootless-containers/rootlesskit/issues/220#issuecomment-783224610 + defer func() { + if err != nil { + err = errors.Join(ErrHostsStore, err) + } + }() + + return x.safeStore.WithLock(func() error { + if err = x.safeStore.Delete(id, metaJSON); err != nil { + return err + } + + return x.updateAllHosts() + }) +} + +// AllocHostsFile is used for creating mount-bindable /etc/hosts file. +func (x *hostsStore) AllocHostsFile(id string, content []byte) (location string, err error) { + defer func() { + if err != nil { + err = errors.Join(ErrHostsStore, err) + } + }() + + err = x.safeStore.WithLock(func() error { + err = x.safeStore.GroupEnsure(id) + if err != nil { return err } - return newUpdater(id, x.hostsDirectory).update() + + var loc string + loc, err = x.safeStore.Location(id, hostsFile) + if err != nil { + return err + } + + err = os.WriteFile(loc, content, 0o644) + if err != nil { + err = errors.Join(store.ErrSystemFailure, err) + } + + return err + }) + if err != nil { + return "", err } - return lockutil.WithDirLock(x.hostsDirectory, fn) + + return x.safeStore.Location(id, hostsFile) } -func (x *store) Update(ns, id, newName string) error { - fn := func() error { - metaPath := filepath.Join(x.hostsDirectory, ns, id, metaJSON) - metaB, err := os.ReadFile(metaPath) +func (x *hostsStore) DeallocHostsFile(id string) (err error) { + defer func() { if err != nil { + err = errors.Join(ErrHostsStore, err) + } + }() + + return x.safeStore.WithLock(func() error { return x.safeStore.Delete(id, hostsFile) }) +} + +func (x *hostsStore) HostsPath(id string) (location string, err error) { + defer func() { + if err != nil { + err = errors.Join(ErrHostsStore, err) + } + }() + + return x.safeStore.Location(id, hostsFile) +} + +func (x *hostsStore) Update(id, newName string) (err error) { + defer func() { + if err != nil { + err = errors.Join(ErrHostsStore, err) + } + }() + + return x.safeStore.WithLock(func() error { + var content []byte + if content, err = x.safeStore.Get(id, metaJSON); err != nil { return err } + meta := &Meta{} - if err := json.Unmarshal(metaB, meta); err != nil { + if err = json.Unmarshal(content, meta); err != nil { return err } + meta.Name = newName - metaB, err = json.Marshal(meta) + content, err = json.Marshal(meta) if err != nil { return err } - if err := os.WriteFile(metaPath, metaB, 0644); err != nil { + + if err = x.safeStore.Set(content, id, metaJSON); err != nil { + return err + } + + return x.updateAllHosts() + }) +} + +func (x *hostsStore) updateAllHosts() (err error) { + entries, err := x.safeStore.List() + if err != nil { + return err + } + + metasByEntry := map[string]*Meta{} + metasByIP := map[string]*Meta{} + networkNameByIP := map[string]string{} + + // Phase 1: read all meta files + for _, entry := range entries { + var content []byte + content, err = x.safeStore.Get(entry, metaJSON) + if err != nil { + log.L.WithError(err).Debugf("unable to read %q", entry) + continue + } + meta := &Meta{} + if err = json.Unmarshal(content, meta); err != nil { + log.L.WithError(err).Warnf("unable to unmarshell %q", entry) + continue + } + metasByEntry[entry] = meta + + for netName, cniRes := range meta.Networks { + for _, ipCfg := range cniRes.IPs { + if ip := ipCfg.Address.IP; ip != nil { + if ip.IsLoopback() || ip.IsUnspecified() { + continue + } + ipStr := ip.String() + metasByIP[ipStr] = meta + networkNameByIP[ipStr] = netName + } + } + } + } + + // Phase 2: write hosts files + for _, entry := range entries { + myMeta, ok := metasByEntry[entry] + if !ok { + log.L.WithError(errdefs.ErrNotFound).Debugf("hostsstore metadata %q not found in %q?", metaJSON, entry) + continue + } + + myNetworks := make(map[string]struct{}) + for nwName := range myMeta.Networks { + myNetworks[nwName] = struct{}{} + } + + var content []byte + content, err = x.safeStore.Get(entry, hostsFile) + if err != nil { + log.L.WithError(err).Errorf("unable to retrieve the hosts file for %q", entry) + continue + } + + // parse the hosts file, keep the original host record + // retain custom /etc/hosts entries outside region + var buf bytes.Buffer + if content != nil { + if err = parseHostsButSkipMarkedRegion(&buf, bytes.NewReader(content)); err != nil { + log.L.WithError(err).Errorf("failed to read hosts file for %q", entry) + continue + } + } + + buf.WriteString(fmt.Sprintf("# %s\n", MarkerBegin)) + buf.WriteString("127.0.0.1 localhost localhost.localdomain\n") + buf.WriteString("::1 localhost localhost.localdomain\n") + + // keep extra hosts first + for host, ip := range myMeta.ExtraHosts { + buf.WriteString(fmt.Sprintf("%-15s %s\n", ip, host)) + } + + for ip, netName := range networkNameByIP { + meta := metasByIP[ip] + if line := createLine(netName, meta, myNetworks); len(line) != 0 { + buf.WriteString(fmt.Sprintf("%-15s %s\n", ip, strings.Join(line, " "))) + } + } + + buf.WriteString(fmt.Sprintf("# %s\n", MarkerEnd)) + + var loc string + loc, err = x.safeStore.Location(entry, hostsFile) + if err != nil { return err } - return newUpdater(meta.ID, x.hostsDirectory).update() + + err = os.WriteFile(loc, buf.Bytes(), 0o644) + if err != nil { + log.L.WithError(err).Errorf("failed to write hosts file for %q", entry) + } } - return lockutil.WithDirLock(x.hostsDirectory, fn) + return nil } diff --git a/pkg/dnsutil/hostsstore/updater.go b/pkg/dnsutil/hostsstore/updater.go index 2088c6cbd3c..2b77bb8301d 100644 --- a/pkg/dnsutil/hostsstore/updater.go +++ b/pkg/dnsutil/hostsstore/updater.go @@ -17,146 +17,9 @@ package hostsstore import ( - "bytes" - "encoding/json" - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/containerd/errdefs" - "github.com/containerd/log" - "github.com/containerd/nerdctl/v2/pkg/netutil" ) -// newUpdater creates an updater for hostsD (/var/lib/nerdctl//etchosts) -func newUpdater(id, hostsD string) *updater { - u := &updater{ - id: id, - hostsD: hostsD, - metaByIPStr: make(map[string]*Meta), - nwNameByIPStr: make(map[string]string), - metaByDir: make(map[string]*Meta), - } - return u -} - -// updater is the struct for updater.update() -type updater struct { - id string - hostsD string // "/var/lib/nerdctl//etchosts" - metaByIPStr map[string]*Meta // key: IP string - nwNameByIPStr map[string]string // key: IP string, value: key of Meta.Networks - metaByDir map[string]*Meta // key: "/var/lib/nerdctl//etchosts//" -} - -// update updates the hostsD tree. -// Must be called with a locker for the hostsD directory. -func (u *updater) update() error { - // phase1: read meta.json - if err := u.phase1(); err != nil { - return err - } - // phase2: write hosts - return u.phase2() -} - -// phase1: read meta.json -func (u *updater) phase1() error { - readMetaWF := func(path string, _ os.FileInfo, walkErr error) error { - if walkErr != nil { - return walkErr - } - if filepath.Base(path) != metaJSON { - return nil - } - metaB, err := os.ReadFile(path) - if err != nil { - return err - } - var meta Meta - if err := json.Unmarshal(metaB, &meta); err != nil { - return err - } - u.metaByDir[filepath.Dir(path)] = &meta - for nwName, cniRes := range meta.Networks { - for _, ipCfg := range cniRes.IPs { - if ip := ipCfg.Address.IP; ip != nil { - if ip.IsLoopback() || ip.IsUnspecified() { - continue - } - ipStr := ip.String() - u.metaByIPStr[ipStr] = &meta - u.nwNameByIPStr[ipStr] = nwName - } - } - } - return nil - } - return filepath.Walk(u.hostsD, readMetaWF) -} - -// phase2: write hosts -func (u *updater) phase2() error { - writeHostsWF := func(path string, _ os.FileInfo, walkErr error) error { - if walkErr != nil { - return walkErr - } - if filepath.Base(path) != "hosts" { - return nil - } - dir := filepath.Dir(path) - myMeta, ok := u.metaByDir[dir] - if !ok { - log.L.WithError(errdefs.ErrNotFound).Debugf("hostsstore metadata %q not found in %q?", metaJSON, dir) - return nil - } - myNetworks := make(map[string]struct{}) - for nwName := range myMeta.Networks { - myNetworks[nwName] = struct{}{} - } - - // parse the hosts file, keep the original host record - // retain custom /etc/hosts entries outside region - r, err := os.Open(path) - if err != nil { - return err - } - defer r.Close() - var buf bytes.Buffer - if r != nil { - if err := parseHostsButSkipMarkedRegion(&buf, r); err != nil { - log.L.WithError(err).Warn("failed to read hosts file") - } - } - - buf.WriteString(fmt.Sprintf("# %s\n", MarkerBegin)) - buf.WriteString("127.0.0.1 localhost localhost.localdomain\n") - buf.WriteString("::1 localhost localhost.localdomain\n") - - // keep extra hosts first - for host, ip := range myMeta.ExtraHosts { - buf.WriteString(fmt.Sprintf("%-15s %s\n", ip, host)) - } - - for ip, nwName := range u.nwNameByIPStr { - meta := u.metaByIPStr[ip] - if line := createLine(nwName, meta, myNetworks); len(line) != 0 { - buf.WriteString(fmt.Sprintf("%-15s %s\n", ip, strings.Join(line, " "))) - } - } - - buf.WriteString(fmt.Sprintf("# %s\n", MarkerEnd)) - err = os.WriteFile(path, buf.Bytes(), 0644) - if err != nil { - return err - } - return nil - } - return filepath.Walk(u.hostsD, writeHostsWF) -} - // createLine returns a line string slice. // line is like "foo foo.nw0 bar bar.nw0\n" // for `nerdctl --name=foo --hostname=bar --network=n0`. diff --git a/pkg/dnsutil/hostsstore/updater_test.go b/pkg/dnsutil/hostsstore/updater_test.go index c55f4ae3cd6..03ffefae12b 100644 --- a/pkg/dnsutil/hostsstore/updater_test.go +++ b/pkg/dnsutil/hostsstore/updater_test.go @@ -74,8 +74,7 @@ func TestCreateLine(t *testing.T) { } for _, tc := range testCases { thatMeta := &Meta{ - Namespace: "default", - ID: "984d63ce45ae", + ID: "984d63ce45ae", Networks: map[string]*types100.Result{ tc.thatNetwork: { Interfaces: []*types100.Interface{ diff --git a/pkg/identifiers/validate.go b/pkg/identifiers/validate.go index bb6e62c5aaa..7f5ff3522d3 100644 --- a/pkg/identifiers/validate.go +++ b/pkg/identifiers/validate.go @@ -42,9 +42,5 @@ func ValidateDockerCompat(s string) error { return fmt.Errorf("identifier %q must match pattern %q: %w", s, AllowedIdentfierChars, errdefs.ErrInvalidArgument) } - if err := validatePlatformSpecific(s); err != nil { - return err - } - return nil } diff --git a/pkg/identifiers/validate_other.go b/pkg/identifiers/validate_other.go deleted file mode 100644 index 642c6ac3ae6..00000000000 --- a/pkg/identifiers/validate_other.go +++ /dev/null @@ -1,23 +0,0 @@ -//go:build !windows - -/* - 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 identifiers - -func validatePlatformSpecific(identifier string) error { - return nil -} diff --git a/pkg/identifiers/validate_windows.go b/pkg/identifiers/validate_windows.go deleted file mode 100644 index 64141ed3529..00000000000 --- a/pkg/identifiers/validate_windows.go +++ /dev/null @@ -1,41 +0,0 @@ -/* - 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 identifiers - -import ( - "fmt" - "regexp" - - "github.com/containerd/errdefs" -) - -// See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file - -// Note that ¹²³ is technically not required here since they are out of the regexp for regular validation -var windowsDisallowed = regexp.MustCompile(`^(con|prn|nul|aux|com[1-9¹²³]|lpt[1-9¹²³])([.].*)?`) - -func validatePlatformSpecific(identifier string) error { - if windowsDisallowed.MatchString(identifier) { - return fmt.Errorf("identifier %q must not match reserved windows pattern %q: %w", identifier, windowsDisallowed, errdefs.ErrInvalidArgument) - } - - if identifier[len(identifier)-1:] == "." { - return fmt.Errorf("windows does not allow identifiers ending with a dot or space (%q)", identifier) - } - - return nil -} diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index f1704f1781a..aceec3bca3d 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -292,8 +292,11 @@ func ContainerFromNative(n *native.Container) (*Container, error) { cs.Pid = n.Process.Pid cs.ExitCode = int(n.Process.Status.ExitStatus) if containerAnnotations[labels.StateDir] != "" { - lf := state.NewLifecycleState(containerAnnotations[labels.StateDir]) - if err := lf.WithLock(lf.Load); err == nil && !time.Time.IsZero(lf.StartedAt) { + if lf, err := state.New(containerAnnotations[labels.StateDir]); err != nil { + log.L.WithError(err).Errorf("failed retrieving state") + } else if err = lf.Load(); err != nil { + log.L.WithError(err).Errorf("failed retrieving StartedAt from state") + } else if !time.Time.IsZero(lf.StartedAt) { cs.StartedAt = lf.StartedAt.UTC().Format(time.RFC3339Nano) } } diff --git a/pkg/mountutil/mountutil.go b/pkg/mountutil/mountutil.go index b2a7b90dd30..d55a2cb6646 100644 --- a/pkg/mountutil/mountutil.go +++ b/pkg/mountutil/mountutil.go @@ -189,7 +189,7 @@ func handleAnonymousVolumes(s string, volStore volumestore.VolumeStore) (volumeS res.AnonymousVolume = idgen.GenerateID() log.L.Debugf("creating anonymous volume %q, for %q", res.AnonymousVolume, s) - anonVol, err := volStore.Create(res.AnonymousVolume, []string{}) + anonVol, err := volStore.CreateWithoutLock(res.AnonymousVolume, []string{}) if err != nil { return res, fmt.Errorf("failed to create an anonymous volume %q: %w", res.AnonymousVolume, err) } @@ -204,7 +204,7 @@ func handleNamedVolumes(source string, volStore volumestore.VolumeStore) (volume res.Name = source // Create returns an existing volume or creates a new one if necessary. - vol, err := volStore.Create(res.Name, nil) + vol, err := volStore.CreateWithoutLock(res.Name, nil) if err != nil { return res, fmt.Errorf("failed to get volume %q: %w", res.Name, err) } diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index 20628db56a5..47c1b2bd73e 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -14,297 +14,374 @@ limitations under the License. */ +// Package volumestore allows manipulating containers' volumes. +// All methods are safe to use concurrently (and perform atomic writes), except CreateWithoutLock, which is specifically +// meant to be used multiple times, inside a Lock-ed section. package volumestore import ( "encoding/json" "errors" "fmt" - "os" "path/filepath" - "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/identifiers" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/v2/pkg/lockutil" + "github.com/containerd/nerdctl/v2/pkg/store" "github.com/containerd/nerdctl/v2/pkg/strutil" ) const ( + volumeDirBasename = "volumes" dataDirName = "_data" volumeJSONFileName = "volume.json" ) -// VolumeStore allows manipulating containers' volumes -// Every method is protected by a file lock, and is safe to use concurrently. -// If you need to use multiple methods successively (for example: List, then Remove), you should instead optin -// for an explicit durable lock, by first calling `Lock` then `defer Unlock`. -// This is also true (and important to do) for any operation that is going to inspect containers before going for -// creation or removal of volumes. +// ErrNameStore will wrap all errors here +var ErrVolumeStore = errors.New("volume-store error") + type VolumeStore interface { - Create(name string, labels []string) (*native.Volume, error) + // Exists checks if a given volume exists + Exists(name string) (bool, error) + // Get returns an existing volume Get(name string, size bool) (*native.Volume, error) + // Create will either return an existing volume, or create a new one + // NOTE that different labels will NOT create a new volume if there is one by that name already, + // but instead return the existing one with the (possibly different) labels + Create(name string, labels []string) (vol *native.Volume, err error) + // List returns all existing volumes. + // Note that list is expensive as it reads all volumes individual info List(size bool) (map[string]native.Volume, error) - Remove(names []string) (removed []string, warns []error, err error) + // Remove one of more volumes + Remove(generator func() ([]string, []error, error)) (removed []string, warns []error, err error) + // Prune will call a filtering function expected to return the volumes name to delete + Prune(filter func(volumes []*native.Volume) ([]string, error)) (err error) + // Count returns the number of volumes + Count() (count int, err error) + + // Lock: see store implementation Lock() error - Unlock() error + // CreateWithoutLock will create a volume (or return an existing one). + // This method does NOT lock (unlike Create). + // It is meant to be used between `Lock` and `Release`, and is specifically useful when multiple different volume + // creation will have to happen in different method calls (eg: container create). + CreateWithoutLock(name string, labels []string) (*native.Volume, error) + // Release: see store implementation + Release() error } // New returns a VolumeStore -func New(dataStore, ns string) (VolumeStore, error) { - if dataStore == "" || ns == "" { - return nil, errdefs.ErrInvalidArgument +func New(dataStore, namespace string) (volStore VolumeStore, err error) { + defer func() { + if err != nil { + err = errors.Join(ErrVolumeStore, err) + } + }() + + if dataStore == "" || namespace == "" { + return nil, store.ErrInvalidArgument } - volStoreDir := filepath.Join(dataStore, "volumes", ns) - if err := os.MkdirAll(volStoreDir, 0700); err != nil { + st, err := store.New(filepath.Join(dataStore, volumeDirBasename, namespace), 0, 0o644) + if err != nil { return nil, err } - vs := &volumeStore{ - dir: volStoreDir, - } - return vs, nil + + return &volumeStore{ + Locker: st, + manager: st, + }, nil } type volumeStore struct { - dir string - locked *os.File + // Expose the lock primitives directly to satisfy interface for Lock and Release + store.Locker + + manager store.Manager } -// Lock should be called when you need an exclusive lock on the volume store for an extended period of time -// spanning multiple atomic method calls. -// Be sure to defer Unlock to release it. -func (vs *volumeStore) Lock() error { - if vs.locked != nil { - return fmt.Errorf("cannot lock already locked volume store %q", vs.dir) - } +// Exists checks if a volume exists in the store +func (vs *volumeStore) Exists(name string) (doesExist bool, err error) { + defer func() { + if err != nil { + err = errors.Join(ErrVolumeStore, err) + } + }() - dirFile, err := lockutil.Lock(vs.dir) - if err != nil { - return err + if err = identifiers.ValidateDockerCompat(name); err != nil { + return false, err } - vs.locked = dirFile - return nil + // No need for a lock here, the operation is atomic + return vs.manager.Exists(name) } -// Unlock should be called once done (see Lock) to release the persistent lock on the store -func (vs *volumeStore) Unlock() error { - if vs.locked == nil { - return fmt.Errorf("cannot unlock already unlocked volume store %q", vs.dir) +// Get retrieves a native volume from the store, optionally with its size +func (vs *volumeStore) Get(name string, size bool) (vol *native.Volume, err error) { + defer func() { + if err != nil { + err = errors.Join(ErrVolumeStore, err) + } + }() + + if err = identifiers.ValidateDockerCompat(name); err != nil { + return nil, err } + // If we require the size, this is no longer atomic, so, we need to lock + err = vs.WithLock(func() error { + vol, err = vs.rawGet(name, size) + return err + }) + + return vol, err +} + +// CreateWithoutLock will create a new volume, or return an existing one if there is one already by that name +// It does NOT lock for you - unlike all the other methods - though it *will* error if you do not lock. +// This is on purpose as volume creation in most cases are done during container creation, +// and implies an extended period of time for locking. +// To use: +// volStore.Lock() +// defer volStore.Release() +// volStore.CreateWithoutLock(...) +func (vs *volumeStore) CreateWithoutLock(name string, labels []string) (vol *native.Volume, err error) { defer func() { - vs.locked = nil + if err != nil { + err = errors.Join(ErrVolumeStore, err) + } }() - if err := lockutil.Unlock(vs.locked); err != nil { - return fmt.Errorf("failed to unlock volume store %q: %w", vs.dir, err) + if err = identifiers.ValidateDockerCompat(name); err != nil { + return nil, err } - return nil + + return vs.rawCreate(name, labels) } -// Create will create a new volume, or return an existing one if there is one already by that name -// Besides a possible locking error, it might return ErrInvalidArgument, hard filesystem errors, json errors -func (vs *volumeStore) Create(name string, labels []string) (*native.Volume, error) { - if err := identifiers.ValidateDockerCompat(name); err != nil { - return nil, fmt.Errorf("invalid volume name: %w", err) +func (vs *volumeStore) Create(name string, labels []string) (vol *native.Volume, err error) { + defer func() { + if err != nil { + err = errors.Join(ErrVolumeStore, err) + } + }() + + if err = identifiers.ValidateDockerCompat(name); err != nil { + return nil, err } - volPath := filepath.Join(vs.dir, name) - volDataPath := filepath.Join(volPath, dataDirName) - volFilePath := filepath.Join(volPath, volumeJSONFileName) + err = vs.Locker.WithLock(func() error { + vol, err = vs.rawCreate(name, labels) + return err + }) - vol := &native.Volume{} + return vol, err +} - fn := func() error { - // Failures that are not os.ErrExist must exit here - if err := os.Mkdir(volPath, 0700); err != nil && !errors.Is(err, os.ErrExist) { +func (vs *volumeStore) Count() (count int, err error) { + defer func() { + if err != nil { + err = errors.Join(ErrVolumeStore, err) + } + }() + + err = vs.Locker.WithLock(func() error { + names, err := vs.manager.List() + if err != nil { return err } - if err := os.Mkdir(volDataPath, 0755); err != nil && !errors.Is(err, os.ErrExist) { + + count = len(names) + return nil + }) + + return count, err +} + +func (vs *volumeStore) List(size bool) (res map[string]native.Volume, err error) { + defer func() { + if err != nil { + err = errors.Join(ErrVolumeStore, err) + } + }() + + res = make(map[string]native.Volume) + + err = vs.Locker.WithLock(func() error { + names, err := vs.manager.List() + if err != nil { return err } - volOpts := struct { - Labels map[string]string `json:"labels"` - }{} + for _, name := range names { + vol, err := vs.rawGet(name, size) + if err != nil { + log.L.WithError(err).Errorf("something is wrong with %q", name) + continue + } + res[name] = *vol + } + + return nil + }) + + return res, err +} - if len(labels) > 0 { - volOpts.Labels = strutil.ConvertKVStringsToMap(labels) +// Remove will remove one or more containers +func (vs *volumeStore) Remove(generator func() ([]string, []error, error)) (removed []string, warns []error, err error) { + defer func() { + if err != nil { + err = errors.Join(ErrVolumeStore, err) } + }() - // Failure here must exit, no need to clean-up - labelsJSON, err := json.MarshalIndent(volOpts, "", " ") + err = vs.Locker.WithLock(func() error { + var names []string + names, warns, err = generator() if err != nil { return err } - // If it does not exist - if _, err = os.Stat(volFilePath); err != nil { - // Any other stat error than "not exists", hard exit - if !errors.Is(err, os.ErrNotExist) { - return err + for _, name := range names { + // Invalid name, soft error + if err = identifiers.ValidateDockerCompat(name); err != nil { + // TODO: we are clearly mixing presentation concerns here + // This should be handled by the cli, not here + warns = append(warns, err) + continue } - // Error was does not exist, so, write it - if err = os.WriteFile(volFilePath, labelsJSON, 0644); err != nil { + + // Erroring on Exists is a hard error + // !doesExist is a soft error + // Inability to delete is a hard error + if doesExist, err := vs.manager.Exists(name); err != nil { + return err + } else if !doesExist { + // TODO: see above + warns = append(warns, fmt.Errorf("volume %q: %w", name, store.ErrNotFound)) + continue + } else if err = vs.manager.Delete(name); err != nil { return err } - } else { - log.L.Warnf("volume %q already exists and will be returned as-is", name) - } - // At this point, we either have a volume, or created a new one successfully - vol.Name = name - vol.Mountpoint = volDataPath + // Otherwise, add it the list of successfully removed + removed = append(removed, name) + } return nil - } - - var err error - if vs.locked == nil { - err = lockutil.WithDirLock(vs.dir, fn) - } else { - err = fn() - } - if err != nil { - return nil, err - } + }) - return vol, nil + return removed, warns, err } -// Get retrieves a native volume from the store -// Besides a possible locking error, it might return ErrInvalidArgument, ErrNotFound, or a filesystem error -func (vs *volumeStore) Get(name string, size bool) (*native.Volume, error) { - if err := identifiers.ValidateDockerCompat(name); err != nil { - return nil, fmt.Errorf("invalid volume name: %w", err) - } - volPath := filepath.Join(vs.dir, name) - volDataPath := filepath.Join(volPath, dataDirName) - volFilePath := filepath.Join(volPath, volumeJSONFileName) +func (vs *volumeStore) Prune(filter func(vol []*native.Volume) ([]string, error)) (err error) { + defer func() { + if err != nil { + err = errors.Join(ErrVolumeStore, err) + } + }() - vol := &native.Volume{} + return vs.Locker.WithLock(func() error { + names, err := vs.manager.List() + if err != nil { + return err + } - fn := func() error { - if _, err := os.Stat(volDataPath); err != nil { - if os.IsNotExist(err) { - return fmt.Errorf("%q does not exist in the volume store: %w", name, errdefs.ErrNotFound) + res := []*native.Volume{} + for _, name := range names { + vol, err := vs.rawGet(name, false) + if err != nil { + log.L.WithError(err).Errorf("something is wrong with %q", name) + continue } - return fmt.Errorf("filesystem error reading %q from the volume store: %w", name, err) + res = append(res, vol) } - volumeDataBytes, err := os.ReadFile(volFilePath) + toDelete, err := filter(res) if err != nil { - if os.IsNotExist(err) { - return fmt.Errorf("%q labels file does not exist in the volume store: %w", name, errdefs.ErrNotFound) - } - return fmt.Errorf("filesystem error reading %q from the volume store: %w", name, err) + return err } - vol.Name = name - vol.Mountpoint = volDataPath - vol.Labels = labels(volumeDataBytes) - - if size { - vol.Size, err = volumeSize(vol) + for _, name := range toDelete { + err = vs.manager.Delete(name) if err != nil { - return fmt.Errorf("failed reading volume size for %q from the volume store: %w", name, err) + return err } } + return nil + }) +} + +func (vs *volumeStore) rawGet(name string, size bool) (vol *native.Volume, err error) { + content, err := vs.manager.Get(name, volumeJSONFileName) + if err != nil { + return nil, err } - var err error - if vs.locked == nil { - err = lockutil.WithDirLock(vs.dir, fn) - } else { - err = fn() + vol = &native.Volume{ + Name: name, + Labels: labels(content), } + + vol.Mountpoint, err = vs.manager.Location(name, dataDirName) if err != nil { return nil, err } + if size { + vol.Size, err = vs.manager.GroupSize(name, dataDirName) + if err != nil { + return nil, errors.Join(fmt.Errorf("failed reading volume size for %q", name), err) + } + } + return vol, nil } -// List retrieves all known volumes from the store. -// Besides a possible locking error, it might return ErrNotFound (indicative that the store is in a broken state), or a filesystem error -func (vs *volumeStore) List(size bool) (map[string]native.Volume, error) { - res := map[string]native.Volume{} +func (vs *volumeStore) rawCreate(name string, labels []string) (vol *native.Volume, err error) { + volOpts := struct { + Labels map[string]string `json:"labels"` + }{} - fn := func() error { - dirEntries, err := os.ReadDir(vs.dir) - if err != nil { - return fmt.Errorf("filesystem error while trying to list volumes from the volume store: %w", err) - } + if len(labels) > 0 { + volOpts.Labels = strutil.ConvertKVStringsToMap(labels) + } - for _, dirEntry := range dirEntries { - name := dirEntry.Name() - vol, err := vs.Get(name, size) - if err != nil { - return err - } - res[name] = *vol - } - return nil + // Failure here must exit, no need to clean-up + labelsJSON, err := json.MarshalIndent(volOpts, "", " ") + if err != nil { + return nil, err } - var err error - // Since we are calling Get, we need to acquire a global lock - if vs.locked == nil { - err = vs.Lock() - if err != nil { + if doesExist, err := vs.manager.Exists(name, volumeJSONFileName); err != nil { + return nil, err + } else if !doesExist { + if err = vs.manager.Set(labelsJSON, name, volumeJSONFileName); err != nil { return nil, err } - defer vs.Unlock() + } else { + log.L.Warnf("volume %q already exists and will be returned as-is", name) + // FIXME: we do not check if the existing volume has the same labels as requested - should we? } - err = fn() - if err != nil { - return nil, err + + // At this point, we either have an existing volume, or created a new one successfully + vol = &native.Volume{ + Name: name, } - return res, nil -} -// Remove will remove one or more containers -// Besides a possible locking error, it might return hard filesystem errors -// Any other failure (ErrInvalidArgument, ErrNotFound) is a soft error that will be added the `warns` -func (vs *volumeStore) Remove(names []string) (removed []string, warns []error, err error) { - fn := func() error { - for _, name := range names { - // Invalid name, soft error - if err := identifiers.ValidateDockerCompat(name); err != nil { - warns = append(warns, fmt.Errorf("invalid volume name: %w", err)) - continue - } - dir := filepath.Join(vs.dir, name) - // Does not exist, soft error - if _, err := os.Stat(dir); err != nil { - if os.IsNotExist(err) { - warns = append(warns, fmt.Errorf("no such volume: %s (%w)", name, errdefs.ErrNotFound)) - continue - } - return fmt.Errorf("filesystem error while trying to remove volumes from the volume store: %w", err) - } - // Hard filesystem error, hard error, and stop here - if err := os.RemoveAll(dir); err != nil { - return fmt.Errorf("filesystem error while trying to remove volumes from the volume store: %w", err) - } - // Otherwise, add it the list of successfully removed - removed = append(removed, name) - } - return nil + if err = vs.manager.GroupEnsure(name, dataDirName); err != nil { + return nil, err } - if vs.locked == nil { - err = lockutil.WithDirLock(vs.dir, fn) - } else { - err = fn() + if vol.Mountpoint, err = vs.manager.Location(name, dataDirName); err != nil { + return nil, err } - return removed, warns, err + return vol, nil } // Private helpers @@ -318,21 +395,3 @@ func labels(b []byte) *map[string]string { } return vo.Labels } - -func volumeSize(volume *native.Volume) (int64, error) { - var size int64 - var walkFn = func(_ string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() { - size += info.Size() - } - return err - } - var err = filepath.Walk(volume.Mountpoint, walkFn) - if err != nil { - return 0, err - } - return size, nil -} diff --git a/pkg/namestore/namestore.go b/pkg/namestore/namestore.go index a6b57968c82..6ded12d6c95 100644 --- a/pkg/namestore/namestore.go +++ b/pkg/namestore/namestore.go @@ -14,119 +14,167 @@ limitations under the License. */ +// Package namestore provides a simple store for containers to exclusively acquire and release names. +// All methods are safe to use concurrently. +// Note that locking of the store is done at the namespace level. +// The namestore is currently used by container create, remove, rename, and as part of the ocihook events cycle. package namestore import ( + "errors" "fmt" - "os" "path/filepath" - "strings" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/identifiers" - "github.com/containerd/nerdctl/v2/pkg/lockutil" + "github.com/containerd/nerdctl/v2/pkg/store" ) -func New(dataStore, ns string) (NameStore, error) { - dir := filepath.Join(dataStore, "names", ns) - if err := os.MkdirAll(dir, 0700); err != nil { - return nil, err +// ErrNameStore will wrap all errors here +var ErrNameStore = errors.New("name-store error") + +// New will return a NameStore for a given namespace. +func New(stateDir, namespace string) (NameStore, error) { + if namespace == "" { + return nil, errors.Join(ErrNameStore, store.ErrInvalidArgument) } - store := &nameStore{ - dir: dir, + + st, err := store.New(filepath.Join(stateDir, namespace), 0, 0) + if err != nil { + return nil, errors.Join(ErrNameStore, err) } - return store, nil + + return &nameStore{ + safeStore: st, + }, nil } +// NameStore allows acquiring, releasing and renaming. +// "names" must abide by identifiers.ValidateDockerCompat +// A container cannot release or rename a name it does not own. +// A container cannot acquire a name that is already owned by another container. +// Re-acquiring a name does not error and is a no-op. +// Double releasing a name will error. +// Note that technically a given container may acquire multiple different names, although this is not +// something we do in the codebase. type NameStore interface { + // Acquire exclusively grants `name` to container with `id`. Acquire(name, id string) error + // Acquire allows the container owning a specific name to release it Release(name, id string) error + // Rename allows the container owning a specific name to change it to newName (if available) Rename(oldName, id, newName string) error } type nameStore struct { - dir string + safeStore store.Store } -func (x *nameStore) Acquire(name, id string) error { - if err := identifiers.ValidateDockerCompat(name); err != nil { - return fmt.Errorf("invalid name: %w", err) - } - if strings.TrimSpace(id) != id { - return fmt.Errorf("untrimmed ID %q", id) +func (x *nameStore) Acquire(name, id string) (err error) { + defer func() { + if err != nil { + err = errors.Join(ErrNameStore, err) + } + }() + + if err = identifiers.ValidateDockerCompat(name); err != nil { + return err } - fn := func() error { - fileName := filepath.Join(x.dir, name) - if b, err := os.ReadFile(fileName); err == nil { - if strings.TrimSpace(string(b)) == "" { - // currently acquired for an empty id - this obviously should never happen - // this is recoverable, and we are not hard erroring, but still indicative that something was wrong - // https://github.com/containerd/nerdctl/issues/3351 - log.L.Errorf("current name %q is reserved for a an empty id - please report this is as a bug", name) - } else if string(b) != id { - // if acquired by a different container, we error out here - return fmt.Errorf("name %q is already used by ID %q", name, string(b)) + + return x.safeStore.WithLock(func() error { + var previousID []byte + previousID, err = x.safeStore.Get(name) + if err != nil { + if !errors.Is(err, store.ErrNotFound) { + return err } - // Otherwise, this is just re-acquiring after a restart - // For example, if containerd was bounced, previously running containers that would get restarted will go - // again through onCreateRuntime (unlike in a "normal" stop/start flow). - // As such, we are allowing reacquiring by the same id - // See: https://github.com/containerd/nerdctl/issues/3354 + } else if string(previousID) == "" { + // This has happened in the past, probably following some other error condition of OS restart + // We do warn about it, but do not hard-error and let the new container acquire the name + log.L.Warnf("name %q was locked by an empty id - this is abnormal and should be reported", name) + } else if string(previousID) != id { + // If the name is already used by another container, that is a hard error + return fmt.Errorf("name %q is already used by ID %q", name, previousID) } - return os.WriteFile(fileName, []byte(id), 0600) - } - return lockutil.WithDirLock(x.dir, fn) + + // If the id was the same, we are "re-acquiring". + // Maybe containerd was bounced, so previously running containers that would get restarted will go again through + // onCreateRuntime (unlike in a "normal" stop/start flow), without ever had gone through onPostStop. + // As such, reacquiring by the same id is not a bug... + // See: https://github.com/containerd/nerdctl/issues/3354 + return x.safeStore.Set([]byte(id), name) + }) } -func (x *nameStore) Release(name, id string) error { - if name == "" { - return nil - } - if err := identifiers.ValidateDockerCompat(name); err != nil { - return fmt.Errorf("invalid name: %w", err) - } - if strings.TrimSpace(id) != id { - return fmt.Errorf("untrimmed ID %q", id) +func (x *nameStore) Release(name, id string) (err error) { + defer func() { + if err != nil { + err = errors.Join(ErrNameStore, err) + } + }() + + if err = identifiers.ValidateDockerCompat(name); err != nil { + return err } - fn := func() error { - fileName := filepath.Join(x.dir, name) - b, err := os.ReadFile(fileName) + + return x.safeStore.WithLock(func() error { + var content []byte + content, err = x.safeStore.Get(name) if err != nil { - if os.IsNotExist(err) { - err = nil - } return err } - if s := strings.TrimSpace(string(b)); s != id { - return fmt.Errorf("name %q is used by ID %q, not by %q", name, s, id) + + if string(content) != id { + // Never seen this, but technically possible if downstream code is messed-up + return fmt.Errorf("cannot release name %q (used by ID %q, not by %q)", name, content, id) } - return os.RemoveAll(fileName) - } - return lockutil.WithDirLock(x.dir, fn) + + return x.safeStore.Delete(name) + }) } -func (x *nameStore) Rename(oldName, id, newName string) error { - if oldName == "" || newName == "" { - return nil - } - if err := identifiers.ValidateDockerCompat(newName); err != nil { - return fmt.Errorf("invalid name %q: %w", newName, err) +func (x *nameStore) Rename(oldName, id, newName string) (err error) { + defer func() { + if err != nil { + err = errors.Join(ErrNameStore, err) + } + }() + + if err = identifiers.ValidateDockerCompat(newName); err != nil { + return err } - fn := func() error { - oldFileName := filepath.Join(x.dir, oldName) - b, err := os.ReadFile(oldFileName) + + return x.safeStore.WithLock(func() error { + var doesExist bool + var content []byte + doesExist, err = x.safeStore.Exists(newName) if err != nil { return err } - if s := strings.TrimSpace(string(b)); s != id { - return fmt.Errorf("name %q is used by ID %q, not by %q", oldName, s, id) + + if doesExist { + content, err = x.safeStore.Get(newName) + if err != nil { + return err + } + return fmt.Errorf("name %q is already used by ID %q", newName, string(content)) } - newFileName := filepath.Join(x.dir, newName) - if b, err := os.ReadFile(newFileName); err == nil { - return fmt.Errorf("name %q is already used by ID %q", newName, string(b)) + + content, err = x.safeStore.Get(oldName) + if err != nil { + return err } - return os.Rename(oldFileName, newFileName) - } - return lockutil.WithDirLock(x.dir, fn) + + if string(content) != id { + return fmt.Errorf("name %q is used by ID %q, not by %q", oldName, content, id) + } + + err = x.safeStore.Set(content, newName) + if err != nil { + return err + } + + return x.safeStore.Delete(oldName) + }) } diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 922e6ff8c96..e67ec17c677 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -44,6 +44,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" "github.com/containerd/nerdctl/v2/pkg/ocihook/state" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/store" ) const ( @@ -408,7 +409,7 @@ func applyNetworkSettings(opts *handlerOpts) error { return err } ctx := context.Background() - hs, err := hostsstore.NewStore(opts.dataStore) + hs, err := hostsstore.New(opts.dataStore, opts.state.Annotations[labels.Namespace]) if err != nil { return err } @@ -436,7 +437,6 @@ func applyNetworkSettings(opts *handlerOpts) error { gocni.WithArgs("NERDCTL_CNI_DHCP_HOSTNAME", opts.state.Annotations[labels.Hostname]), ) hsMeta := hostsstore.Meta{ - Namespace: opts.state.Annotations[labels.Namespace], ID: opts.state.ID, Networks: make(map[string]*types100.Result, len(opts.cniNames)), Hostname: opts.state.Annotations[labels.Hostname], @@ -510,30 +510,46 @@ func onCreateRuntime(opts *handlerOpts) error { netError = applyNetworkSettings(opts) } - lf := state.NewLifecycleState(opts.state.Annotations[labels.StateDir]) + // Set StartedAt and CreateError + lf, err := state.New(opts.state.Annotations[labels.StateDir]) + if err != nil { + return err + } - return errors.Join(netError, lf.WithLock(func() error { - // Errors are voluntarily ignored here, as they should not be fatal. - // The lifecycle struct is also already warning about the issue. - _ = lf.Load() + err = lf.Transform(func(lf *state.Store) error { lf.StartedAt = time.Now() lf.CreateError = netError != nil - return lf.Save() - })) + return nil + }) + if err != nil { + return err + } + + return netError } func onPostStop(opts *handlerOpts) error { - // See https://github.com/containerd/nerdctl/issues/3357 - // Check if we actually errored during runtimeCreate - // If that is the case, CreateError is set, and we are in postStop while the container will NOT be deleted (see ticket). - // In that case, do NOT treat this as a deletion, as the container is still there. - // Reset CreateError, and return. - lf := state.NewLifecycleState(opts.state.Annotations[labels.StateDir]) - if lf.WithLock(lf.Load) == nil { - if lf.CreateError { - lf.CreateError = false - return lf.WithLock(lf.Save) - } + lf, err := state.New(opts.state.Annotations[labels.StateDir]) + if err != nil { + return err + } + + var shouldExit bool + err = lf.Transform(func(lf *state.Store) error { + // See https://github.com/containerd/nerdctl/issues/3357 + // Check if we actually errored during runtimeCreate + // If that is the case, CreateError is set, and we are in postStop while the container will NOT be deleted (see ticket). + // Thus, do NOT treat this as a deletion, as the container is still there. + // Reset CreateError, and return. + shouldExit = lf.CreateError + lf.CreateError = false + return nil + }) + if err != nil { + return err + } + if shouldExit { + return nil } ctx := context.Background() @@ -586,11 +602,11 @@ func onPostStop(opts *handlerOpts) error { log.L.WithError(err).Errorf("failed to call cni.Remove") return err } - hs, err := hostsstore.NewStore(opts.dataStore) + hs, err := hostsstore.New(opts.dataStore, ns) if err != nil { return err } - if err := hs.Release(ns, opts.state.ID); err != nil { + if err := hs.Release(opts.state.ID); err != nil { return err } } @@ -599,7 +615,8 @@ func onPostStop(opts *handlerOpts) error { return err } name := opts.state.Annotations[labels.Name] - if err := namst.Release(name, opts.state.ID); err != nil { + // Double-releasing may happen with containers started with --rm, so, ignore NotFound errors + if err := namst.Release(name, opts.state.ID); err != nil && !errors.Is(err, store.ErrNotFound) { return fmt.Errorf("failed to release container name %s: %w", name, err) } return nil diff --git a/pkg/ocihook/state/state.go b/pkg/ocihook/state/state.go index 312bf973556..52253d390fe 100644 --- a/pkg/ocihook/state/state.go +++ b/pkg/ocihook/state/state.go @@ -14,87 +14,114 @@ limitations under the License. */ +// Package state provides a store to retrieve and save container lifecycle related information +// This is typically used by oci-hooks for information that cannot be retrieved / updated otherwise +// Specifically, the state carries container start time, and transient information about possible failures during +// hook events processing. +// All store methods are safe to use concurrently and only write atomically. +// Since the state is transient and carrying solely informative data, errors returned from here could be treated as +// soft-failures. +// Note that locking is done at the container state directory level. +// state is currently used by ocihooks and for read by dockercompat (to display started-at time) package state import ( "encoding/json" "errors" - "fmt" - "os" - "path/filepath" "time" - "github.com/containerd/log" - - "github.com/containerd/nerdctl/v2/pkg/lockutil" + "github.com/containerd/nerdctl/v2/pkg/store" ) -// This is meant to store stateful informations about containers that we receive from ocihooks -// We are storing them inside the container statedir -// Note that you MUST use WithLock to perform any operation (like Read or Write). -// Typically: -// lf.WithLock(func ()error { -// lf.Load() -// // Modify something on the object -// lf.StartedAt = ... -// lf.Save() -// }) - -const ( - lifecycleFile = "lifecycle.json" -) +// lifecycleFile is the name of file carrying the container information, relative to stateDir +const lifecycleFile = "lifecycle.json" -func NewLifecycleState(stateDir string) *LifecycleState { - return &LifecycleState{ - stateDir: stateDir, +// ErrLifecycleStore will wrap all errors here +var ErrLifecycleStore = errors.New("lifecycle-store error") + +// New will return a lifecycle struct for the container which stateDir is passed as argument +func New(stateDir string) (*Store, error) { + st, err := store.New(stateDir, 0, 0) + if err != nil { + return nil, errors.Join(ErrLifecycleStore, err) } + + return &Store{ + safeStore: st, + }, nil } -type LifecycleState struct { - stateDir string +// Store exposes methods to retrieve and transform state information about containers. +type Store struct { + safeStore store.Store + + // StartedAt reflects the time at which we received the oci-hook onCreateRuntime event StartedAt time.Time `json:"started_at"` CreateError bool `json:"create_error"` } -func (lf *LifecycleState) WithLock(fun func() error) error { - err := lockutil.WithDirLock(lf.stateDir, fun) - if err != nil { - return fmt.Errorf("failed to lock state dir: %w", err) - } +// Load will populate the struct with existing in-store lifecycle information +func (lf *Store) Load() (err error) { + defer func() { + if err != nil { + err = errors.Join(ErrLifecycleStore, err) + } + }() - return nil + return lf.safeStore.WithLock(lf.rawLoad) } -func (lf *LifecycleState) Load() error { - data, err := os.ReadFile(filepath.Join(lf.stateDir, lifecycleFile)) - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - return fmt.Errorf("unable to read lifecycle file: %w", err) +// Transform should be used to perform random mutations +func (lf *Store) Transform(fun func(lf *Store) error) (err error) { + defer func() { + if err != nil { + err = errors.Join(ErrLifecycleStore, err) } - } else { - err = json.Unmarshal(data, lf) + }() + + return lf.safeStore.WithLock(func() error { + err = lf.rawLoad() + if err != nil { + return err + } + err = fun(lf) if err != nil { - // Logging an error, as Load errors are generally ignored downstream - log.L.Error("unable to unmarshall lifecycle data") - return fmt.Errorf("unable to unmarshall lifecycle data: %w", err) + return err } + return lf.rawSave() + }) +} + +// Delete will destroy the lifecycle data +func (lf *Store) Delete() (err error) { + defer func() { + if err != nil { + err = errors.Join(ErrLifecycleStore, err) + } + }() + + return lf.safeStore.WithLock(lf.rawDelete) +} + +func (lf *Store) rawLoad() (err error) { + data, err := lf.safeStore.Get(lifecycleFile) + if err == nil { + err = json.Unmarshal(data, lf) + } else if errors.Is(err, store.ErrNotFound) { + err = nil } - return nil + + return err } -func (lf *LifecycleState) Save() error { - // Write atomically (write, then move) to avoid incomplete writes from happening +func (lf *Store) rawSave() (err error) { data, err := json.Marshal(lf) if err != nil { - return fmt.Errorf("unable to marshall lifecycle data: %w", err) - } - err = os.WriteFile(filepath.Join(lf.stateDir, "."+lifecycleFile), data, 0600) - if err != nil { - return fmt.Errorf("unable to write lifecycle file: %w", err) + return err } - err = os.Rename(filepath.Join(lf.stateDir, "."+lifecycleFile), filepath.Join(lf.stateDir, lifecycleFile)) - if err != nil { - return fmt.Errorf("unable to write lifecycle file: %w", err) - } - return nil + return lf.safeStore.Set(data, lifecycleFile) +} + +func (lf *Store) rawDelete() (err error) { + return lf.safeStore.Delete(lifecycleFile) } From 23aca88ad00b419c00e2553f79f89ff2e6fe422d Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 1 Sep 2024 15:57:56 -0700 Subject: [PATCH 0739/1066] Refactor: cleanup prompting Signed-off-by: apostasie --- pkg/cmd/login/login.go | 59 +--------- pkg/cmd/login/prompt.go | 109 ++++++++++++++++++ .../login/{login_unix.go => prompt_unix.go} | 22 ++-- .../{login_windows.go => prompt_windows.go} | 13 +-- 4 files changed, 130 insertions(+), 73 deletions(-) create mode 100644 pkg/cmd/login/prompt.go rename pkg/cmd/login/{login_unix.go => prompt_unix.go} (73%) rename pkg/cmd/login/{login_windows.go => prompt_windows.go} (79%) diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 6d5f5a026d4..6f4492ae71b 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -17,18 +17,14 @@ package login import ( - "bufio" "context" "errors" "fmt" "io" "net/http" "net/url" - "os" - "strings" "golang.org/x/net/context/ctxhttp" - "golang.org/x/term" "github.com/containerd/containerd/v2/core/remotes/docker" "github.com/containerd/containerd/v2/core/remotes/docker/config" @@ -66,7 +62,7 @@ func Login(ctx context.Context, options types.LoginCommandOptions, stdout io.Wri } if err != nil || credentials.Username == "" || credentials.Password == "" { - err = configureAuthentication(credentials, options.Username, options.Password) + err = promptUserForAuthentication(credentials, options.Username, options.Password, stdout) if err != nil { return err } @@ -205,56 +201,3 @@ func tryLoginWithRegHost(ctx context.Context, rh docker.RegistryHost) error { return errors.New("too many 401 (probably)") } - -func configureAuthentication(credentials *dockerconfigresolver.Credentials, username, password string) error { - if username = strings.TrimSpace(username); username == "" { - username = credentials.Username - } - if username == "" { - fmt.Print("Enter Username: ") - usr, err := readUsername() - if err != nil { - return err - } - username = usr - } - if username == "" { - return fmt.Errorf("error: Username is Required") - } - - if password == "" { - fmt.Print("Enter Password: ") - pwd, err := readPassword() - fmt.Println() - if err != nil { - return err - } - password = pwd - } - if password == "" { - return fmt.Errorf("error: Password is Required") - } - - credentials.Username = username - credentials.Password = password - - return nil -} - -func readUsername() (string, error) { - var fd *os.File - if term.IsTerminal(int(os.Stdin.Fd())) { - fd = os.Stdin - } else { - return "", fmt.Errorf("stdin is not a terminal (Hint: use `nerdctl login --username=USERNAME --password-stdin`)") - } - - reader := bufio.NewReader(fd) - username, err := reader.ReadString('\n') - if err != nil { - return "", fmt.Errorf("error reading username: %w", err) - } - username = strings.TrimSpace(username) - - return username, nil -} diff --git a/pkg/cmd/login/prompt.go b/pkg/cmd/login/prompt.go new file mode 100644 index 00000000000..db1f6554244 --- /dev/null +++ b/pkg/cmd/login/prompt.go @@ -0,0 +1,109 @@ +/* + 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 login + +import ( + "bufio" + "errors" + "fmt" + "io" + "os" + "strings" + + "golang.org/x/term" + + "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" +) + +var ( + // User did not provide non-empty credentials when prompted for it + ErrUsernameIsRequired = errors.New("username is required") + ErrPasswordIsRequired = errors.New("password is required") + + // System errors - not a terminal, failure to read, etc + ErrReadingUsername = errors.New("unable to read username") + ErrReadingPassword = errors.New("unable to read password") + ErrNotATerminal = errors.New("stdin is not a terminal (Hint: use `nerdctl login --username=USERNAME --password-stdin`)") + ErrCannotAllocateTerminal = errors.New("error allocating terminal") +) + +// promptUserForAuthentication will prompt the user for credentials if needed +// It might error with any of the errors defined above. +func promptUserForAuthentication(credentials *dockerconfigresolver.Credentials, username, password string, stdout io.Writer) error { + var err error + + // If the provided username is empty... + if username = strings.TrimSpace(username); username == "" { + // Use the one we know of (from the store) + username = credentials.Username + // If the one from the store was empty as well, prompt and read the username + if username == "" { + _, _ = fmt.Fprint(stdout, "Enter Username: ") + username, err = readUsername() + if err != nil { + return err + } + + username = strings.TrimSpace(username) + // If it still is empty, that is an error + if username == "" { + return ErrUsernameIsRequired + } + } + } + + // If password was NOT passed along, ask for it + if password == "" { + _, _ = fmt.Fprint(stdout, "Enter Password: ") + password, err = readPassword() + if err != nil { + return err + } + + _, _ = fmt.Fprintln(stdout) + password = strings.TrimSpace(password) + + // If nothing was provided, error out + if password == "" { + return ErrPasswordIsRequired + } + } + + // Attach non-empty credentials to the auth object and return + credentials.Username = username + credentials.Password = password + + return nil +} + +// readUsername will try to read from user input +// It might error with: +// - ErrNotATerminal +// - ErrReadingUsername +func readUsername() (string, error) { + fd := os.Stdin + if !term.IsTerminal(int(fd.Fd())) { + return "", ErrNotATerminal + } + + username, err := bufio.NewReader(fd).ReadString('\n') + if err != nil { + return "", errors.Join(ErrReadingUsername, err) + } + + return strings.TrimSpace(username), nil +} diff --git a/pkg/cmd/login/login_unix.go b/pkg/cmd/login/prompt_unix.go similarity index 73% rename from pkg/cmd/login/login_unix.go rename to pkg/cmd/login/prompt_unix.go index c1eec8fdf01..69529473f6d 100644 --- a/pkg/cmd/login/login_unix.go +++ b/pkg/cmd/login/prompt_unix.go @@ -19,28 +19,34 @@ package login import ( - "fmt" + "errors" "os" "syscall" "golang.org/x/term" + + "github.com/containerd/log" ) func readPassword() (string, error) { - var fd int - if term.IsTerminal(syscall.Stdin) { - fd = syscall.Stdin - } else { + fd := syscall.Stdin + if !term.IsTerminal(fd) { tty, err := os.Open("/dev/tty") if err != nil { - return "", fmt.Errorf("error allocating terminal: %w", err) + return "", errors.Join(ErrCannotAllocateTerminal, err) } - defer tty.Close() + defer func() { + err = tty.Close() + if err != nil { + log.L.WithError(err).Error("failed closing tty") + } + }() fd = int(tty.Fd()) } + bytePassword, err := term.ReadPassword(fd) if err != nil { - return "", fmt.Errorf("error reading password: %w", err) + return "", errors.Join(ErrReadingPassword, err) } return string(bytePassword), nil diff --git a/pkg/cmd/login/login_windows.go b/pkg/cmd/login/prompt_windows.go similarity index 79% rename from pkg/cmd/login/login_windows.go rename to pkg/cmd/login/prompt_windows.go index 89c3834fb92..913e6ff5f98 100644 --- a/pkg/cmd/login/login_windows.go +++ b/pkg/cmd/login/prompt_windows.go @@ -17,22 +17,21 @@ package login import ( - "fmt" + "errors" "syscall" "golang.org/x/term" ) func readPassword() (string, error) { - var fd int - if term.IsTerminal(int(syscall.Stdin)) { - fd = int(syscall.Stdin) - } else { - return "", fmt.Errorf("error allocating terminal") + fd := int(syscall.Stdin) + if !term.IsTerminal(fd) { + return "", ErrNotATerminal } + bytePassword, err := term.ReadPassword(fd) if err != nil { - return "", fmt.Errorf("error reading password: %w", err) + return "", errors.Join(ErrReadingPassword, err) } return string(bytePassword), nil From efeb191a9378e09eb9ad7d3db73984fb713c2b9f Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 3 Sep 2024 20:25:45 -0700 Subject: [PATCH 0740/1066] Fix windows linter complaints Signed-off-by: apostasie --- .../{container_cp.go => container_cp_unix.go} | 2 + .../container/container_list_windows_test.go | 1 - .../container_run_network_base_test.go | 26 ---- .../container_run_network_linux_test.go | 25 ++++ .../container_run_network_windows_test.go | 18 +-- cmd/nerdctl/image/image_encrypt_linux_test.go | 8 +- pkg/cmd/container/run_cgroup_freebsd.go | 27 ---- pkg/cmd/container/run_cgroup_windows.go | 27 ---- pkg/cmd/container/run_gpus.go | 63 --------- pkg/cmd/container/run_linux.go | 59 +++++++++ .../{run_ulimit.go => run_ulimit_linux.go} | 0 pkg/cmd/container/run_windows.go | 2 +- pkg/cmd/container/top.go | 124 ------------------ pkg/cmd/container/top_unix.go | 124 ++++++++++++++++++ .../container_network_manager_windows.go | 4 +- pkg/netutil/netutil_windows.go | 4 - pkg/ocihook/ocihook_windows.go | 1 - pkg/statsutil/stats.go | 9 -- pkg/statsutil/stats_linux.go | 9 ++ pkg/sysinfo/sysinfo.go | 6 +- .../{iptables.go => iptables_linux.go} | 0 .../{certsd.go => certsd_linux.go} | 0 22 files changed, 240 insertions(+), 299 deletions(-) rename cmd/nerdctl/container/{container_cp.go => container_cp_unix.go} (99%) delete mode 100644 pkg/cmd/container/run_cgroup_freebsd.go delete mode 100644 pkg/cmd/container/run_cgroup_windows.go rename pkg/cmd/container/{run_ulimit.go => run_ulimit_linux.go} (100%) rename pkg/testutil/iptables/{iptables.go => iptables_linux.go} (100%) rename pkg/testutil/testregistry/{certsd.go => certsd_linux.go} (100%) diff --git a/cmd/nerdctl/container/container_cp.go b/cmd/nerdctl/container/container_cp_unix.go similarity index 99% rename from cmd/nerdctl/container/container_cp.go rename to cmd/nerdctl/container/container_cp_unix.go index 716fc8fc5c9..e6e1f70dce1 100644 --- a/cmd/nerdctl/container/container_cp.go +++ b/cmd/nerdctl/container/container_cp_unix.go @@ -1,3 +1,5 @@ +//go:build unix + /* Copyright The containerd Authors. diff --git a/cmd/nerdctl/container/container_list_windows_test.go b/cmd/nerdctl/container/container_list_windows_test.go index b9559a791b8..39eec453684 100644 --- a/cmd/nerdctl/container/container_list_windows_test.go +++ b/cmd/nerdctl/container/container_list_windows_test.go @@ -32,7 +32,6 @@ import ( type psTestContainer struct { name string labels map[string]string - volumes []string network string } diff --git a/cmd/nerdctl/container/container_run_network_base_test.go b/cmd/nerdctl/container/container_run_network_base_test.go index 4e75448975b..60a27be5202 100644 --- a/cmd/nerdctl/container/container_run_network_base_test.go +++ b/cmd/nerdctl/container/container_run_network_base_test.go @@ -22,7 +22,6 @@ import ( "fmt" "io" "net" - "regexp" "strings" "testing" @@ -223,28 +222,3 @@ func baseTestRunPort(t *testing.T, nginxImage string, nginxIndexHTMLSnippet stri } } - -func valuesOfMapStringString(m map[string]string) map[string]struct{} { - res := make(map[string]struct{}) - for _, v := range m { - res[v] = struct{}{} - } - return res -} - -func extractHostPort(portMapping string, port string) (string, error) { - // Regular expression to extract host port from port mapping information - re := regexp.MustCompile(`(?P\d{1,5})/tcp ->.*?0.0.0.0:(?P\d{1,5}).*?`) - portMappingLines := strings.Split(portMapping, "\n") - for _, portMappingLine := range portMappingLines { - // Find the matches - matches := re.FindStringSubmatch(portMappingLine) - // Check if there is a match - if len(matches) >= 3 && matches[1] == port { - // Extract the host port number - hostPort := matches[2] - return hostPort, nil - } - } - return "", fmt.Errorf("could not extract host port from port mapping: %s", portMapping) -} diff --git a/cmd/nerdctl/container/container_run_network_linux_test.go b/cmd/nerdctl/container/container_run_network_linux_test.go index 8a21e54b5a1..4c3c7d572a5 100644 --- a/cmd/nerdctl/container/container_run_network_linux_test.go +++ b/cmd/nerdctl/container/container_run_network_linux_test.go @@ -37,6 +37,31 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" ) +func extractHostPort(portMapping string, port string) (string, error) { + // Regular expression to extract host port from port mapping information + re := regexp.MustCompile(`(?P\d{1,5})/tcp ->.*?0.0.0.0:(?P\d{1,5}).*?`) + portMappingLines := strings.Split(portMapping, "\n") + for _, portMappingLine := range portMappingLines { + // Find the matches + matches := re.FindStringSubmatch(portMappingLine) + // Check if there is a match + if len(matches) >= 3 && matches[1] == port { + // Extract the host port number + hostPort := matches[2] + return hostPort, nil + } + } + return "", fmt.Errorf("could not extract host port from port mapping: %s", portMapping) +} + +func valuesOfMapStringString(m map[string]string) map[string]struct{} { + res := make(map[string]struct{}) + for _, v := range m { + res[v] = struct{}{} + } + return res +} + // TestRunInternetConnectivity tests Internet connectivity with `apk update` func TestRunInternetConnectivity(t *testing.T) { base := testutil.NewBase(t) diff --git a/cmd/nerdctl/container/container_run_network_windows_test.go b/cmd/nerdctl/container/container_run_network_windows_test.go index 9cd8430e5d3..53e9dd73bfc 100644 --- a/cmd/nerdctl/container/container_run_network_windows_test.go +++ b/cmd/nerdctl/container/container_run_network_windows_test.go @@ -126,22 +126,22 @@ func TestHnsEndpointsExistDuringContainerLifecycle(t *testing.T) { "tail", "-f", ) t.Logf("Creating HNS lifecycle test container with command: %q", strings.Join(cmd.Command, " ")) - containerId := strings.TrimSpace(cmd.Run().Stdout()) - t.Logf("HNS endpoint lifecycle test container ID: %q", containerId) + containerID := strings.TrimSpace(cmd.Run().Stdout()) + t.Logf("HNS endpoint lifecycle test container ID: %q", containerID) // HNS endpoints should be allocated on container creation. - assertHnsEndpointsExistence(t, true, containerId, testNet.Name) + assertHnsEndpointsExistence(t, true, containerID, testNet.Name) // Starting and stopping the container should NOT affect/change the endpoints. - base.Cmd("start", containerId).AssertOK() - assertHnsEndpointsExistence(t, true, containerId, testNet.Name) + base.Cmd("start", containerID).AssertOK() + assertHnsEndpointsExistence(t, true, containerID, testNet.Name) - base.Cmd("stop", containerId).AssertOK() - assertHnsEndpointsExistence(t, true, containerId, testNet.Name) + base.Cmd("stop", containerID).AssertOK() + assertHnsEndpointsExistence(t, true, containerID, testNet.Name) // Removing the container should remove the HNS endpoints. - base.Cmd("rm", containerId).AssertOK() - assertHnsEndpointsExistence(t, false, containerId, testNet.Name) + base.Cmd("rm", containerID).AssertOK() + assertHnsEndpointsExistence(t, false, containerID, testNet.Name) } // Returns a network to be used for testing. diff --git a/cmd/nerdctl/image/image_encrypt_linux_test.go b/cmd/nerdctl/image/image_encrypt_linux_test.go index 61fb6c30981..80ff117c007 100644 --- a/cmd/nerdctl/image/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image/image_encrypt_linux_test.go @@ -29,18 +29,22 @@ func TestImageEncryptJWE(t *testing.T) { testutil.RequiresBuild(t) testutil.DockerIncompatible(t) keyPair := helpers.NewJWEKeyPair(t) - defer keyPair.Cleanup() base := testutil.NewBase(t) tID := testutil.Identifier(t) reg := testregistry.NewWithNoAuth(base, 0, false) + + defer keyPair.Cleanup() defer reg.Cleanup(nil) + base.Cmd("pull", testutil.CommonImage).AssertOK() encryptImageRef := fmt.Sprintf("127.0.0.1:%d/%s:encrypted", reg.Port, tID) - defer base.Cmd("rmi", encryptImageRef).Run() base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, testutil.CommonImage, encryptImageRef).AssertOK() base.Cmd("image", "inspect", "--mode=native", "--format={{len .Index.Manifests}}", encryptImageRef).AssertOutExactly("1\n") base.Cmd("image", "inspect", "--mode=native", "--format={{json .Manifest.Layers}}", encryptImageRef).AssertOutContains("org.opencontainers.image.enc.keys.jwe") base.Cmd("push", encryptImageRef).AssertOK() + + defer base.Cmd("rmi", encryptImageRef).Run() + // remove all local images (in the nerdctl-test namespace), to ensure that we do not have blobs of the original image. helpers.RmiAll(base) base.Cmd("pull", encryptImageRef).AssertFail() // defaults to --unpack=true, and fails due to missing prv key diff --git a/pkg/cmd/container/run_cgroup_freebsd.go b/pkg/cmd/container/run_cgroup_freebsd.go deleted file mode 100644 index 994d800cdae..00000000000 --- a/pkg/cmd/container/run_cgroup_freebsd.go +++ /dev/null @@ -1,27 +0,0 @@ -/* - 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 container - -import ( - "github.com/containerd/containerd/v2/pkg/oci" - - "github.com/containerd/nerdctl/v2/pkg/api/types" -) - -func generateCgroupOpts(id string, options types.ContainerCreateOptions) ([]oci.SpecOpts, error) { - return []oci.SpecOpts{}, nil -} diff --git a/pkg/cmd/container/run_cgroup_windows.go b/pkg/cmd/container/run_cgroup_windows.go deleted file mode 100644 index 994d800cdae..00000000000 --- a/pkg/cmd/container/run_cgroup_windows.go +++ /dev/null @@ -1,27 +0,0 @@ -/* - 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 container - -import ( - "github.com/containerd/containerd/v2/pkg/oci" - - "github.com/containerd/nerdctl/v2/pkg/api/types" -) - -func generateCgroupOpts(id string, options types.ContainerCreateOptions) ([]oci.SpecOpts, error) { - return []oci.SpecOpts{}, nil -} diff --git a/pkg/cmd/container/run_gpus.go b/pkg/cmd/container/run_gpus.go index e2261e641eb..967858b6bf5 100644 --- a/pkg/cmd/container/run_gpus.go +++ b/pkg/cmd/container/run_gpus.go @@ -22,11 +22,6 @@ import ( "fmt" "strconv" "strings" - - "github.com/containerd/containerd/v2/contrib/nvidia" - "github.com/containerd/containerd/v2/pkg/oci" - - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) // GPUReq is a request for GPUs. @@ -36,64 +31,6 @@ type GPUReq struct { Capabilities []string } -func parseGPUOpts(value []string) (res []oci.SpecOpts, _ error) { - for _, gpu := range value { - gpuOpt, err := parseGPUOpt(gpu) - if err != nil { - return nil, err - } - res = append(res, gpuOpt) - } - return res, nil -} - -func parseGPUOpt(value string) (oci.SpecOpts, error) { - req, err := ParseGPUOptCSV(value) - if err != nil { - return nil, err - } - - var gpuOpts []nvidia.Opts - - if len(req.DeviceIDs) > 0 { - gpuOpts = append(gpuOpts, nvidia.WithDeviceUUIDs(req.DeviceIDs...)) - } else if req.Count > 0 { - var devices []int - for i := 0; i < req.Count; i++ { - devices = append(devices, i) - } - gpuOpts = append(gpuOpts, nvidia.WithDevices(devices...)) - } else if req.Count < 0 { - gpuOpts = append(gpuOpts, nvidia.WithAllDevices) - } - - str2cap := make(map[string]nvidia.Capability) - for _, c := range nvidia.AllCaps() { - str2cap[string(c)] = c - } - var nvidiaCaps []nvidia.Capability - for _, c := range req.Capabilities { - if cp, isNvidiaCap := str2cap[c]; isNvidiaCap { - nvidiaCaps = append(nvidiaCaps, cp) - } - } - if len(nvidiaCaps) != 0 { - gpuOpts = append(gpuOpts, nvidia.WithCapabilities(nvidiaCaps...)) - } else { - // Add "utility", "compute" capability if unset. - // Please see also: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/user-guide.html#driver-capabilities - gpuOpts = append(gpuOpts, nvidia.WithCapabilities(nvidia.Utility, nvidia.Compute)) - } - - if rootlessutil.IsRootless() { - // "--no-cgroups" option is needed to nvidia-container-cli in rootless environment - // Please see also: https://github.com/moby/moby/issues/38729#issuecomment-463493866 - gpuOpts = append(gpuOpts, nvidia.WithNoCgroups) - } - - return nvidia.WithGPUs(gpuOpts...), nil -} - // ParseGPUOptCSV parses a GPU option from CSV. func ParseGPUOptCSV(value string) (*GPUReq, error) { csvReader := csv.NewReader(strings.NewReader(value)) diff --git a/pkg/cmd/container/run_linux.go b/pkg/cmd/container/run_linux.go index 1c7522010b2..cbe38d62e46 100644 --- a/pkg/cmd/container/run_linux.go +++ b/pkg/cmd/container/run_linux.go @@ -25,6 +25,7 @@ import ( "github.com/opencontainers/runtime-spec/specs-go" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/contrib/nvidia" "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" @@ -260,3 +261,61 @@ func withOOMScoreAdj(score int) oci.SpecOpts { return nil } } + +func parseGPUOpts(value []string) (res []oci.SpecOpts, _ error) { + for _, gpu := range value { + gpuOpt, err := parseGPUOpt(gpu) + if err != nil { + return nil, err + } + res = append(res, gpuOpt) + } + return res, nil +} + +func parseGPUOpt(value string) (oci.SpecOpts, error) { + req, err := ParseGPUOptCSV(value) + if err != nil { + return nil, err + } + + var gpuOpts []nvidia.Opts + + if len(req.DeviceIDs) > 0 { + gpuOpts = append(gpuOpts, nvidia.WithDeviceUUIDs(req.DeviceIDs...)) + } else if req.Count > 0 { + var devices []int + for i := 0; i < req.Count; i++ { + devices = append(devices, i) + } + gpuOpts = append(gpuOpts, nvidia.WithDevices(devices...)) + } else if req.Count < 0 { + gpuOpts = append(gpuOpts, nvidia.WithAllDevices) + } + + str2cap := make(map[string]nvidia.Capability) + for _, c := range nvidia.AllCaps() { + str2cap[string(c)] = c + } + var nvidiaCaps []nvidia.Capability + for _, c := range req.Capabilities { + if cp, isNvidiaCap := str2cap[c]; isNvidiaCap { + nvidiaCaps = append(nvidiaCaps, cp) + } + } + if len(nvidiaCaps) != 0 { + gpuOpts = append(gpuOpts, nvidia.WithCapabilities(nvidiaCaps...)) + } else { + // Add "utility", "compute" capability if unset. + // Please see also: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/user-guide.html#driver-capabilities + gpuOpts = append(gpuOpts, nvidia.WithCapabilities(nvidia.Utility, nvidia.Compute)) + } + + if rootlessutil.IsRootless() { + // "--no-cgroups" option is needed to nvidia-container-cli in rootless environment + // Please see also: https://github.com/moby/moby/issues/38729#issuecomment-463493866 + gpuOpts = append(gpuOpts, nvidia.WithNoCgroups) + } + + return nvidia.WithGPUs(gpuOpts...), nil +} diff --git a/pkg/cmd/container/run_ulimit.go b/pkg/cmd/container/run_ulimit_linux.go similarity index 100% rename from pkg/cmd/container/run_ulimit.go rename to pkg/cmd/container/run_ulimit_linux.go diff --git a/pkg/cmd/container/run_windows.go b/pkg/cmd/container/run_windows.go index ea8409d4708..6b38e7e9f3f 100644 --- a/pkg/cmd/container/run_windows.go +++ b/pkg/cmd/container/run_windows.go @@ -49,7 +49,7 @@ func setPlatformOptions( internalLabels *internalLabels, options types.ContainerCreateOptions, ) ([]oci.SpecOpts, error) { - var opts []oci.SpecOpts + opts := []oci.SpecOpts{} if options.CPUs > 0.0 { opts = append(opts, oci.WithWindowsCPUCount(uint64(options.CPUs))) } diff --git a/pkg/cmd/container/top.go b/pkg/cmd/container/top.go index 0e2f49adadc..35addf54887 100644 --- a/pkg/cmd/container/top.go +++ b/pkg/cmd/container/top.go @@ -28,8 +28,6 @@ package container import ( "context" "fmt" - "regexp" - "strconv" "strings" containerd "github.com/containerd/containerd/v2/client" @@ -74,125 +72,3 @@ func Top(ctx context.Context, client *containerd.Client, containers []string, op } return nil } - -// appendProcess2ProcList is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L49-L55 -func appendProcess2ProcList(procList *ContainerTopOKBody, fields []string) { - // Make sure number of fields equals number of header titles - // merging "overhanging" fields - process := fields[:len(procList.Titles)-1] - process = append(process, strings.Join(fields[len(procList.Titles)-1:], " ")) - procList.Processes = append(procList.Processes, process) -} - -// psPidsArg is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L119-L131 -// -// psPidsArg converts a slice of PIDs to a string consisting -// of comma-separated list of PIDs prepended by "-q". -// For example, psPidsArg([]uint32{1,2,3}) returns "-q1,2,3". -func psPidsArg(pids []uint32) string { - b := []byte{'-', 'q'} - for i, p := range pids { - b = strconv.AppendUint(b, uint64(p), 10) - if i < len(pids)-1 { - b = append(b, ',') - } - } - return string(b) -} - -// validatePSArgs is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L19-L35 -func validatePSArgs(psArgs string) error { - // NOTE: \\s does not detect unicode whitespaces. - // So we use fieldsASCII instead of strings.Fields in parsePSOutput. - // See https://github.com/docker/docker/pull/24358 - // nolint: gosimple - re := regexp.MustCompile(`\s+(\S*)=\s*(PID\S*)`) - for _, group := range re.FindAllStringSubmatch(psArgs, -1) { - if len(group) >= 3 { - k := group[1] - v := group[2] - if k != "pid" { - return fmt.Errorf("specifying \"%s=%s\" is not allowed", k, v) - } - } - } - return nil -} - -// fieldsASCII is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L37-L47 -// -// fieldsASCII is similar to strings.Fields but only allows ASCII whitespaces -func fieldsASCII(s string) []string { - fn := func(r rune) bool { - switch r { - case '\t', '\n', '\f', '\r', ' ': - return true - } - return false - } - return strings.FieldsFunc(s, fn) -} - -// hasPid is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L57-L64 -func hasPid(procs []uint32, pid int) bool { - for _, p := range procs { - if int(p) == pid { - return true - } - } - return false -} - -// parsePSOutput is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L66-L117 -func parsePSOutput(output []byte, procs []uint32) (*ContainerTopOKBody, error) { - procList := &ContainerTopOKBody{} - - lines := strings.Split(string(output), "\n") - procList.Titles = fieldsASCII(lines[0]) - - pidIndex := -1 - for i, name := range procList.Titles { - if name == "PID" { - pidIndex = i - break - } - } - if pidIndex == -1 { - return nil, fmt.Errorf("couldn't find PID field in ps output") - } - - // loop through the output and extract the PID from each line - // fixing #30580, be able to display thread line also when "m" option used - // in "docker top" client command - preContainedPidFlag := false - for _, line := range lines[1:] { - if len(line) == 0 { - continue - } - fields := fieldsASCII(line) - - var ( - p int - err error - ) - - if fields[pidIndex] == "-" { - if preContainedPidFlag { - appendProcess2ProcList(procList, fields) - } - continue - } - p, err = strconv.Atoi(fields[pidIndex]) - if err != nil { - return nil, fmt.Errorf("unexpected pid '%s': %s", fields[pidIndex], err) - } - - if hasPid(procs, p) { - preContainedPidFlag = true - appendProcess2ProcList(procList, fields) - continue - } - preContainedPidFlag = false - } - return procList, nil -} diff --git a/pkg/cmd/container/top_unix.go b/pkg/cmd/container/top_unix.go index 0504849673c..606e6c5772d 100644 --- a/pkg/cmd/container/top_unix.go +++ b/pkg/cmd/container/top_unix.go @@ -34,6 +34,8 @@ import ( "fmt" "io" "os/exec" + "regexp" + "strconv" "strings" "text/tabwriter" @@ -120,3 +122,125 @@ func containerTop(ctx context.Context, stdio io.Writer, client *containerd.Clien return w.Flush() } + +// appendProcess2ProcList is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L49-L55 +func appendProcess2ProcList(procList *ContainerTopOKBody, fields []string) { + // Make sure number of fields equals number of header titles + // merging "overhanging" fields + process := fields[:len(procList.Titles)-1] + process = append(process, strings.Join(fields[len(procList.Titles)-1:], " ")) + procList.Processes = append(procList.Processes, process) +} + +// psPidsArg is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L119-L131 +// +// psPidsArg converts a slice of PIDs to a string consisting +// of comma-separated list of PIDs prepended by "-q". +// For example, psPidsArg([]uint32{1,2,3}) returns "-q1,2,3". +func psPidsArg(pids []uint32) string { + b := []byte{'-', 'q'} + for i, p := range pids { + b = strconv.AppendUint(b, uint64(p), 10) + if i < len(pids)-1 { + b = append(b, ',') + } + } + return string(b) +} + +// validatePSArgs is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L19-L35 +func validatePSArgs(psArgs string) error { + // NOTE: \\s does not detect unicode whitespaces. + // So we use fieldsASCII instead of strings.Fields in parsePSOutput. + // See https://github.com/docker/docker/pull/24358 + // nolint: gosimple + re := regexp.MustCompile(`\s+(\S*)=\s*(PID\S*)`) + for _, group := range re.FindAllStringSubmatch(psArgs, -1) { + if len(group) >= 3 { + k := group[1] + v := group[2] + if k != "pid" { + return fmt.Errorf("specifying \"%s=%s\" is not allowed", k, v) + } + } + } + return nil +} + +// fieldsASCII is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L37-L47 +// +// fieldsASCII is similar to strings.Fields but only allows ASCII whitespaces +func fieldsASCII(s string) []string { + fn := func(r rune) bool { + switch r { + case '\t', '\n', '\f', '\r', ' ': + return true + } + return false + } + return strings.FieldsFunc(s, fn) +} + +// hasPid is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L57-L64 +func hasPid(procs []uint32, pid int) bool { + for _, p := range procs { + if int(p) == pid { + return true + } + } + return false +} + +// parsePSOutput is from https://github.com/moby/moby/blob/v20.10.6/daemon/top_unix.go#L66-L117 +func parsePSOutput(output []byte, procs []uint32) (*ContainerTopOKBody, error) { + procList := &ContainerTopOKBody{} + + lines := strings.Split(string(output), "\n") + procList.Titles = fieldsASCII(lines[0]) + + pidIndex := -1 + for i, name := range procList.Titles { + if name == "PID" { + pidIndex = i + break + } + } + if pidIndex == -1 { + return nil, fmt.Errorf("couldn't find PID field in ps output") + } + + // loop through the output and extract the PID from each line + // fixing #30580, be able to display thread line also when "m" option used + // in "docker top" client command + preContainedPidFlag := false + for _, line := range lines[1:] { + if len(line) == 0 { + continue + } + fields := fieldsASCII(line) + + var ( + p int + err error + ) + + if fields[pidIndex] == "-" { + if preContainedPidFlag { + appendProcess2ProcList(procList, fields) + } + continue + } + p, err = strconv.Atoi(fields[pidIndex]) + if err != nil { + return nil, fmt.Errorf("unexpected pid '%s': %s", fields[pidIndex], err) + } + + if hasPid(procs, p) { + preContainedPidFlag = true + appendProcess2ProcList(procList, fields) + continue + } + preContainedPidFlag = false + } + return procList, nil +} diff --git a/pkg/containerutil/container_network_manager_windows.go b/pkg/containerutil/container_network_manager_windows.go index e81ea4560a9..6d85ca8fc68 100644 --- a/pkg/containerutil/container_network_manager_windows.go +++ b/pkg/containerutil/container_network_manager_windows.go @@ -118,12 +118,12 @@ func (m *cniNetworkManager) CleanupNetworking(ctx context.Context, container con return fmt.Errorf("failed to get container specs for networking cleanup: %s", err) } - netNsId, found := spec.Annotations[ocihook.NetworkNamespace] + netNsID, found := spec.Annotations[ocihook.NetworkNamespace] if !found { return fmt.Errorf("no %q annotation present on container with ID %s", ocihook.NetworkNamespace, containerID) } - return cni.Remove(ctx, containerID, netNsId, m.getCNINamespaceOpts()...) + return cni.Remove(ctx, containerID, netNsID, m.getCNINamespaceOpts()...) } // Returns the set of NetworkingOptions which should be set as labels on the container. diff --git a/pkg/netutil/netutil_windows.go b/pkg/netutil/netutil_windows.go index 8ae9bdb3486..8e0e67a01ed 100644 --- a/pkg/netutil/netutil_windows.go +++ b/pkg/netutil/netutil_windows.go @@ -95,7 +95,3 @@ func (e *CNIEnv) generateIPAM(driver string, subnets []string, gatewayStr, ipRan } return ipam, nil } - -func removeBridgeNetworkInterface(name string) error { - return nil -} diff --git a/pkg/ocihook/ocihook_windows.go b/pkg/ocihook/ocihook_windows.go index ef9df017c98..03323a67215 100644 --- a/pkg/ocihook/ocihook_windows.go +++ b/pkg/ocihook/ocihook_windows.go @@ -18,5 +18,4 @@ package ocihook func loadAppArmor() { //noop - return } diff --git a/pkg/statsutil/stats.go b/pkg/statsutil/stats.go index bfbf8b6e1c0..d732e1d837d 100644 --- a/pkg/statsutil/stats.go +++ b/pkg/statsutil/stats.go @@ -121,15 +121,6 @@ func (cs *Stats) SetError(err error) { } } -func calculateMemPercent(limit float64, usedNo float64) float64 { - // Limit will never be 0 unless the container is not running and we haven't - // got any data from cgroup - if limit != 0 { - return usedNo / limit * 100.0 - } - return 0 -} - // Rendering a FormattedStatsEntry from StatsEntry func RenderEntry(in *StatsEntry, noTrunc bool) FormattedStatsEntry { return FormattedStatsEntry{ diff --git a/pkg/statsutil/stats_linux.go b/pkg/statsutil/stats_linux.go index 3d88685daf9..61afba099bb 100644 --- a/pkg/statsutil/stats_linux.go +++ b/pkg/statsutil/stats_linux.go @@ -25,6 +25,15 @@ import ( v2 "github.com/containerd/cgroups/v3/cgroup2/stats" ) +func calculateMemPercent(limit float64, usedNo float64) float64 { + // Limit will never be 0 unless the container is not running and we haven't + // got any data from cgroup + if limit != 0 { + return usedNo / limit * 100.0 + } + return 0 +} + func SetCgroupStatsFields(previousStats *ContainerStats, data *v1.Metrics, links []netlink.Link) (StatsEntry, error) { cpuPercent := calculateCgroupCPUPercent(previousStats, data) diff --git a/pkg/sysinfo/sysinfo.go b/pkg/sysinfo/sysinfo.go index 4e0452423ac..0e150222c9b 100644 --- a/pkg/sysinfo/sysinfo.go +++ b/pkg/sysinfo/sysinfo.go @@ -70,13 +70,13 @@ type SysInfo struct { // cgMounts is the list of cgroup v1 mount paths, indexed by subsystem, to // inspect availability of subsystems. - cgMounts map[string]string + cgMounts map[string]string //nolint:unused // cg2GroupPath is the cgroup v2 group path to inspect availability of the controllers. - cg2GroupPath string + cg2GroupPath string //nolint:unused // cg2Controllers is an index of available cgroup v2 controllers. - cg2Controllers map[string]struct{} + cg2Controllers map[string]struct{} //nolint:unused } type cgroupMemInfo struct { diff --git a/pkg/testutil/iptables/iptables.go b/pkg/testutil/iptables/iptables_linux.go similarity index 100% rename from pkg/testutil/iptables/iptables.go rename to pkg/testutil/iptables/iptables_linux.go diff --git a/pkg/testutil/testregistry/certsd.go b/pkg/testutil/testregistry/certsd_linux.go similarity index 100% rename from pkg/testutil/testregistry/certsd.go rename to pkg/testutil/testregistry/certsd_linux.go From e0de7b1cdfbb997c5694bccd5fbb3903b318d5c2 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 3 Sep 2024 20:34:13 -0700 Subject: [PATCH 0741/1066] Fix freebsd lint Signed-off-by: apostasie --- cmd/nerdctl/container/container_cp_linux.go | 46 ++++++++++++ cmd/nerdctl/container/container_cp_unix.go | 70 ------------------- .../container_network_manager.go | 1 + pkg/netutil/netutil_test.go | 1 + pkg/ocihook/ocihook_freebsd.go | 1 - pkg/testutil/testutil_freebsd.go | 12 ++++ 6 files changed, 60 insertions(+), 71 deletions(-) delete mode 100644 cmd/nerdctl/container/container_cp_unix.go diff --git a/cmd/nerdctl/container/container_cp_linux.go b/cmd/nerdctl/container/container_cp_linux.go index 53abf9f898b..21ab42cc0c7 100644 --- a/cmd/nerdctl/container/container_cp_linux.go +++ b/cmd/nerdctl/container/container_cp_linux.go @@ -17,7 +17,10 @@ package container import ( + "errors" "fmt" + "path/filepath" + "strings" "github.com/spf13/cobra" @@ -131,3 +134,46 @@ func processCpOptions(cmd *cobra.Command, args []string) (types.ContainerCpOptio func AddCpCommand(rootCmd *cobra.Command) { rootCmd.AddCommand(newCpCommand()) } + +var errFileSpecDoesntMatchFormat = errors.New("filespec must match the canonical format: [container:]file/path") + +func parseCpFileSpec(arg string) (*cpFileSpec, error) { + i := strings.Index(arg, ":") + + // filespec starting with a semicolon is invalid + if i == 0 { + return nil, errFileSpecDoesntMatchFormat + } + + if filepath.IsAbs(arg) { + // Explicit local absolute path, e.g., `C:\foo` or `/foo`. + return &cpFileSpec{ + Container: nil, + Path: arg, + }, nil + } + + parts := strings.SplitN(arg, ":", 2) + + if len(parts) == 1 || strings.HasPrefix(parts[0], ".") { + // Either there's no `:` in the arg + // OR it's an explicit local relative path like `./file:name.txt`. + return &cpFileSpec{ + Path: arg, + }, nil + } + + return &cpFileSpec{ + Container: &parts[0], + Path: parts[1], + }, nil +} + +type cpFileSpec struct { + Container *string + Path string +} + +func cpShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return nil, cobra.ShellCompDirectiveFilterFileExt +} diff --git a/cmd/nerdctl/container/container_cp_unix.go b/cmd/nerdctl/container/container_cp_unix.go deleted file mode 100644 index e6e1f70dce1..00000000000 --- a/cmd/nerdctl/container/container_cp_unix.go +++ /dev/null @@ -1,70 +0,0 @@ -//go:build unix - -/* - 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 container - -import ( - "errors" - "path/filepath" - "strings" - - "github.com/spf13/cobra" -) - -var errFileSpecDoesntMatchFormat = errors.New("filespec must match the canonical format: [container:]file/path") - -func parseCpFileSpec(arg string) (*cpFileSpec, error) { - i := strings.Index(arg, ":") - - // filespec starting with a semicolon is invalid - if i == 0 { - return nil, errFileSpecDoesntMatchFormat - } - - if filepath.IsAbs(arg) { - // Explicit local absolute path, e.g., `C:\foo` or `/foo`. - return &cpFileSpec{ - Container: nil, - Path: arg, - }, nil - } - - parts := strings.SplitN(arg, ":", 2) - - if len(parts) == 1 || strings.HasPrefix(parts[0], ".") { - // Either there's no `:` in the arg - // OR it's an explicit local relative path like `./file:name.txt`. - return &cpFileSpec{ - Path: arg, - }, nil - } - - return &cpFileSpec{ - Container: &parts[0], - Path: parts[1], - }, nil -} - -type cpFileSpec struct { - Container *string - Path string -} - -func cpShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveFilterFileExt -} diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index fa303ad3e9c..d596b3eb543 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -649,6 +649,7 @@ func writeEtcHostnameForContainer(globalOptions types.GlobalCommandOptions, host // Loads all available networks and verifies that every selected network // from the networkSlice is of a type within supportedTypes. +// nolint:unused func verifyNetworkTypes(env *netutil.CNIEnv, networkSlice []string, supportedTypes []string) (map[string]*netutil.NetworkConfig, error) { netMap, err := env.NetworkMap() if err != nil { diff --git a/pkg/netutil/netutil_test.go b/pkg/netutil/netutil_test.go index 30c4c4084ac..512dfe226c5 100644 --- a/pkg/netutil/netutil_test.go +++ b/pkg/netutil/netutil_test.go @@ -133,6 +133,7 @@ func TestParseIPAMRange(t *testing.T) { // Note that this test will require a CNI driver bearing the same name as // the type of the default network. (denoted by netutil.DefaultNetworkName, // which is used as both the name of the default network and its Driver) +// nolint:unused func testDefaultNetworkCreation(t *testing.T) { // To prevent subnet collisions when attempting to recreate the default network // in the isolated CNI config dir we'll be using, we must first delete diff --git a/pkg/ocihook/ocihook_freebsd.go b/pkg/ocihook/ocihook_freebsd.go index ef9df017c98..03323a67215 100644 --- a/pkg/ocihook/ocihook_freebsd.go +++ b/pkg/ocihook/ocihook_freebsd.go @@ -18,5 +18,4 @@ package ocihook func loadAppArmor() { //noop - return } diff --git a/pkg/testutil/testutil_freebsd.go b/pkg/testutil/testutil_freebsd.go index 91bb973c11e..9cbded4e258 100644 --- a/pkg/testutil/testutil_freebsd.go +++ b/pkg/testutil/testutil_freebsd.go @@ -16,6 +16,8 @@ package testutil +import "fmt" + const ( CommonImage = "docker.io/knast/freebsd:13-STABLE" @@ -26,3 +28,13 @@ const ( // https://www.rfc-editor.org/rfc/rfc793 ExpectedConnectionRefusedError = "connection refused" ) + +var ( + AlpineImage = mirrorOf("alpine:3.13") + NginxAlpineImage = mirrorOf("nginx:1.19-alpine") +) + +func mirrorOf(s string) string { + // plain mirror, NOT stargz-converted images + return fmt.Sprintf("ghcr.io/stargz-containers/%s-org", s) +} From ca0f64537520e3fec110825c9264cbe6cc02404f Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 3 Sep 2024 20:38:25 -0700 Subject: [PATCH 0742/1066] Enforce linting for freebsd and windows Signed-off-by: apostasie --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 685aa439169..0831c640047 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,9 @@ clean: lint: lint-go lint-imports lint-yaml lint-shell lint-go: - cd $(MAKEFILE_DIR) && golangci-lint run $(VERBOSE_FLAG_LONG) ./... + cd $(MAKEFILE_DIR) && GOOS=linux golangci-lint run $(VERBOSE_FLAG_LONG) ./... && \ + GOOS=windows golangci-lint run $(VERBOSE_FLAG_LONG) ./... && \ + GOOS=freebsd golangci-lint run $(VERBOSE_FLAG_LONG) ./... lint-imports: cd $(MAKEFILE_DIR) && ./hack/lint-imports.sh From dbc05409edb88d87f41d1ed3ddf050b482516eec Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 3 Sep 2024 12:37:54 -0700 Subject: [PATCH 0743/1066] Fix TestLoadStdinFromPipe: do not leak test images breaking tests using prune Signed-off-by: apostasie --- cmd/nerdctl/image/image_load_linux_test.go | 28 +++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/cmd/nerdctl/image/image_load_linux_test.go b/cmd/nerdctl/image/image_load_linux_test.go index d92a2167f80..4d7b0f83dce 100644 --- a/cmd/nerdctl/image/image_load_linux_test.go +++ b/cmd/nerdctl/image/image_load_linux_test.go @@ -32,23 +32,35 @@ import ( func TestLoadStdinFromPipe(t *testing.T) { t.Parallel() base := testutil.NewBase(t) - + img := testutil.Identifier(t) tmp := t.TempDir() - img := testutil.Identifier(t) + "image" - base.Cmd("pull", testutil.CommonImage).AssertOK() - base.Cmd("tag", testutil.CommonImage, img).AssertOK() - base.Cmd("save", img, "-o", filepath.Join(tmp, "common.tar")).AssertOK() - base.Cmd("rmi", "-f", img).AssertOK() - loadCmd := strings.Join(base.Cmd("load").Command, " ") output := filepath.Join(tmp, "output") + setup := func() { + base.Cmd("pull", testutil.CommonImage).AssertOK() + base.Cmd("tag", testutil.CommonImage, img).AssertOK() + base.Cmd("save", img, "-o", filepath.Join(tmp, "common.tar")).AssertOK() + base.Cmd("rmi", "-f", img).AssertOK() + } + + tearDown := func() { + base.Cmd("rmi", "-f", img).AssertOK() + } + + t.Cleanup(tearDown) + tearDown() + + setup() + + loadCmd := strings.Join(base.Cmd("load").Command, " ") combined, err := exec.Command("sh", "-euxc", fmt.Sprintf("`cat %s/common.tar | %s > %s`", tmp, loadCmd, output)).CombinedOutput() assert.NilError(t, err, "failed with error %s and combined output is %s", err, string(combined)) + fb, err := os.ReadFile(output) assert.NilError(t, err) assert.Assert(t, strings.Contains(string(fb), fmt.Sprintf("Loaded image: %s:latest", img))) - base.Cmd("images").AssertOutContains(testutil.ImageRepo(testutil.CommonImage)) + base.Cmd("images").AssertOutContains(img) } func TestLoadStdinEmpty(t *testing.T) { From 935ee8a029b080ac700baa15d40dca797caa2cf9 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 3 Sep 2024 13:52:10 -0700 Subject: [PATCH 0744/1066] Fix TestRunApparmor: relax stdout matching to not fail when testing rootless Signed-off-by: apostasie --- cmd/nerdctl/container/container_run_security_linux_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/nerdctl/container/container_run_security_linux_test.go b/cmd/nerdctl/container/container_run_security_linux_test.go index aa0775bbf9c..e5c6ec87b1e 100644 --- a/cmd/nerdctl/container/container_run_security_linux_test.go +++ b/cmd/nerdctl/container/container_run_security_linux_test.go @@ -182,8 +182,8 @@ func TestRunApparmor(t *testing.T) { attrCurrentEnforceExpected := fmt.Sprintf("%s (enforce)\n", defaultProfile) base.Cmd("run", "--rm", testutil.AlpineImage, "cat", attrCurrentPath).AssertOutExactly(attrCurrentEnforceExpected) base.Cmd("run", "--rm", "--security-opt", "apparmor="+defaultProfile, testutil.AlpineImage, "cat", attrCurrentPath).AssertOutExactly(attrCurrentEnforceExpected) - base.Cmd("run", "--rm", "--security-opt", "apparmor=unconfined", testutil.AlpineImage, "cat", attrCurrentPath).AssertOutExactly("unconfined\n") - base.Cmd("run", "--rm", "--privileged", testutil.AlpineImage, "cat", attrCurrentPath).AssertOutExactly("unconfined\n") + base.Cmd("run", "--rm", "--security-opt", "apparmor=unconfined", testutil.AlpineImage, "cat", attrCurrentPath).AssertOutContains("unconfined") + base.Cmd("run", "--rm", "--privileged", testutil.AlpineImage, "cat", attrCurrentPath).AssertOutContains("unconfined") } // TestRunSeccompCapSysPtrace tests https://github.com/containerd/nerdctl/issues/976 From 4c0c5a6040d56e3be877fa1c607e756fcab9f7ba Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 4 Sep 2024 00:16:08 -0700 Subject: [PATCH 0745/1066] Move testing.md to docs/dev Signed-off-by: apostasie --- .github/workflows/test-canary.yml | 2 +- .github/workflows/test-kube.yml | 2 +- .github/workflows/test.yml | 6 +++--- README.md | 2 +- docs/{ => dev}/testing.md | 0 5 files changed, 6 insertions(+), 6 deletions(-) rename docs/{ => dev}/testing.md (100%) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 0a21c29d523..7c385edb236 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -112,5 +112,5 @@ jobs: ctrdVersion: ${{ env.CONTAINERD_VERSION }} run: powershell hack/configure-windows-ci.ps1 - name: "Run integration tests" - # See https://github.com/containerd/nerdctl/blob/main/docs/testing.md#about-parallelization + # See https://github.com/containerd/nerdctl/blob/main/docs/dev/testing.md#about-parallelization run: go test -p 1 -v ./cmd/nerdctl/... diff --git a/.github/workflows/test-kube.yml b/.github/workflows/test-kube.yml index 2d00b532603..cb487898173 100644 --- a/.github/workflows/test-kube.yml +++ b/.github/workflows/test-kube.yml @@ -22,7 +22,7 @@ jobs: with: fetch-depth: 1 - name: "Run Kubernetes integration tests" - # See https://github.com/containerd/nerdctl/blob/main/docs/testing.md#about-parallelization + # See https://github.com/containerd/nerdctl/blob/main/docs/dev/testing.md#about-parallelization run: | ./hack/build-integration-kubernetes.sh sudo ./_output/nerdctl exec nerdctl-test-control-plane bash -c -- 'export TMPDIR="$HOME"/tmp; mkdir -p "$TMPDIR"; cd /nerdctl-source; /usr/local/go/bin/go test -p 1 ./cmd/nerdctl/... -test.only-kubernetes' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3567d43436c..f00e7c85a8d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -290,7 +290,7 @@ jobs: timeout_minutes: 30 max_attempts: 2 retry_on: error - # See https://github.com/containerd/nerdctl/blob/main/docs/testing.md#about-parallelization + # See https://github.com/containerd/nerdctl/blob/main/docs/dev/testing.md#about-parallelization command: go test -p 1 -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon - name: "Ensure that the IPv6 integration test suite is compatible with Docker" uses: nick-fields/retry@v3 @@ -298,7 +298,7 @@ jobs: timeout_minutes: 30 max_attempts: 2 retry_on: error - # See https://github.com/containerd/nerdctl/blob/main/docs/testing.md#about-parallelization + # See https://github.com/containerd/nerdctl/blob/main/docs/dev/testing.md#about-parallelization command: go test -p 1 -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon -test.only-ipv6 test-integration-windows: @@ -332,7 +332,7 @@ jobs: run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" - # See https://github.com/containerd/nerdctl/blob/main/docs/testing.md#about-parallelization + # See https://github.com/containerd/nerdctl/blob/main/docs/dev/testing.md#about-parallelization run: go test -p 1 -v ./cmd/nerdctl/... test-integration-freebsd: diff --git a/README.md b/README.md index 79a79473e48..ef85dbd54f5 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ Using `go install github.com/containerd/nerdctl/v2/cmd/nerdctl` is possible, but ### Testing -See [testing nerdctl](docs/testing.md). +See [testing nerdctl](docs/dev/testing.md). ### Contributing to nerdctl diff --git a/docs/testing.md b/docs/dev/testing.md similarity index 100% rename from docs/testing.md rename to docs/dev/testing.md From ea86ae9a4366520cf64db08b4769f237f68b3353 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 4 Sep 2024 00:18:27 -0700 Subject: [PATCH 0746/1066] Adding document about pkg/store Signed-off-by: apostasie --- docs/dev/store.md | 163 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 docs/dev/store.md diff --git a/docs/dev/store.md b/docs/dev/store.md new file mode 100644 index 00000000000..c0954fb0063 --- /dev/null +++ b/docs/dev/store.md @@ -0,0 +1,163 @@ +# About `pkg/store` + +## TL;DR + +You _may_ want to read this if you are developing something in nerdctl that would involve storing persistent information. + +If there is a "store" already in the codebase (eg: volumestore, namestore, etc) that does provide the methods that you need, +you are fine and should just stick to that. + +On the other hand, if you are curious, or if what you want to write is "new", then _you should_ have a look at this document: +it does provide extended information about how we manage persistent data storage, especially with regard to concurrency +and atomicity. + +## Motivation + +The core of nerdctl aims at keeping its dependencies as lightweight as possible. +For that reason, nerdctl does not use a database to store persistent information, but instead uses the filesystem, +under a variety of directories. + +That "information" is typically volumes metadata, containers lifecycle info, the "name store" (which does ensure no two +containers can be named the same), etc. + +However, storing data on the filesystem in a reliable way comes with challenges: +- incomplete writes may happen (because of a system restart, or an application crash), leaving important structured files +in a broken state +- concurrent writes, or reading while writing would obviously be a problem as well, be it accross goroutines, or between +concurrent executions of the nerdctl binary, or embedded in a third-party application that does concurrently access resources + +The `pkg/store` package does provide a "storage" abstraction that takes care of these issues, generally providing +guarantees that concurrent operations can be performed safely, and that writes are "atomic", ensuring we never brick +user installs. + +For details about how, and what is done, read-on. + +## The problem with writing a file + +A write may very well be interrupted. + +While reading the resulting mangled file will typically break `json.Unmarshall` for example, and while we should still +handle such cases gracefully and provide meaningful information to the user about which file is damaged (which could be due +to the user manually modifying them), using "atomic" writes will (almost always (*)) prevent this from happening +on our part. + +An "atomic" write is usually performed by first writing data to a temporary file, and then, only if the write operation +succeeded, move that temporary file to its final destination. + +The `rename` syscall (see https://man7.org/linux/man-pages/man2/rename.2.html) is indeed "atomic" +(eg: it fully succeeds, or fails), providing said guarantees that you end-up with a complete file that has the entirety +of what was meant to be written. + +This is an "almost always", as an _operating system crash_ MAY break that promise (this is highly dependent on specifics +that are out of scope here, and that nerdctl has no control over). +Though, crashing operating systems is (hopefully) a sufficiently rare event that we can consider we "always" have atomic writes. + +There is one caveat with "rename-based atomic writes" though: if you mount the file itself inside a container, +an atomic write will not work as you expect, as the inode will (obviously) change when you modify the file, +and these changes will not be propagated inside the container. + +This caveat is the reason why `hostsstore` does NOT use an atomic write to update the `hosts` file, but a traditional write. + +## Concurrency between go routines + +This is a (simple) well-known problem. Just use a mutex to prevent concurrent modifications of the same object. + +Note that this is not much of a problem right now in nerdctl itself - but it might be in third-party applications using +our codebase. + +This is just generally good hygiene when building concurrency-safe packages. + +## Concurrency between distinct binary invocations + +This is much more of a problem. + +There are many good reasons and real-life scenarios where concurrent binary execution may happen. +A third-party deployment tool (similar to terraform for eg), that will batch a bunch of operations to be performed +to achieve a desired infrastructure state, and call many `nerdctl` invocations in parallel to achieve that. +This is also common-place in testing (subpackages). +And of course, a third-party tool that would be long-running and allow parallel execution, leveraging nerdctl codebase +as a library, may certainly produce these circumstances. + +The known answer to that problem is to use a filesystem lock (or flock). + +Concretely, the first process will "lock" a directory. All other processes trying to do the same will then be put +in a queue and wait for the prior lock to be released before they can "lock" themselves, in turn. + +Filesystem locking comes with its own set of challenges: +- implementation is somewhat low-level (the golang core library keeps their implementation internal, and you have to +reimplement your own with platform-dependent APIs and syscalls) +- it is tricky to get right - there are reasons why golang core does not make it public +- locking "scope" should be done carefully: having ONE global lock for everything will definitely hurt performance badly, +as you will basically make everything "sequential", effectively destroying some of the benefits of parallelizing code +in the first place... + +## Lock design... + +While it is tempting to just provide self-locking, individual methods as an API (`Get`, `Set`), this is not the right +answer. + +Imagine a context where consuming code would first like to check if something exists, then later on create it if it does not: +```golang +if !store.Exists("something") { + // do things + // ... + // Now, create + store.Set([]byte("data"), "something") +} +``` + +You do have two methods (`Get` and `Set`) that _may individually_ guarantee they are the sole user of that resource, +but a concurrent change _in between_ these two calls may very well (and _will_) happen and change the state of the world. + +Effectively, in that case, `Set` might overwrite changes made by another go routine or concurrent execution, possibly +wrecking havoc in another process. + +_When_ to lock, and _for how long_, is a decision that only the embedding code can make. + +A good example is container creation. +It may require the creation of several different volumes. +In that case, you want to lock at the start of the container creation process, and only release the lock when you are fully +done creating the container - not just when done creating a volume (nor even when done creating all volumes). + +## ... while safeguarding the developer + +nerdctl still provides some safeguards for the developer. + +Any store method that DOES require locking will fail loudly if it does not detect a lock. + +This is obviously not bullet-proof. +For example, the lock may belong to another goroutine instead of the one we are in (and we cannot detect that). +But this is still better than nothing, and will help developers making sure they **do** lock. + +## Using the `store` api to implement your own storage + +While - as mentioned above - the store does _not_ lock on its own, specific "stores implementations" may, and should, +provide higher-level methods that best fit their data-model usage, and that **do** lock on their own. + +For example, the namestore (which is the simplest store), does provide three simple methods: +- Acquire +- Release +- Rename + +Users of the `namestore` do not have to bother with locking. These methods are safe to use concurrently. + +This is a good example of how to leverage core store primitives to implement a developer friendly, safe storage for +"something" (in that case "names"). + +Finaly note an important point - mentioned above: locking should be done to the smallest possible "segment" of sub-directories. +Specifically, any store should lock only - at most - resources under the _namespace_ being manipulated. + +For example, a container lifecycle storage should not lock out any other container, but only its own private directory. + +## Scope, ambitions and future + +`pkg/store` has no ambition whatsoever to be a generic solution, usable outside nerdctl. + +It is solely designed to fit nerdctl needs, and if it was to be made usable standalone, would probably have to be modified +extensively, which is clearly out of scope here. + +Furthermore, there are already much more advanced generic solutions out there that you should use instead for outside-of-nerdctl projects. + +As for future, one nice thing we should consider is to implement read-only locks in addition to the exclusive, write-locks +we currently use. +The net benefit would be a performance boost in certain contexts (massively parallel, mostly read environments). \ No newline at end of file From 7bcfc5058c30b339e4c35f29b085a363a4d6e97d Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 4 Sep 2024 23:40:22 +0900 Subject: [PATCH 0747/1066] Dockerfile: runc: set CC and STRIP explicitly Split from PR 3153. Needed for cross-compilation of runc v1.2. Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 15f2f859148..36ff9c41381 100644 --- a/Dockerfile +++ b/Dockerfile @@ -90,7 +90,7 @@ WORKDIR /go/src/github.com/opencontainers/runc RUN git checkout ${RUNC_VERSION} && \ mkdir -p /out ENV CGO_ENABLED=1 -RUN GO=xx-go make static && \ +RUN GO=xx-go CC=$(xx-info)-gcc STRIP=$(xx-info)-strip make static && \ xx-verify --static runc && cp -v -a runc /out/runc.${TARGETARCH} FROM build-base-debian AS build-bypass4netns From 1a4a5a95fa3d82645275d5706878fee6f74abd57 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 4 Sep 2024 12:29:09 -0700 Subject: [PATCH 0748/1066] Hostsstore resolution cleanup As described in https://github.com/containerd/nerdctl/issues/3047, hosts.toml file lookup will treat https://foo:443 and https://foo differently, possibly leading to divergent behaviors *for the same registry*. This PR makes it so that a registry URL using the default https port (443) will ALSO lookup files stored in a "portless" directory. Finally, as dockerconfigresolver.go will soon go under significant changes, the hosts.toml resolution functions have been also isolated in their separate, own file. Signed-off-by: apostasie --- .../dockerconfigresolver.go | 37 ++++------- .../dockerconfigresolver/hostsstore.go | 66 +++++++++++++++++++ 2 files changed, 79 insertions(+), 24 deletions(-) create mode 100644 pkg/imgutil/dockerconfigresolver/hostsstore.go diff --git a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go index 47a7be13c29..5262dd729d0 100644 --- a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go +++ b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go @@ -20,7 +20,6 @@ import ( "context" "crypto/tls" "errors" - "os" "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/containerd/v2/core/remotes/docker" @@ -57,24 +56,9 @@ func WithSkipVerifyCerts(b bool) Opt { // WithHostsDirs specifies directories like /etc/containerd/certs.d and /etc/docker/certs.d func WithHostsDirs(orig []string) Opt { - var ss []string - if len(orig) == 0 { - log.L.Debug("no hosts dir was specified") - } - for _, v := range orig { - if _, err := os.Stat(v); err == nil { - log.L.Debugf("Found hosts dir %q", v) - ss = append(ss, v) - } else { - if errors.Is(err, os.ErrNotExist) { - log.L.WithError(err).Debugf("Ignoring hosts dir %q", v) - } else { - log.L.WithError(err).Warnf("Ignoring hosts dir %q", v) - } - } - } + validDirs := validateDirectories(orig) return func(o *opts) { - o.hostsDirs = ss + o.hostsDirs = validDirs } } @@ -96,14 +80,19 @@ func NewHostOptions(ctx context.Context, refHostname string, optFuncs ...Opt) (* } var ho dockerconfig.HostOptions - ho.HostDir = func(s string) (string, error) { - for _, hostsDir := range o.hostsDirs { - found, err := dockerconfig.HostDirFromRoot(hostsDir)(s) - if (err != nil && !errdefs.IsNotFound(err)) || (found != "") { - return found, err + ho.HostDir = func(hostURL string) (string, error) { + regURL, err := Parse(hostURL) + if err != nil { + return "", err + } + dir, err := hostDirsFromRoot(regURL, o.hostsDirs) + if err != nil { + if errors.Is(err, errdefs.ErrNotFound) { + err = nil } + return "", err } - return "", nil + return dir, nil } if o.authCreds != nil { diff --git a/pkg/imgutil/dockerconfigresolver/hostsstore.go b/pkg/imgutil/dockerconfigresolver/hostsstore.go new file mode 100644 index 00000000000..0273a9cd7a6 --- /dev/null +++ b/pkg/imgutil/dockerconfigresolver/hostsstore.go @@ -0,0 +1,66 @@ +/* + 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 dockerconfigresolver + +import ( + "errors" + "os" + + "github.com/containerd/containerd/v2/core/remotes/docker/config" + "github.com/containerd/errdefs" + "github.com/containerd/log" +) + +// validateDirectories inspect a slice of strings and returns the ones that are valid readable directories +func validateDirectories(orig []string) []string { + ss := []string{} + for _, v := range orig { + fi, err := os.Stat(v) + if err != nil || !fi.IsDir() { + if !errors.Is(err, os.ErrNotExist) { + log.L.WithError(err).Warnf("Ignoring hosts location %q", v) + } + continue + } + ss = append(ss, v) + } + return ss +} + +// hostDirsFromRoot will retrieve a host.toml file for the namespace host, possibly trying without port +// if the requested port is standard. +// https://github.com/containerd/nerdctl/issues/3047 +func hostDirsFromRoot(registryURL *RegistryURL, dirs []string) (string, error) { + hostsDirs := validateDirectories(dirs) + + // Go through the configured system location to consider for hosts.toml files + for _, hostsDir := range hostsDirs { + found, err := config.HostDirFromRoot(hostsDir)(registryURL.Host) + // If we errored with anything but NotFound, or if we found one, return now + if (err != nil && !errdefs.IsNotFound(err)) || (found != "") { + return found, err + } + // If not found, and the port is standard, try again without the port + if registryURL.Port() == standardHTTPSPort { + found, err = config.HostDirFromRoot(hostsDir)(registryURL.Hostname()) + if (err != nil && !errors.Is(err, errdefs.ErrNotFound)) || (found != "") { + return found, err + } + } + } + return "", nil +} From 1ecbd87a0961cd12ff0fbdda158e4d62f9bcf2e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 22:58:51 +0000 Subject: [PATCH 0749/1066] build(deps): bump the golang-x group with 3 updates Bumps the golang-x group with 3 updates: [golang.org/x/sys](https://github.com/golang/sys), [golang.org/x/term](https://github.com/golang/term) and [golang.org/x/text](https://github.com/golang/text). Updates `golang.org/x/sys` from 0.24.0 to 0.25.0 - [Commits](https://github.com/golang/sys/compare/v0.24.0...v0.25.0) Updates `golang.org/x/term` from 0.23.0 to 0.24.0 - [Commits](https://github.com/golang/term/compare/v0.23.0...v0.24.0) Updates `golang.org/x/text` from 0.17.0 to 0.18.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.17.0...v0.18.0) --- updated-dependencies: - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index aebb89b9bf8..0d2f3a36c0b 100644 --- a/go.mod +++ b/go.mod @@ -68,9 +68,9 @@ require ( golang.org/x/crypto v0.26.0 golang.org/x/net v0.28.0 golang.org/x/sync v0.8.0 - golang.org/x/sys v0.24.0 - golang.org/x/term v0.23.0 - golang.org/x/text v0.17.0 + golang.org/x/sys v0.25.0 + golang.org/x/term v0.24.0 + golang.org/x/text v0.18.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) diff --git a/go.sum b/go.sum index 0afe83322b8..894c2a6c6b6 100644 --- a/go.sum +++ b/go.sum @@ -382,14 +382,14 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From 4bb3fc02cc1a21a0b04b6d4baaf528d6b4e252e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 22:56:58 +0000 Subject: [PATCH 0750/1066] build(deps): bump the golang-x group with 2 updates Bumps the golang-x group with 2 updates: [golang.org/x/crypto](https://github.com/golang/crypto) and [golang.org/x/net](https://github.com/golang/net). Updates `golang.org/x/crypto` from 0.26.0 to 0.27.0 - [Commits](https://github.com/golang/crypto/compare/v0.26.0...v0.27.0) Updates `golang.org/x/net` from 0.28.0 to 0.29.0 - [Commits](https://github.com/golang/net/compare/v0.28.0...v0.29.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 0d2f3a36c0b..99fd88abe01 100644 --- a/go.mod +++ b/go.mod @@ -65,8 +65,8 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.26.0 - golang.org/x/net v0.28.0 + golang.org/x/crypto v0.27.0 + golang.org/x/net v0.29.0 golang.org/x/sync v0.8.0 golang.org/x/sys v0.25.0 golang.org/x/term v0.24.0 diff --git a/go.sum b/go.sum index 894c2a6c6b6..e17f4e03f6c 100644 --- a/go.sum +++ b/go.sum @@ -336,8 +336,8 @@ go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= @@ -357,8 +357,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From aeef5bedad16c7504951529e8623fa5e75933c81 Mon Sep 17 00:00:00 2001 From: TinaMor Date: Tue, 13 Aug 2024 16:30:43 +0300 Subject: [PATCH 0751/1066] Fix Windows path check in 'LogURIGenerator' Signed-off-by: Christine Murimi --- .../container/container_run_linux_test.go | 21 ++++++++++++++++ cmd/nerdctl/container/container_run_test.go | 24 ------------------- .../container/container_run_windows_test.go | 15 ++++++++++++ pkg/taskutil/taskutil.go | 8 +++++-- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/cmd/nerdctl/container/container_run_linux_test.go b/cmd/nerdctl/container/container_run_linux_test.go index 2d114e93ddb..aca549d9446 100644 --- a/cmd/nerdctl/container/container_run_linux_test.go +++ b/cmd/nerdctl/container/container_run_linux_test.go @@ -498,3 +498,24 @@ func TestRunWithDetachKeys(t *testing.T) { container := base.InspectContainer(containerName) assert.Equal(base.T, container.State.Running, true) } + +func TestRunWithTtyAndDetached(t *testing.T) { + base := testutil.NewBase(t) + imageName := testutil.CommonImage + withoutTtyContainerName := "without-terminal-" + testutil.Identifier(t) + withTtyContainerName := "with-terminal-" + testutil.Identifier(t) + + // without -t, fail + base.Cmd("run", "-d", "--name", withoutTtyContainerName, imageName, "stty").AssertOK() + defer base.Cmd("container", "rm", "-f", withoutTtyContainerName).AssertOK() + base.Cmd("logs", withoutTtyContainerName).AssertCombinedOutContains("stty: standard input: Not a tty") + withoutTtyContainer := base.InspectContainer(withoutTtyContainerName) + assert.Equal(base.T, 1, withoutTtyContainer.State.ExitCode) + + // with -t, success + base.Cmd("run", "-d", "-t", "--name", withTtyContainerName, imageName, "stty").AssertOK() + defer base.Cmd("container", "rm", "-f", withTtyContainerName).AssertOK() + base.Cmd("logs", withTtyContainerName).AssertCombinedOutContains("speed 38400 baud; line = 0;") + withTtyContainer := base.InspectContainer(withTtyContainerName) + assert.Equal(base.T, 0, withTtyContainer.State.ExitCode) +} diff --git a/cmd/nerdctl/container/container_run_test.go b/cmd/nerdctl/container/container_run_test.go index 8d64226198c..d6d7f4a576f 100644 --- a/cmd/nerdctl/container/container_run_test.go +++ b/cmd/nerdctl/container/container_run_test.go @@ -459,30 +459,6 @@ COPY --from=builder /go/src/logger/logger / assert.Check(t, strings.Contains(log, "bar")) } -func TestRunWithTtyAndDetached(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) - withTtyContainerName := "with-terminal-" + testutil.Identifier(t) - - // without -t, fail - base.Cmd("run", "-d", "--name", withoutTtyContainerName, imageName, "stty").AssertOK() - defer base.Cmd("container", "rm", "-f", withoutTtyContainerName).AssertOK() - base.Cmd("logs", withoutTtyContainerName).AssertCombinedOutContains("stty: standard input: Not a tty") - withoutTtyContainer := base.InspectContainer(withoutTtyContainerName) - assert.Equal(base.T, 1, withoutTtyContainer.State.ExitCode) - - // with -t, success - base.Cmd("run", "-d", "-t", "--name", withTtyContainerName, imageName, "stty").AssertOK() - defer base.Cmd("container", "rm", "-f", withTtyContainerName).AssertOK() - base.Cmd("logs", withTtyContainerName).AssertCombinedOutContains("speed 38400 baud; line = 0;") - withTtyContainer := base.InspectContainer(withTtyContainerName) - assert.Equal(base.T, 0, withTtyContainer.State.ExitCode) -} - // history: There was a bug that the --add-host items disappear when the another container created. // This case ensures that it's doesn't happen. // (https://github.com/containerd/nerdctl/issues/2560) diff --git a/cmd/nerdctl/container/container_run_windows_test.go b/cmd/nerdctl/container/container_run_windows_test.go index c7ec6e72aa1..2b63a4f215c 100644 --- a/cmd/nerdctl/container/container_run_windows_test.go +++ b/cmd/nerdctl/container/container_run_windows_test.go @@ -117,3 +117,18 @@ func TestRunProcessContainerWithDevice(t *testing.T) { "cmd", "/S", "/C", "dir C:\\Windows\\System32\\HostDriverStore", ).AssertOutContains("FileRepository") } + +func TestRunWithTtyAndDetached(t *testing.T) { + base := testutil.NewBase(t) + imageName := testutil.CommonImage + withTtyContainerName := "with-terminal-" + testutil.Identifier(t) + + // with -t, success, the container should run with tty support. + base.Cmd("run", "-d", "-t", "--name", withTtyContainerName, imageName, "cmd", "/c", "echo", "Hello, World with TTY!").AssertOK() + defer base.Cmd("container", "rm", "-f", withTtyContainerName).AssertOK() + + // Check logs for successful command execution (with TTY specific behavior if any) + base.Cmd("logs", withTtyContainerName).AssertOutContains("Hello, World with TTY!") + withTtyContainer := base.InspectContainer(withTtyContainerName) + assert.Equal(base.T, 0, withTtyContainer.State.ExitCode) +} diff --git a/pkg/taskutil/taskutil.go b/pkg/taskutil/taskutil.go index fe6cd15fd83..35ac3d8effc 100644 --- a/pkg/taskutil/taskutil.go +++ b/pkg/taskutil/taskutil.go @@ -96,11 +96,15 @@ func NewTask(ctx context.Context, client *containerd.Client, container container if len(args) != 2 { return nil, errors.New("parse logging path error") } - ioCreator = cio.TerminalBinaryIO(u.Path, map[string]string{ + parsedPath := u.Path + // For Windows, remove the leading slash + if (runtime.GOOS == "windows") && (strings.HasPrefix(parsedPath, "/")) { + parsedPath = strings.TrimLeft(parsedPath, "/") + } + ioCreator = cio.TerminalBinaryIO(parsedPath, map[string]string{ args[0]: args[1], }) } else if flagT && !flagD { - if con == nil { return nil, errors.New("got nil con with flagT=true") } From 6f685c374ec6971dabf1a58df7e4304534de7ca2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 22:02:52 +0000 Subject: [PATCH 0752/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.2.0+incompatible to 27.2.1+incompatible - [Commits](https://github.com/docker/cli/compare/v27.2.0...v27.2.1) Updates `github.com/docker/docker` from 27.2.0+incompatible to 27.2.1+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.2.0...v27.2.1) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 99fd88abe01..abb43c44bbe 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.1 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.2.0+incompatible - github.com/docker/docker v27.2.0+incompatible + github.com/docker/cli v27.2.1+incompatible + github.com/docker/docker v27.2.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index e17f4e03f6c..8137f7b0cee 100644 --- a/go.sum +++ b/go.sum @@ -88,10 +88,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.2.0+incompatible h1:yHD1QEB1/0vr5eBNpu8tncu8gWxg8EydFPOSKHzXSMM= -github.com/docker/cli v27.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.2.0+incompatible h1:Rk9nIVdfH3+Vz4cyI/uhbINhEZ/oLmc+CBXmH6fbNk4= -github.com/docker/docker v27.2.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.2.1+incompatible h1:U5BPtiD0viUzjGAjV1p0MGB8eVA3L3cbIrnyWmSJI70= +github.com/docker/cli v27.2.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.2.1+incompatible h1:fQdiLfW7VLscyoeYEBz7/J8soYFDZV1u6VW6gJEjNMI= +github.com/docker/docker v27.2.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From e22055bccc1c57451f4d7023ab4951e21d886ce4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2024 22:32:57 +0000 Subject: [PATCH 0753/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.1.6 to 2.2.0. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.1.6...v2.2.0) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index abb43c44bbe..08629f9b9be 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.6 - github.com/compose-spec/compose-go/v2 v2.1.6 + github.com/compose-spec/compose-go/v2 v2.2.0 github.com/containerd/accelerated-container-image v1.2.1 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index 8137f7b0cee..7e0f7f384b1 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.1.6 h1:d0Cs0DffmOwmSzs0YPHwKCskknGq2jfGg4uGowlEpps= -github.com/compose-spec/compose-go/v2 v2.1.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.2.0 h1:VsQosGhuO+H9wh5laiIiAe4TVd73kQ5NWwmNrdm0HRA= +github.com/compose-spec/compose-go/v2 v2.2.0/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.1 h1:ODV7nD5o5VmHIZT1OzadRQxOBLnQWnvSEouG6hFh6hA= github.com/containerd/accelerated-container-image v1.2.1/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= From 646f8409f7d0e9ce5e73b74fe43cc065b1770d23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 21:57:25 +0000 Subject: [PATCH 0754/1066] build(deps): bump github.com/containerd/accelerated-container-image Bumps [github.com/containerd/accelerated-container-image](https://github.com/containerd/accelerated-container-image) from 1.2.1 to 1.2.2. - [Release notes](https://github.com/containerd/accelerated-container-image/releases) - [Commits](https://github.com/containerd/accelerated-container-image/compare/v1.2.1...v1.2.2) --- updated-dependencies: - dependency-name: github.com/containerd/accelerated-container-image dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 08629f9b9be..aa99f044b91 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.6 github.com/compose-spec/compose-go/v2 v2.2.0 - github.com/containerd/accelerated-container-image v1.2.1 + github.com/containerd/accelerated-container-image v1.2.2 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0-rc.3 diff --git a/go.sum b/go.sum index 7e0f7f384b1..afa757511d9 100644 --- a/go.sum +++ b/go.sum @@ -25,8 +25,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/v2 v2.2.0 h1:VsQosGhuO+H9wh5laiIiAe4TVd73kQ5NWwmNrdm0HRA= github.com/compose-spec/compose-go/v2 v2.2.0/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= -github.com/containerd/accelerated-container-image v1.2.1 h1:ODV7nD5o5VmHIZT1OzadRQxOBLnQWnvSEouG6hFh6hA= -github.com/containerd/accelerated-container-image v1.2.1/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= +github.com/containerd/accelerated-container-image v1.2.2 h1:GzBaFYyA3JFJGor9de1tX2aLSIG1vIewdNzJrcP3dco= +github.com/containerd/accelerated-container-image v1.2.2/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= From 5864ea387ee498eb858ac921f9f3adf953c86436 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 22:46:08 +0000 Subject: [PATCH 0755/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.3.1 to 0.3.2. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Changelog](https://github.com/cyphar/filepath-securejoin/blob/main/CHANGELOG.md) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.3.1...v0.3.2) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 08629f9b9be..e0532e31430 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.8.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.3.1 + github.com/cyphar/filepath-securejoin v0.3.2 github.com/distribution/reference v0.6.0 github.com/docker/cli v27.2.1+incompatible github.com/docker/docker v27.2.1+incompatible diff --git a/go.sum b/go.sum index 7e0f7f384b1..24f70a51321 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.3.1 h1:1V7cHiaW+C+39wEfpH6XlLBQo3j/PciWFrgfCLS8XrE= -github.com/cyphar/filepath-securejoin v0.3.1/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= +github.com/cyphar/filepath-securejoin v0.3.2 h1:QhZu5AxQ+o1XZH0Ye05YzvJ0kAdK6VQc0z9NNMek7gc= +github.com/cyphar/filepath-securejoin v0.3.2/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= From b2174cbb642ef862227fd95aad77807866e55f9b Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 4 Sep 2024 16:06:47 -0700 Subject: [PATCH 0756/1066] Fix test to workaround docker credstore symlink fault As described in https://github.com/containerd/nerdctl/issues/3413 there seems to be a fault in docker credentials store that makes relative symlinks resolve to pwd instead of where they are. This in turn will break our test if the current working directory is read-only (typical with Lima). This changeset does Chdir to the parent temp directory so we can workaround that problem. Signed-off-by: apostasie --- .../credentialsstore_test.go | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go b/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go index 38bf4a29e35..6e83bc30584 100644 --- a/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go +++ b/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go @@ -168,27 +168,41 @@ func TestBrokenCredentialsStore(t *testing.T) { }, } - t.Run("Broken Docker Config testing", func(t *testing.T) { + t.Run("Docker Config testing with a variety of filesystem situations", func(t *testing.T) { + // Do NOT parallelize this test, as it relies on Chdir, which would have side effects for other tests. registryURL, err := Parse("registry") if err != nil { t.Fatal(err) } - for _, tc := range testCases { - t.Run(tc.description, func(t *testing.T) { + for _, testCase := range testCases { + tc := testCase + t.Run(tc.description, func(tt *testing.T) { + // See https://github.com/containerd/nerdctl/issues/3413 + var oldpwd string directory := tc.setup() - cs, err := NewCredentialsStore(directory) - assert.ErrorIs(t, err, tc.errorNew) + oldpwd, err = os.Getwd() + assert.NilError(tt, err) + // Ignore the error, as the destination may not be a directory + _ = os.Chdir(directory) + tt.Cleanup(func() { + err = os.Chdir(oldpwd) + assert.NilError(tt, err) + }) + + var cs *CredentialsStore + cs, err = NewCredentialsStore(directory) + assert.ErrorIs(tt, err, tc.errorNew) if err != nil { return } var af *Credentials af, err = cs.Retrieve(registryURL, true) - assert.ErrorIs(t, err, tc.errorRead) + assert.ErrorIs(tt, err, tc.errorRead) err = cs.Store(registryURL, af) - assert.ErrorIs(t, err, tc.errorWrite) + assert.ErrorIs(tt, err, tc.errorWrite) }) } }) From bc2a0070c5bff5133d41825087e285f47d3a791e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 22:19:37 +0000 Subject: [PATCH 0757/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.2.1+incompatible to 27.3.0+incompatible - [Commits](https://github.com/docker/cli/compare/v27.2.1...v27.3.0) Updates `github.com/docker/docker` from 27.2.1+incompatible to 27.3.0+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.2.1...v27.3.0) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index f38c16e7772..ed10f8a6da3 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.2 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.2.1+incompatible - github.com/docker/docker v27.2.1+incompatible + github.com/docker/cli v27.3.0+incompatible + github.com/docker/docker v27.3.0+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 1a19f7fefeb..12aff1e30ae 100644 --- a/go.sum +++ b/go.sum @@ -88,10 +88,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.2.1+incompatible h1:U5BPtiD0viUzjGAjV1p0MGB8eVA3L3cbIrnyWmSJI70= -github.com/docker/cli v27.2.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.2.1+incompatible h1:fQdiLfW7VLscyoeYEBz7/J8soYFDZV1u6VW6gJEjNMI= -github.com/docker/docker v27.2.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.3.0+incompatible h1:h7J5eiGdUbH2Q4EcGr1mFb20qzS7Nrot3EI9hwycpK0= +github.com/docker/cli v27.3.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.3.0+incompatible h1:BNb1QY6o4JdKpqwi9IB+HUYcRRrVN4aGFUTvDmWYK1A= +github.com/docker/docker v27.3.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 06a257ef2dcae106661911ba0bc265b1399dd310 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 18 Sep 2024 09:41:37 -0700 Subject: [PATCH 0758/1066] Fix panic 'provided file is not a console' As outlined in https://github.com/containerd/nerdctl/issues/3433, containerd/console will panic on a call to console.Current(). This patch provides a simple consoleutil wrapper that will return an error instead. Note that part of https://github.com/containerd/nerdctl/pull/3300 is being reverted, as no longer necessary. This patch does not try to be "smart" and does not check the status of stdin/out/err otherwise or if it is consistent with user provided flags, but merely ensures we do not crash. Signed-off-by: apostasie --- cmd/nerdctl/container/container_exec.go | 10 +--------- cmd/nerdctl/container/container_run.go | 5 ++++- pkg/cmd/container/attach.go | 5 ++++- pkg/cmd/container/exec.go | 11 +++++++++-- pkg/consoleutil/consoleutil.go | 14 ++++++++++++++ pkg/containerutil/containerutil.go | 5 ++++- 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/cmd/nerdctl/container/container_exec.go b/cmd/nerdctl/container/container_exec.go index 4dd596ce54c..fc6f0c0c6ac 100644 --- a/cmd/nerdctl/container/container_exec.go +++ b/cmd/nerdctl/container/container_exec.go @@ -18,9 +18,7 @@ package container import ( "errors" - "os" - "github.com/moby/term" "github.com/spf13/cobra" containerd "github.com/containerd/containerd/v2/client" @@ -58,6 +56,7 @@ func NewExecCommand() *cobra.Command { } func processExecCommandOptions(cmd *cobra.Command) (types.ContainerExecOptions, error) { + // We do not check if we have a terminal here, as container.Exec calling console.Current will ensure that globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { return types.ContainerExecOptions{}, err @@ -88,13 +87,6 @@ func processExecCommandOptions(cmd *cobra.Command) (types.ContainerExecOptions, } } - _, isTerminal := term.GetFdInfo(os.Stdin) - if !flagD { - if flagT && flagI && !isTerminal { - return types.ContainerExecOptions{}, errors.New("the input device is not a TTY") - } - } - workdir, err := cmd.Flags().GetString("workdir") if err != nil { return types.ContainerExecOptions{}, err diff --git a/cmd/nerdctl/container/container_run.go b/cmd/nerdctl/container/container_run.go index 143cd16d99f..a514d3795af 100644 --- a/cmd/nerdctl/container/container_run.go +++ b/cmd/nerdctl/container/container_run.go @@ -389,7 +389,10 @@ func runAction(cmd *cobra.Command, args []string) error { var con console.Console if createOpt.TTY && !createOpt.Detach { - con = console.Current() + con, err = consoleutil.Current() + if err != nil { + return err + } defer con.Reset() if err := con.SetRaw(); err != nil { return err diff --git a/pkg/cmd/container/attach.go b/pkg/cmd/container/attach.go index eb74252cf1d..fbbddafcb40 100644 --- a/pkg/cmd/container/attach.go +++ b/pkg/cmd/container/attach.go @@ -66,7 +66,10 @@ func Attach(ctx context.Context, client *containerd.Client, req string, options con console.Console ) if spec.Process.Terminal { - con = console.Current() + con, err = consoleutil.Current() + if err != nil { + return err + } defer con.Reset() if err := con.SetRaw(); err != nil { return fmt.Errorf("failed to set the console to raw mode: %w", err) diff --git a/pkg/cmd/container/exec.go b/pkg/cmd/container/exec.go index a7ad6857c33..c00c776998b 100644 --- a/pkg/cmd/container/exec.go +++ b/pkg/cmd/container/exec.go @@ -106,7 +106,10 @@ func execActionWithContainer(ctx context.Context, client *containerd.Client, con var con console.Console if options.TTY { - con = console.Current() + con, err = consoleutil.Current() + if err != nil { + return err + } defer con.Reset() if err := con.SetRaw(); err != nil { return err @@ -164,7 +167,11 @@ func generateExecProcessSpec(ctx context.Context, client *containerd.Client, con pspec := spec.Process pspec.Terminal = options.TTY if pspec.Terminal { - if size, err := console.Current().Size(); err == nil { + con, err := consoleutil.Current() + if err != nil { + return nil, err + } + if size, err := con.Size(); err == nil { pspec.ConsoleSize = &specs.Box{Height: uint(size.Height), Width: uint(size.Width)} } } diff --git a/pkg/consoleutil/consoleutil.go b/pkg/consoleutil/consoleutil.go index 4f9167a0b4c..a19988a6895 100644 --- a/pkg/consoleutil/consoleutil.go +++ b/pkg/consoleutil/consoleutil.go @@ -18,8 +18,22 @@ package consoleutil import ( "context" + "os" + + "github.com/containerd/console" ) +// Current is from https://github.com/containerd/console/blob/v1.0.4/console.go#L68-L81 +// adapted so that it does not panic +func Current() (c console.Console, err error) { + for _, s := range []*os.File{os.Stderr, os.Stdout, os.Stdin} { + if c, err = console.ConsoleFromFile(s); err == nil { + return c, nil + } + } + return nil, console.ErrNotAConsole +} + // resizer is from https://github.com/containerd/containerd/blob/v1.7.0-rc.2/cmd/ctr/commands/tasks/tasks.go#L25-L27 type resizer interface { Resize(ctx context.Context, w, h uint32) error diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 3e1af0cb9e6..814156117fc 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -244,7 +244,10 @@ func Start(ctx context.Context, container containerd.Container, flagA bool, clie flagT := process.Process.Terminal var con console.Console if flagA && flagT { - con = console.Current() + con, err = consoleutil.Current() + if err != nil { + return err + } defer con.Reset() if err := con.SetRaw(); err != nil { return err From de9a0045943e3f9a108a2d5d8e411a5bb830bbb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 22:50:53 +0000 Subject: [PATCH 0759/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.3.0+incompatible to 27.3.1+incompatible - [Commits](https://github.com/docker/cli/compare/v27.3.0...v27.3.1) Updates `github.com/docker/docker` from 27.3.0+incompatible to 27.3.1+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.3.0...v27.3.1) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ed10f8a6da3..f750c1d63df 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.2 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.3.0+incompatible - github.com/docker/docker v27.3.0+incompatible + github.com/docker/cli v27.3.1+incompatible + github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 12aff1e30ae..45c512ab10a 100644 --- a/go.sum +++ b/go.sum @@ -88,10 +88,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.3.0+incompatible h1:h7J5eiGdUbH2Q4EcGr1mFb20qzS7Nrot3EI9hwycpK0= -github.com/docker/cli v27.3.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.3.0+incompatible h1:BNb1QY6o4JdKpqwi9IB+HUYcRRrVN4aGFUTvDmWYK1A= -github.com/docker/docker v27.3.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= +github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 062f4ff865c7d7f42f7354d3c03424cf0b50722c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 22:51:01 +0000 Subject: [PATCH 0760/1066] build(deps): bump github.com/go-viper/mapstructure/v2 Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/go-viper/mapstructure/releases) - [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md) - [Commits](https://github.com/go-viper/mapstructure/compare/v2.1.0...v2.2.0) --- updated-dependencies: - dependency-name: github.com/go-viper/mapstructure/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ed10f8a6da3..18aa7d59676 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( github.com/fatih/color v1.17.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/fsnotify/fsnotify v1.7.0 - github.com/go-viper/mapstructure/v2 v2.1.0 + github.com/go-viper/mapstructure/v2 v2.2.0 github.com/ipfs/go-cid v0.4.1 github.com/klauspost/compress v1.17.9 github.com/mattn/go-isatty v0.0.20 diff --git a/go.sum b/go.sum index 12aff1e30ae..3e55a1f78c6 100644 --- a/go.sum +++ b/go.sum @@ -123,8 +123,8 @@ github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7 github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= -github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.2.0 h1:zGE1Kaz78LVwzU0kOfZuqwKKiG1gLkHTZ/cZioHp9po= +github.com/go-viper/mapstructure/v2 v2.2.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= From 2d2979242d250e21f567eac2c4d9ad125ad5c900 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 20 Sep 2024 17:15:29 -0700 Subject: [PATCH 0761/1066] Prevent concurrency on commit and remove Some container operations require exclusive access to the container, and/or have no elegant way to deal with concurrent container removal. See for example: https://github.com/containerd/nerdctl/issues/1391 This PR adds a locking method that containers can use, backed by a store instance inside the container statedir, and enforces exclusive locking for `Commit` and `Remove`. There may be other container operations where we would like to apply the lock as well (to be evaluated). Finally note that this locking mechanism is to prevent another instance of nerdctl from executing concurrently, and does not offer guarantees that the container will not be manipulated by a different cli or otherwise change state on its own. Signed-off-by: apostasie --- ...linux_test.go => container_remove_test.go} | 6 ++- .../container_remove_windows_test.go | 15 ------ pkg/cmd/container/remove.go | 34 +++++++----- pkg/containerutil/lock.go | 52 +++++++++++++++++++ pkg/imgutil/commit/commit.go | 7 +++ 5 files changed, 84 insertions(+), 30 deletions(-) rename cmd/nerdctl/container/{container_remove_linux_test.go => container_remove_test.go} (85%) create mode 100644 pkg/containerutil/lock.go diff --git a/cmd/nerdctl/container/container_remove_linux_test.go b/cmd/nerdctl/container/container_remove_test.go similarity index 85% rename from cmd/nerdctl/container/container_remove_linux_test.go rename to cmd/nerdctl/container/container_remove_test.go index 6a304b80ebf..3f9eecfd679 100644 --- a/cmd/nerdctl/container/container_remove_linux_test.go +++ b/cmd/nerdctl/container/container_remove_test.go @@ -24,16 +24,18 @@ import ( func TestRemoveContainer(t *testing.T) { t.Parallel() + base := testutil.NewBase(t) tID := testutil.Identifier(t) // ignore error base.Cmd("rm", tID, "-f").AssertOK() - base.Cmd("run", "-d", "--name", tID, testutil.CommonImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", tID, testutil.NginxAlpineImage).AssertOK() defer base.Cmd("rm", tID, "-f").AssertOK() base.Cmd("rm", tID).AssertFail() - base.Cmd("kill", tID).AssertOK() + // `kill` does return before the container actually stops + base.Cmd("stop", tID).AssertOK() base.Cmd("rm", tID).AssertOK() } diff --git a/cmd/nerdctl/container/container_remove_windows_test.go b/cmd/nerdctl/container/container_remove_windows_test.go index f3b1a73f640..c6733ca1e9b 100644 --- a/cmd/nerdctl/container/container_remove_windows_test.go +++ b/cmd/nerdctl/container/container_remove_windows_test.go @@ -24,21 +24,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil" ) -func TestRemoveProcessContainer(t *testing.T) { - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - - // ignore error - base.Cmd("rm", tID, "-f").AssertOK() - - base.Cmd("run", "-d", "--name", tID, testutil.NginxAlpineImage).AssertOK() - defer base.Cmd("rm", tID, "-f").AssertOK() - base.Cmd("rm", tID).AssertFail() - - base.Cmd("kill", tID).AssertOK() - base.Cmd("rm", tID).AssertOK() -} - func TestRemoveHyperVContainer(t *testing.T) { base := testutil.NewBase(t) tID := testutil.Identifier(t) diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 0445953be73..5acc7465c5a 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -101,11 +101,30 @@ func Remove(ctx context.Context, client *containerd.Client, containers []string, // - then and ONLY then, on a successful container remove, clean things-up on our side (volume store, etcetera) // If you do need to add more cleanup, please do so at the bottom of the defer function func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions types.GlobalCommandOptions, force bool, removeAnonVolumes bool, client *containerd.Client) (retErr error) { - // defer the storage of remove error in the dedicated label + // Get labels + containerLabels, err := c.Labels(ctx) + if err != nil { + return err + } + + // Lock the container state + lf, err := containerutil.Lock(ctx, c) + if err != nil { + return err + } + defer func() { + // If there was an error, update the label + // Note that we will (obviously) not store any unlocking or statedir removal error from below if retErr != nil { containerutil.UpdateErrorLabel(ctx, c, retErr) } + // Release the lock + retErr = errors.Join(lf.Release(), retErr) + // Note: technically, this is racy... + if retErr == nil { + retErr = os.RemoveAll(containerLabels[labels.StateDir]) + } }() // Get namespace @@ -113,11 +132,6 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions if err != nil { return err } - // Get labels - containerLabels, err := c.Labels(ctx) - if err != nil { - return err - } // Get datastore dataStore, err := clientutil.DataStore(globalOptions.DataRoot, globalOptions.Address) if err != nil { @@ -139,9 +153,8 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions return err } - // Get the container id, stateDir and name + // Get the container id and name id := c.ID() - stateDir := containerLabels[labels.StateDir] name := containerLabels[labels.Name] // This will evaluate retErr to decide if we proceed with removal or not @@ -198,11 +211,6 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions log.G(ctx).WithError(err).Warnf("failed to cleanup IPC for container %q", id) } - // Remove state dir - soft failure - if err = os.RemoveAll(stateDir); err != nil { - log.G(ctx).WithError(err).Warnf("failed to remove container state dir %s", stateDir) - } - // Enforce release name here in case the poststop hook name release fails - soft failure if name != "" { // Double-releasing may happen with containers started with --rm, so, ignore NotFound errors diff --git a/pkg/containerutil/lock.go b/pkg/containerutil/lock.go new file mode 100644 index 00000000000..896f6f1f618 --- /dev/null +++ b/pkg/containerutil/lock.go @@ -0,0 +1,52 @@ +/* + 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 containerutil + +import ( + "context" + "errors" + "path/filepath" + + "github.com/containerd/containerd/v2/client" + + "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/store" +) + +func Lock(ctx context.Context, c client.Container) (store.Store, error) { + containerLabels, err := c.Labels(ctx) + if err != nil { + return nil, err + } + + stateDir := containerLabels[labels.StateDir] + if stateDir == "" { + return nil, errors.New("container is missing statedir label") + } + + stor, err := store.New(filepath.Join(stateDir, "oplock"), 0, 0) + if err != nil { + return nil, err + } + + err = stor.Lock() + if err != nil { + return nil, err + } + + return stor, nil +} diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index 44e582052cb..b504035dd22 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -44,6 +44,7 @@ import ( "github.com/containerd/log" "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/containerutil" imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" ) @@ -66,6 +67,12 @@ var ( ) func Commit(ctx context.Context, client *containerd.Client, container containerd.Container, opts *Opts) (digest.Digest, error) { + lf, err := containerutil.Lock(ctx, container) + if err != nil { + return emptyDigest, err + } + defer lf.Release() + id := container.ID() info, err := container.Info(ctx) if err != nil { From bfc2da4038c1bbff7a6f78ceca700c211141e0ba Mon Sep 17 00:00:00 2001 From: Jin Dong Date: Sat, 21 Sep 2024 12:45:42 -0400 Subject: [PATCH 0762/1066] increase golangci-lint timeout to 10min Signed-off-by: Jin Dong --- .golangci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.golangci.yml b/.golangci.yml index 21e02d8c0df..f7dbbab93e0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,6 +1,7 @@ --- run: concurrency: 6 + timeout: 5m linters: disable-all: true enable: From 2c95d090237c534b9ddec59b6488386445c41da6 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 17 Sep 2024 20:39:56 -0700 Subject: [PATCH 0763/1066] Adding NG test tooling Our testing tools have served us well, and there are plenty of good things with them that we absolutely need to keep. We have grown a large test suite though, and the sheer size of it is putting pressure on it and it is starting to show cracks. Besides bugs per-se (double execution) - that we hopefully fixed - our design is reaching its limits. We do have rather impactful issues with regard to test isolation and test concurrency, leading to situations where it is hard or outright impossible to figure out which test is causing a cascading failure, or why the adding of a new test file working individually breaks everything. Furthermore, as we are not prescriptive on certain things, we do see a lot of negative patterns emerging from test authors: - defer being used instead of t.Cleanup - not calling cleanup routines before running tests - outright forgetting to cleanup resources - Cwd for binary calls is by default the current working directory of the test process - this is causing a variety of issues, as it could very well be read-only (lima), and should by default be a temp directory - manipulating the environment directly - which has side-effects for other tests - tests becoming big blurbs of mixed together setup, cleanup, and actual test routines - making them hard to read and figuring out what is actually being tested - subtests repetitiveness w. shadowing testutil.T leading to confusing code - ... or not dereferencing the current test in a loop - in-test homegrown abstractions being inherently repetitive, with the same boilerplate over and over again - structuring tests and subtests being left as an exercise to the developer - leading to a wide variety of approaches and complex boilerplate - hard to debug: a lot of the assert methods do not provide any feedback whatsoever on what was the command that actually failed, or what was the output, or environment of it - icmd.Expected showing its limits, and making assumptions that there is only one error you can test, or that you can only test the output if exitCode == 0 - running commands with other binaries than the current target (eg: not calling base.Cmd) being left as an exercise to the developer, leading to all of the issues above (Chdir, Env manipulation, no debugging output, etc) - no-parallel being the default - unless specified otherwise - which should be the other way around - very rarely testing stderr in case of error - partly because we do not use typed errors, but also because it is cumbersome / not obvious / limited This new tooling offers a set of abstractions that should address all of these and encourage more expressive, better structured, better isolated, more debuggable tests. Signed-off-by: apostasie --- pkg/testutil/nerdtest/test.go | 253 +++++++++++++++++++++++++++++++ pkg/testutil/test/case.go | 175 +++++++++++++++++++++ pkg/testutil/test/command.go | 191 +++++++++++++++++++++++ pkg/testutil/test/data.go | 147 ++++++++++++++++++ pkg/testutil/test/expected.go | 90 +++++++++++ pkg/testutil/test/helpers.go | 71 +++++++++ pkg/testutil/test/requirement.go | 115 ++++++++++++++ pkg/testutil/test/test.go | 119 +++++++++++++++ 8 files changed, 1161 insertions(+) create mode 100644 pkg/testutil/nerdtest/test.go create mode 100644 pkg/testutil/test/case.go create mode 100644 pkg/testutil/test/command.go create mode 100644 pkg/testutil/test/data.go create mode 100644 pkg/testutil/test/expected.go create mode 100644 pkg/testutil/test/helpers.go create mode 100644 pkg/testutil/test/requirement.go create mode 100644 pkg/testutil/test/test.go diff --git a/pkg/testutil/nerdtest/test.go b/pkg/testutil/nerdtest/test.go new file mode 100644 index 00000000000..a2f7a5bd3c2 --- /dev/null +++ b/pkg/testutil/nerdtest/test.go @@ -0,0 +1,253 @@ +/* + 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 nerdtest + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func Setup() { + test.CustomCommand(nerdctlSetup) +} + +// Nerdctl specific config key and values +var NerdctlToml test.ConfigKey = "NerdctlToml" +var HostsDir test.ConfigKey = "HostsDir" +var DataRoot test.ConfigKey = "DataRoot" +var Namespace test.ConfigKey = "Namespace" + +var Mode test.ConfigKey = "Mode" +var ModePrivate test.ConfigValue = "Private" +var IPv6 test.ConfigKey = "IPv6Test" +var Only test.ConfigValue = "Only" + +var OnlyIPv6 = test.MakeRequirement(func(data test.Data) (ret bool, mess string) { + ret = testutil.GetEnableIPv6() + if !ret { + mess = "runner skips IPv6 compatible tests in the non-IPv6 environment" + } + data.WithConfig(IPv6, Only) + return ret, mess +}) + +var Private = test.MakeRequirement(func(data test.Data) (ret bool, mess string) { + data.WithConfig(Mode, ModePrivate) + return true, "" +}) + +var Docker = test.MakeRequirement(func(data test.Data) (ret bool, mess string) { + ret = testutil.GetTarget() == testutil.Docker + if ret { + mess = "current target is docker" + } else { + mess = "current target is not docker" + } + return ret, mess +}) + +var Rootless = test.MakeRequirement(func(data test.Data) (ret bool, mess string) { + ret = rootlessutil.IsRootless() + if ret { + mess = "environment is rootless" + } else { + mess = "environment is rootful" + } + return ret, mess +}) + +var Build = test.MakeRequirement(func(data test.Data) (ret bool, mess string) { + // FIXME: shouldn't we run buildkitd in a container? At least for testing, that would be so much easier than + // against the host install + ret = true + mess = "" + if testutil.GetTarget() == testutil.Nerdctl { + _, err := buildkitutil.GetBuildkitHost(testutil.Namespace) + if err != nil { + ret = false + mess = fmt.Sprintf("test requires buildkitd: %+v", err) + } + } + return ret, mess +}) + +type NerdCommand struct { + test.GenericCommand + // FIXME: annoying - forces custom Clone, etc + Target string +} + +// Run does override the generic command run, as we are testing both docker and nerdctl +func (nc *NerdCommand) Run(expect *test.Expected) { + // We are not in the business of testing docker error output, so, spay expect for errors testing, if any + if expect != nil && nc.Target != testutil.Nerdctl { + expect.Errors = nil + } + + nc.GenericCommand.Run(expect) +} + +// Clone is overridden as well, as we need to pass along the target +func (nc *NerdCommand) Clone() test.Command { + return &NerdCommand{ + GenericCommand: *((nc.GenericCommand.Clone()).(*test.GenericCommand)), + Target: nc.Target, + } +} + +// InspectContainer is a helper that can be used inside custom commands or Setup +func InspectContainer(helpers test.Helpers, name string) dockercompat.Container { + var dc []dockercompat.Container + cmd := helpers.Command("container", "inspect", name) + cmd.Run(&test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + }, + }) + return dc[0] +} + +func InspectVolume(helpers test.Helpers, name string, args ...string) native.Volume { + var dc []native.Volume + cmdArgs := append([]string{"volume", "inspect"}, args...) + cmdArgs = append(cmdArgs, name) + + cmd := helpers.Command(cmdArgs...) + cmd.Run(&test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + }, + }) + return dc[0] +} + +func InspectNetwork(helpers test.Helpers, name string, args ...string) dockercompat.Network { + var dc []dockercompat.Network + cmdArgs := append([]string{"network", "inspect"}, args...) + cmdArgs = append(cmdArgs, name) + + cmd := helpers.Command(cmdArgs...) + cmd.Run(&test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + }, + }) + return dc[0] +} + +func nerdctlSetup(testCase *test.Case, t *testing.T) test.Command { + t.Helper() + + var testUtilBase *testutil.Base + dt := testCase.Data + var pvNamespace string + inherited := false + + if dt.ReadConfig(IPv6) != Only && testutil.GetEnableIPv6() { + t.Skip("runner skips non-IPv6 compatible tests in the IPv6 environment") + } + + if dt.ReadConfig(Mode) == ModePrivate { + // If private was inherited, we already got a configured namespace + if dt.ReadConfig(Namespace) != "" { + pvNamespace = string(dt.ReadConfig(Namespace)) + inherited = true + } else { + // Otherwise, we need to set everything up + pvNamespace = testCase.Data.Identifier() + dt.WithConfig(Namespace, test.ConfigValue(pvNamespace)) + testCase.Env["DOCKER_CONFIG"] = testCase.Data.TempDir() + testCase.Env["NERDCTL_TOML"] = filepath.Join(testCase.Data.TempDir(), "nerdctl.toml") + dt.WithConfig(HostsDir, test.ConfigValue(testCase.Data.TempDir())) + dt.WithConfig(DataRoot, test.ConfigValue(testCase.Data.TempDir())) + } + testUtilBase = testutil.NewBaseWithNamespace(t, pvNamespace) + if testUtilBase.Target == testutil.Docker { + // For docker, just disable parallel + testCase.NoParallel = true + } + } else if dt.ReadConfig(Namespace) != "" { + pvNamespace = string(dt.ReadConfig(Namespace)) + testUtilBase = testutil.NewBaseWithNamespace(t, pvNamespace) + } else { + testUtilBase = testutil.NewBase(t) + } + + // If we were passed custom content for NerdctlToml, save it + // Not happening if this is not nerdctl of course + if testUtilBase.Target == testutil.Nerdctl && dt.ReadConfig(NerdctlToml) != "" { + dest := filepath.Join(testCase.Data.TempDir(), "nerdctl.toml") + testCase.Env["NERDCTL_TOML"] = dest + err := os.WriteFile(dest, []byte(dt.ReadConfig(NerdctlToml)), 0400) + assert.NilError(t, err, "failed to write custom nerdctl toml file for test") + } + + // Build the base + baseCommand := &NerdCommand{} + baseCommand.WithBinary(testUtilBase.Binary) + baseCommand.WithArgs(testUtilBase.Args...) + baseCommand.WithEnv(testCase.Env) + baseCommand.WithT(t) + baseCommand.WithTempDir(testCase.Data.TempDir()) + baseCommand.Target = testUtilBase.Target + + if testUtilBase.Target == testutil.Nerdctl { + if dt.ReadConfig(HostsDir) != "" { + baseCommand.GenericCommand.WithArgs("--hosts-dir=" + string(dt.ReadConfig(HostsDir))) + } + + if dt.ReadConfig(DataRoot) != "" { + baseCommand.GenericCommand.WithArgs("--data-root=" + string(dt.ReadConfig(DataRoot))) + } + } + + // If we were in a custom namespace, not inherited - make sure we clean up the namespace + // FIXME: this is broken, and custom namespaces are not cleaned properly + if testUtilBase.Target == testutil.Nerdctl && pvNamespace != "" && !inherited { + cleanup := func() { + cl := baseCommand.Clone() + cl.WithArgs("namespace", "remove", pvNamespace) + cl.Run(nil) + } + cleanup() + t.Cleanup(cleanup) + } + + // Attach the base command + return baseCommand +} diff --git a/pkg/testutil/test/case.go b/pkg/testutil/test/case.go new file mode 100644 index 00000000000..eed35a929f6 --- /dev/null +++ b/pkg/testutil/test/case.go @@ -0,0 +1,175 @@ +/* + 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 test + +import ( + "testing" + + "gotest.tools/v3/assert" +) + +// Group informally describes a slice of tests +type Group []*Case + +func (tg *Group) Run(t *testing.T) { + t.Helper() + // If the group contains only one test, no need to create a subtest + sub := len(*tg) > 1 + if sub { + t.Parallel() + } + // Run each subtest + for _, tc := range *tg { + tc.subIt = sub + tc.Run(t) + } +} + +// Case describes an entire test-case, including data, setup and cleanup routines, command and expectations +type Case struct { + // Description contains a human-readable short desc, used as a seed for the identifier and as a title for the test + Description string + // NoParallel disables parallel execution if set to true + NoParallel bool + // Env contains a map of environment variables to use for commands run in Setup, Command and Cleanup + // Note that the environment is inherited by subtests + Env map[string]string + // Data contains test specific data, accessible to all operations, also inherited by subtests + Data Data + + // Setup + Setup Butler + // Expected + Expected Manager + // Command + Command Executor + // Cleanup + Cleanup Butler + // Requirement + Require Requirement + + // SubTests + SubTests []*Case + + // Private + helpers Helpers + t *testing.T + parent *Case + baseCommand Command + + subIt bool +} + +// Run prepares and executes the test, and any possible subtests +func (test *Case) Run(t *testing.T) { + t.Helper() + // Run the test + testRun := func(tt *testing.T) { + tt.Helper() + test.seal(tt) + + if registeredInit == nil { + bc := &GenericCommand{} + bc.WithEnv(test.Env) + bc.WithT(tt) + bc.WithTempDir(test.Data.TempDir()) + test.baseCommand = bc + } else { + test.baseCommand = registeredInit(test, test.t) + } + + test.exec(tt) + } + + if test.subIt { + t.Run(test.Description, testRun) + } else { + testRun(t) + } +} + +// seal is a private method to prepare the test +func (test *Case) seal(t *testing.T) { + t.Helper() + assert.Assert(t, test.t == nil, "You cannot run a test multiple times") + assert.Assert(t, test.Description != "", "A test description cannot be empty") + assert.Assert(t, test.Command == nil || test.Expected != nil, + "Expectations for a test command cannot be nil. You may want to use Setup instead.") + + // Ensure we have env + if test.Env == nil { + test.Env = map[string]string{} + } + + // If we have a parent, get parent env and data + var parentData Data + if test.parent != nil { + parentData = test.parent.Data + for k, v := range test.parent.Env { + if _, ok := test.Env[k]; !ok { + test.Env[k] = v + } + } + } + + // Attach testing.T + test.t = t + // Inherit and attach Data + test.Data = configureData(t, test.Data, parentData) + + // Check the requirements + if test.Require != nil { + test.Require(test.Data, t) + } +} + +// exec is a private method that will take care of the test setup, command and cleanup execution +func (test *Case) exec(t *testing.T) { + t.Helper() + test.helpers = &helpers{ + test.baseCommand, + } + + // Set parallel unless asked not to + if !test.NoParallel { + t.Parallel() + } + + // Register cleanup if there is any, and run it to collect any leftovers from previous runs + if test.Cleanup != nil { + test.Cleanup(test.Data, test.helpers) + t.Cleanup(func() { + test.Cleanup(test.Data, test.helpers) + }) + } + + // Run setup + if test.Setup != nil { + test.Setup(test.Data, test.helpers) + } + + // Run the command if any, with expectations + if test.Command != nil { + test.Command(test.Data, test.helpers).Run(test.Expected(test.Data, test.helpers)) + } + + for _, subTest := range test.SubTests { + subTest.parent = test + subTest.subIt = true + subTest.Run(t) + } +} diff --git a/pkg/testutil/test/command.go b/pkg/testutil/test/command.go new file mode 100644 index 00000000000..6fbb1779d52 --- /dev/null +++ b/pkg/testutil/test/command.go @@ -0,0 +1,191 @@ +/* + 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 test + +import ( + "fmt" + "io" + "os" + "strings" + "testing" + "time" + + "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" +) + +// GenericCommand is a concrete Command implementation +type GenericCommand struct { + WorkingDir string + Env map[string]string + + t *testing.T + tempDir string + helperBinary string + helperArgs []string + mainBinary string + mainArgs []string + result *icmd.Result + stdin io.Reader + async bool + timeout time.Duration +} + +func (gc *GenericCommand) WithBinary(binary string) Command { + gc.mainBinary = binary + return gc +} + +func (gc *GenericCommand) WithArgs(args ...string) Command { + gc.mainArgs = append(gc.mainArgs, args...) + return gc +} + +// WithEnv will overload the command env with values from the passed map +func (gc *GenericCommand) WithEnv(env map[string]string) Command { + if gc.Env == nil { + gc.Env = map[string]string{} + } + for k, v := range env { + gc.Env[k] = v + } + return gc +} + +func (gc *GenericCommand) WithWrapper(binary string, args ...string) Command { + gc.helperBinary = binary + gc.helperArgs = args + return gc +} + +// WithStdin sets the standard input of Cmd to the specified reader +func (gc *GenericCommand) WithStdin(r io.Reader) Command { + gc.stdin = r + return gc +} + +func (gc *GenericCommand) Background(timeout time.Duration) Command { + // Run it + gc.async = true + i := gc.boot() + gc.result = icmd.StartCmd(i) + gc.timeout = timeout + return gc +} + +// TODO: it should be possible to: +// - timeout execution +func (gc *GenericCommand) Run(expect *Expected) { + var result *icmd.Result + var env []string + if gc.async { + result = icmd.WaitOnCmd(gc.timeout, gc.result) + env = gc.result.Cmd.Env + } else { + icmdCmd := gc.boot() + env = icmdCmd.Env + // Run it + result = icmd.RunCmd(icmdCmd) + } + + // Check our expectations, if any + if expect != nil { + // Build the debug string - additionally attach the env (which icmd does not do) + debug := result.String() + "Env:\n" + strings.Join(env, "\n") + // ExitCode goes first + if expect.ExitCode == -1 { + assert.Assert(gc.t, result.ExitCode != 0, + "Expected exit code to be different than 0"+debug) + } else { + assert.Assert(gc.t, expect.ExitCode == result.ExitCode, + fmt.Sprintf("Expected exit code: %d", expect.ExitCode)+debug) + } + // Range through the expected errors and confirm they are seen on stderr + for _, expectErr := range expect.Errors { + assert.Assert(gc.t, strings.Contains(result.Stderr(), expectErr.Error()), + fmt.Sprintf("Expected error: %q to be found in stderr", expectErr.Error())+debug) + } + // Finally, check the output if we are asked to + if expect.Output != nil { + expect.Output(result.Stdout(), debug, gc.t) + } + } +} + +func (gc *GenericCommand) boot() icmd.Cmd { + // This is a helper function, not to appear in the debugging output + gc.t.Helper() + + binary := gc.mainBinary + args := gc.mainArgs + if gc.helperBinary != "" { + args = append([]string{binary}, args...) + args = append(gc.helperArgs, args...) + binary = gc.helperBinary + } + + // Create the command and set the env + // TODO: do we really need icmd? + icmdCmd := icmd.Command(binary, args...) + icmdCmd.Env = []string{} + for _, v := range os.Environ() { + // Ignore LS_COLORS from the env, just too much noise + if !strings.HasPrefix(v, "LS_COLORS") { + icmdCmd.Env = append(icmdCmd.Env, v) + } + } + + // Ensure the subprocess gets executed in a temporary directory unless explicitly instructed otherwise + icmdCmd.Dir = gc.WorkingDir + if icmdCmd.Dir == "" { + icmdCmd.Dir = gc.tempDir + } + + // Attach any extra env we have + for k, v := range gc.Env { + icmdCmd.Env = append(icmdCmd.Env, fmt.Sprintf("%s=%s", k, v)) + } + + return icmdCmd +} + +func (gc *GenericCommand) Clone() Command { + // Copy the command and return a new one - with WorkingDir, binary, args, etc + cc := *gc + // Clone Env + cc.Env = make(map[string]string, len(gc.Env)) + for k, v := range gc.Env { + cc.Env[k] = v + } + return &cc +} + +func (gc *GenericCommand) Clear() Command { + gc.mainBinary = "" + gc.helperBinary = "" + gc.mainArgs = []string{} + gc.helperArgs = []string{} + return gc +} + +func (gc *GenericCommand) WithT(t *testing.T) { + gc.t = t +} + +func (gc *GenericCommand) WithTempDir(tempDir string) { + gc.tempDir = tempDir +} diff --git a/pkg/testutil/test/data.go b/pkg/testutil/test/data.go new file mode 100644 index 00000000000..99f2aa041ad --- /dev/null +++ b/pkg/testutil/test/data.go @@ -0,0 +1,147 @@ +/* + 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 test + +import ( + "crypto/sha256" + "fmt" + "strings" + "testing" +) + +// Contains the implementation of the Data interface + +type data struct { + config map[ConfigKey]ConfigValue + + system map[SystemKey]SystemValue + + labels map[string]string + testID string + tempDir string +} + +func (dt *data) WithConfig(key ConfigKey, value ConfigValue) Data { + if dt.config == nil { + dt.config = make(map[ConfigKey]ConfigValue) + } + dt.config[key] = value + return dt +} + +func (dt *data) ReadConfig(key ConfigKey) ConfigValue { + if dt.config == nil { + dt.config = make(map[ConfigKey]ConfigValue) + } + if val, ok := dt.config[key]; ok { + return val + } + return "" +} + +func (dt *data) Get(key string) string { + if dt.labels == nil { + dt.labels = map[string]string{} + } + return dt.labels[key] +} + +func (dt *data) Set(key string, value string) Data { + if dt.labels == nil { + dt.labels = map[string]string{} + } + dt.labels[key] = value + return dt +} + +func (dt *data) Identifier() string { + return dt.testID +} + +func (dt *data) TempDir() string { + return dt.tempDir +} + +func (dt *data) adopt(parent Data) { + for k, v := range parent.getLabels() { + // Only copy keys that are not set already + if _, ok := dt.labels[k]; !ok { + dt.Set(k, v) + } + } + for k, v := range parent.getConfig() { + // Only copy keys that are not set already + if _, ok := dt.config[k]; !ok { + dt.WithConfig(k, v) + } + } +} + +func (dt *data) Sink(key SystemKey, value SystemValue) { + if _, ok := dt.system[key]; !ok { + dt.system[key] = value + } else { + // XXX should we really panic? + panic(fmt.Sprintf("Unable to set system key %s multiple times", key)) + } +} + +func (dt *data) Surface(key SystemKey) SystemValue { + if v, ok := dt.system[key]; ok { + return v + } + // XXX should we really panic? + panic(fmt.Sprintf("Unable to retrieve system key %s", key)) +} + +func (dt *data) getLabels() map[string]string { + return dt.labels +} + +func (dt *data) getConfig() map[ConfigKey]ConfigValue { + return dt.config +} + +func defaultIdentifierHashing(name string) string { + s := strings.ReplaceAll(name, " ", "_") + s = strings.ReplaceAll(s, "/", "_") + s = strings.ReplaceAll(s, "-", "_") + s = strings.ReplaceAll(s, ",", "_") + s = strings.ToLower(s) + if len(s) > 76 { + s = fmt.Sprintf("%x", sha256.Sum256([]byte(s))) + } + + return s +} + +// TODO: allow to pass custom hashing methods? +func configureData(t *testing.T, seedData Data, parent Data) Data { + if seedData == nil { + seedData = &data{} + } + dat := &data{ + config: seedData.getConfig(), + labels: seedData.getLabels(), + tempDir: t.TempDir(), + testID: defaultIdentifierHashing(t.Name()), + } + if parent != nil { + dat.adopt(parent) + } + return dat +} diff --git a/pkg/testutil/test/expected.go b/pkg/testutil/test/expected.go new file mode 100644 index 00000000000..81d617acfdf --- /dev/null +++ b/pkg/testutil/test/expected.go @@ -0,0 +1,90 @@ +/* + 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 test + +import ( + "fmt" + "strings" + "testing" + + "gotest.tools/v3/assert" +) + +func RunCommand(args ...string) Executor { + return func(data Data, helpers Helpers) Command { + return helpers.Command(args...) + } +} + +// WithData returns a data object with a certain key value set +func WithData(key string, value string) Data { + dat := &data{} + dat.Set(key, value) + return dat +} + +// WithConfig returns a data object with a certain config property set +func WithConfig(key ConfigKey, value ConfigValue) Data { + dat := &data{} + dat.WithConfig(key, value) + return dat +} + +// Expects is provided as a simple helper covering "expectations" for simple use-cases where access to the test data is not necessary +func Expects(exitCode int, errors []error, output Comparator) Manager { + return func(_ Data, _ Helpers) *Expected { + return &Expected{ + ExitCode: exitCode, + Errors: errors, + Output: output, + } + } +} + +// All can be used as a parameter for expected.Output and allow passing a collection of conditions to match +func All(comparators ...Comparator) Comparator { + return func(stdout string, info string, t *testing.T) { + t.Helper() + for _, comparator := range comparators { + comparator(stdout, info, t) + } + } +} + +// Contains can be used as a parameter for expected.Output and ensures a comparison string is found contained in the output +func Contains(compare string) Comparator { + return func(stdout string, info string, t *testing.T) { + t.Helper() + assert.Assert(t, strings.Contains(stdout, compare), fmt.Sprintf("Expected output to contain: %q", compare)+info) + } +} + +// DoesNotContain is to be used for expected.Output to ensure a comparison string is NOT found in the output +func DoesNotContain(compare string) Comparator { + return func(stdout string, info string, t *testing.T) { + t.Helper() + assert.Assert(t, !strings.Contains(stdout, compare), fmt.Sprintf("Expected output to not contain: %q", compare)+info) + } +} + +// Equals is to be used for expected.Output to ensure it is exactly the output +func Equals(compare string) Comparator { + return func(stdout string, info string, t *testing.T) { + t.Helper() + assert.Equal(t, compare, stdout, info) + } +} diff --git a/pkg/testutil/test/helpers.go b/pkg/testutil/test/helpers.go new file mode 100644 index 00000000000..64a734dd86c --- /dev/null +++ b/pkg/testutil/test/helpers.go @@ -0,0 +1,71 @@ +/* + 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 test + +import "testing" + +type Helpers interface { + Ensure(args ...string) + Anyhow(args ...string) + Fail(args ...string) + Capture(args ...string) string + + Command(args ...string) Command + CustomCommand(binary string, args ...string) Command +} + +type helpers struct { + cmd Command +} + +func (hel *helpers) Ensure(args ...string) { + hel.Command(args...).Run(&Expected{}) +} + +func (hel *helpers) Anyhow(args ...string) { + hel.Command(args...).Run(nil) +} + +func (hel *helpers) Fail(args ...string) { + hel.Command(args...).Run(&Expected{ + ExitCode: 1, + }) +} + +func (hel *helpers) Capture(args ...string) string { + var ret string + hel.Command(args...).Run(&Expected{ + Output: func(stdout string, info string, t *testing.T) { + ret = stdout + }, + }) + return ret +} + +func (hel *helpers) Command(args ...string) Command { + cc := hel.cmd.Clone() + cc.WithArgs(args...) + return cc +} + +func (hel *helpers) CustomCommand(binary string, args ...string) Command { + cc := hel.cmd.Clone() + cc.Clear() + cc.WithBinary(binary) + cc.WithArgs(args...) + return cc +} diff --git a/pkg/testutil/test/requirement.go b/pkg/testutil/test/requirement.go new file mode 100644 index 00000000000..1acad13af28 --- /dev/null +++ b/pkg/testutil/test/requirement.go @@ -0,0 +1,115 @@ +/* + 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 test + +import ( + "fmt" + "os/exec" + "runtime" + "testing" +) + +func MakeRequirement(fn func(data Data) (bool, string)) Requirement { + return func(data Data, t *testing.T) (bool, string) { + ret, mess := fn(data) + + if t != nil && !ret { + t.Helper() + t.Skipf("Test skipped as %s", mess) + } + + return ret, mess + } +} + +func Binary(name string) Requirement { + return MakeRequirement(func(data Data) (ret bool, mess string) { + mess = fmt.Sprintf("executable %q has been found in PATH", name) + ret = true + if _, err := exec.LookPath(name); err != nil { + ret = false + mess = fmt.Sprintf("executable %q doesn't exist in PATH", name) + } + + return ret, mess + }) +} + +func OS(os string) Requirement { + return MakeRequirement(func(data Data) (ret bool, mess string) { + mess = fmt.Sprintf("current operating is %q", runtime.GOOS) + ret = true + if runtime.GOOS != os { + ret = false + } + + return ret, mess + }) +} + +var Windows = MakeRequirement(func(data Data) (ret bool, mess string) { + ret = runtime.GOOS == "windows" + if ret { + mess = "operating system is Windows" + } else { + mess = "operating system is not Windows" + } + return ret, mess +}) + +var Linux = MakeRequirement(func(data Data) (ret bool, mess string) { + ret = runtime.GOOS == "linux" + if ret { + mess = "operating system is Linux" + } else { + mess = "operating system is not Linux" + } + return ret, mess +}) + +var Darwin = MakeRequirement(func(data Data) (ret bool, mess string) { + ret = runtime.GOOS == "darwin" + if ret { + mess = "operating system is Darwin" + } else { + mess = "operating system is not Darwin" + } + return ret, mess +}) + +func Not(requirement Requirement) Requirement { + return MakeRequirement(func(data Data) (ret bool, mess string) { + b, mess := requirement(data, nil) + return !b, mess + }) +} + +func Require(thing ...Requirement) Requirement { + return func(data Data, t *testing.T) (ret bool, mess string) { + for _, th := range thing { + b, m := th(data, nil) + if !b { + if t != nil { + t.Helper() + t.Skipf("Test skipped as %s", m) + } + return false, "" + } + } + return true, "" + } +} diff --git a/pkg/testutil/test/test.go b/pkg/testutil/test/test.go new file mode 100644 index 00000000000..2e6743be8e6 --- /dev/null +++ b/pkg/testutil/test/test.go @@ -0,0 +1,119 @@ +/* + 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 test + +import ( + "io" + "testing" + "time" +) + +// A Requirement is a function that can evaluate random requirement and possibly skip a test +// See test.MakeRequirement to make your own +type Requirement func(data Data, t *testing.T) (bool, string) + +// A Butler is the function signature meant to be attached to a Setup or Cleanup routine for a test.Case +type Butler func(data Data, helpers Helpers) + +// An Executor is the function signature meant to be attached to a test.Case Command +type Executor func(data Data, helpers Helpers) Command + +// A Manager is the function signature to be run to produce expectations to be fed to a command +type Manager func(data Data, helpers Helpers) *Expected + +// The Command interface represents a low-level command to execute, typically to be compared with an Expected +// A Command can be used as a Case Command obviously, but also as part of a Setup or Cleanup routine, +// and as the basis of any type of helper. +// A Command can be cloned, in which case, the subcommand inherits a copy of all of its Env and parameters. +// Typically, a Case has a base-command, from which all commands involved in the test are derived. +type Command interface { + // WithBinary specifies what binary to execute + WithBinary(binary string) Command + // WithArgs specifies the args to pass to the binary. Note that WithArgs is additive. + WithArgs(args ...string) Command + // WithEnv adds the passed map to the environment of the command to be executed + WithEnv(env map[string]string) Command + // WithWrapper allows wrapping a command with another command (for example: `time`, `unbuffer`) + WithWrapper(binary string, args ...string) Command + // WithStdin allows passing a reader to be used for stdin for the command + WithStdin(r io.Reader) Command + // Run does execute the command, and compare the output with the provided expectation. + // Passing nil for `Expected` will just run the command regardless of outcome. + // An empty `&Expected{}` is (of course) equivalent to &Expected{Exit: 0}, meaning the command is verified to be + // successful + Run(expect *Expected) + // Clone returns a copy of the command + Clone() Command + // Clear will clear binary and arguments, but retain the env, or any other custom properties + Clear() Command + // Allow starting a command in the background + Background(timeout time.Duration) Command +} + +type Comparator func(stdout string, info string, t *testing.T) + +// Expected expresses the expected output of a command +type Expected struct { + // ExitCode to expect + ExitCode int + // Errors contains any error that (once serialized) should be seen in stderr + Errors []error + // Output function to match against stdout + Output Comparator +} + +type ConfigKey string +type ConfigValue string + +type SystemKey string +type SystemValue string + +// Data is meant to hold information about a test: +// - first, any random key value data that the test implementer wants to carry / modify - this is test data +// - second, configuration specific to the binary being tested - typically defined by the specialized command being tested +// - third, immutable "system" info (unique identifier, tempdir, or other SystemKey/Value pairs) +type Data interface { + // Get returns the value of a certain key for custom data + Get(key string) string + // Set will save `value` for `key` + Set(key string, value string) Data + + // Identifier returns the test identifier that can be used to name resources + Identifier() string + // TempDir returns the test temporary directory + TempDir() string + // Sink allows to define ONCE a certain system property + Sink(key SystemKey, value SystemValue) + // Surface allows retrieving a certain system property + Surface(key SystemKey) SystemValue + + // WithConfig allows setting a declared ConfigKey to a ConfigValue + WithConfig(key ConfigKey, value ConfigValue) Data + ReadConfig(key ConfigKey) ConfigValue + + // Private methods + getLabels() map[string]string + getConfig() map[ConfigKey]ConfigValue +} + +var ( + registeredInit func(test *Case, t *testing.T) Command +) + +func CustomCommand(custom func(test *Case, t *testing.T) Command) { + registeredInit = custom +} From cc56a0931f86069e9ffbe3822730f58da1f0d758 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 17 Sep 2024 20:41:22 -0700 Subject: [PATCH 0764/1066] Move root and volume tests to new test tooling Signed-off-by: apostasie --- cmd/nerdctl/main_linux_test.go | 38 +- cmd/nerdctl/main_test.go | 149 ++-- cmd/nerdctl/main_test_test.go | 147 ++++ cmd/nerdctl/volume/volume_create_test.go | 162 ++-- cmd/nerdctl/volume/volume_inspect_test.go | 389 ++++----- cmd/nerdctl/volume/volume_list_test.go | 742 ++++++++---------- cmd/nerdctl/volume/volume_namespace_test.go | 178 ++--- cmd/nerdctl/volume/volume_prune_linux_test.go | 172 ++-- .../volume/volume_remove_linux_test.go | 319 +++----- 9 files changed, 1063 insertions(+), 1233 deletions(-) create mode 100644 cmd/nerdctl/main_test_test.go diff --git a/cmd/nerdctl/main_linux_test.go b/cmd/nerdctl/main_linux_test.go index a0e82861a84..274604e27b9 100644 --- a/cmd/nerdctl/main_linux_test.go +++ b/cmd/nerdctl/main_linux_test.go @@ -20,17 +20,39 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) // TestIssue108 tests https://github.com/containerd/nerdctl/issues/108 // ("`nerdctl run --net=host -it` fails while `nerdctl run -it --net=host` works") func TestIssue108(t *testing.T) { - base := testutil.NewBase(t) - // unbuffer(1) emulates tty, which is required by `nerdctl run -t`. - // unbuffer(1) can be installed with `apt-get install expect`. - unbuffer := []string{"unbuffer"} - base.CmdWithHelper(unbuffer, "run", "-it", "--rm", "--net=host", testutil.AlpineImage, - "echo", "this was always working").AssertOK() - base.CmdWithHelper(unbuffer, "run", "--rm", "--net=host", "-it", testutil.AlpineImage, - "echo", "this was not working due to issue #108").AssertOK() + nerdtest.Setup() + + testGroup := &test.Group{ + { + Description: "-it --net=host", + Require: test.Binary("unbuffer"), + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers. + Command("run", "-it", "--rm", "--net=host", testutil.AlpineImage, "echo", "this was always working"). + WithWrapper("unbuffer") + }, + // Note: unbuffer will merge stdout and stderr, preventing exact match here + Expected: test.Expects(0, nil, test.Contains("this was always working")), + }, + { + Description: "--net=host -it", + Require: test.Binary("unbuffer"), + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers. + Command("run", "--rm", "--net=host", "-it", testutil.AlpineImage, "echo", "this was not working due to issue #108"). + WithWrapper("unbuffer") + }, + // Note: unbuffer will merge stdout and stderr, preventing exact match here + Expected: test.Expects(0, nil, test.Contains("this was not working due to issue #108")), + }, + } + + testGroup.Run(t) } diff --git a/cmd/nerdctl/main_test.go b/cmd/nerdctl/main_test.go index a450c963bf5..c1e3caf94fd 100644 --- a/cmd/nerdctl/main_test.go +++ b/cmd/nerdctl/main_test.go @@ -17,15 +17,14 @@ package main import ( - "os" - "path/filepath" + "errors" "testing" - "gotest.tools/v3/assert" - "github.com/containerd/containerd/v2/defaults" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestMain(m *testing.M) { @@ -34,56 +33,100 @@ func TestMain(m *testing.M) { // TestUnknownCommand tests https://github.com/containerd/nerdctl/issues/487 func TestUnknownCommand(t *testing.T) { - t.Parallel() - base := testutil.NewBase(t) - base.Cmd("non-existent-command").AssertFail() - base.Cmd("non-existent-command", "info").AssertFail() - base.Cmd("system", "non-existent-command").AssertFail() - base.Cmd("system", "non-existent-command", "info").AssertFail() - base.Cmd("system").AssertOK() // show help without error - base.Cmd("system", "info").AssertOutContains("Kernel Version:") - base.Cmd("info").AssertOutContains("Kernel Version:") + nerdtest.Setup() + + var unknownSubCommand = errors.New("unknown subcommand") + + testGroup := &test.Group{ + { + Description: "non-existent-command", + Command: test.RunCommand("non-existent-command"), + Expected: test.Expects(1, []error{unknownSubCommand}, nil), + }, + { + Description: "non-existent-command info", + Command: test.RunCommand("non-existent-command", "info"), + Expected: test.Expects(1, []error{unknownSubCommand}, nil), + }, + { + Description: "system non-existent-command", + Command: test.RunCommand("system", "non-existent-command"), + Expected: test.Expects(1, []error{unknownSubCommand}, nil), + }, + { + Description: "system non-existent-command info", + Command: test.RunCommand("system", "non-existent-command", "info"), + Expected: test.Expects(1, []error{unknownSubCommand}, nil), + }, + { + Description: "system", + Command: test.RunCommand("system"), + Expected: test.Expects(0, nil, nil), + }, + { + Description: "system info", + Command: test.RunCommand("system", "info"), + Expected: test.Expects(0, nil, test.Contains("Kernel Version:")), + }, + { + Description: "info", + Command: test.RunCommand("info"), + Expected: test.Expects(0, nil, test.Contains("Kernel Version:")), + }, + } + + testGroup.Run(t) } -// TestNerdctlConfig validates the configuration precedence [CLI, Env, TOML, Default]. +// TestNerdctlConfig validates the configuration precedence [CLI, Env, TOML, Default] and broken config rejection func TestNerdctlConfig(t *testing.T) { - testutil.DockerIncompatible(t) - t.Parallel() - tomlPath := filepath.Join(t.TempDir(), "nerdctl.toml") - err := os.WriteFile(tomlPath, []byte(` -snapshotter = "dummy-snapshotter-via-toml" -`), 0400) - assert.NilError(t, err) - base := testutil.NewBase(t) - - // [Default] - base.Cmd("info", "-f", "{{.Driver}}").AssertOutExactly(defaults.DefaultSnapshotter + "\n") - - // [TOML, Default] - base.Env = append(base.Env, "NERDCTL_TOML="+tomlPath) - base.Cmd("info", "-f", "{{.Driver}}").AssertOutExactly("dummy-snapshotter-via-toml\n") - - // [CLI, TOML, Default] - base.Cmd("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli").AssertOutExactly("dummy-snapshotter-via-cli\n") - - // [Env, TOML, Default] - base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=dummy-snapshotter-via-env") - base.Cmd("info", "-f", "{{.Driver}}").AssertOutExactly("dummy-snapshotter-via-env\n") - - // [CLI, Env, TOML, Default] - base.Cmd("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli").AssertOutExactly("dummy-snapshotter-via-cli\n") -} - -func TestNerdctlConfigBad(t *testing.T) { - testutil.DockerIncompatible(t) - t.Parallel() - tomlPath := filepath.Join(t.TempDir(), "config.toml") - err := os.WriteFile(tomlPath, []byte(` -# containerd config, not nerdctl config -version = 2 -`), 0400) - assert.NilError(t, err) - base := testutil.NewBase(t) - base.Env = append(base.Env, "NERDCTL_TOML="+tomlPath) - base.Cmd("info").AssertFail() + nerdtest.Setup() + + tc := &test.Case{ + Description: "Nerdctl configuration", + // Docker does not support nerdctl.toml obviously + Require: test.Not(nerdtest.Docker), + SubTests: []*test.Case{ + { + Description: "Default", + Command: test.RunCommand("info", "-f", "{{.Driver}}"), + Expected: test.Expects(0, nil, test.Equals(defaults.DefaultSnapshotter+"\n")), + }, + { + Description: "TOML > Default", + Command: test.RunCommand("info", "-f", "{{.Driver}}"), + Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-toml\n")), + Data: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), + }, + { + Description: "Cli > TOML > Default", + Command: test.RunCommand("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli"), + Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-cli\n")), + Data: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), + }, + { + Description: "Env > TOML > Default", + Command: test.RunCommand("info", "-f", "{{.Driver}}"), + Env: map[string]string{"CONTAINERD_SNAPSHOTTER": "dummy-snapshotter-via-env"}, + Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-env\n")), + Data: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), + }, + { + Description: "Cli > Env > TOML > Default", + Command: test.RunCommand("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli"), + Env: map[string]string{"CONTAINERD_SNAPSHOTTER": "dummy-snapshotter-via-env"}, + Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-cli\n")), + Data: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), + }, + { + Description: "Broken config", + Command: test.RunCommand("info"), + Expected: test.Expects(1, []error{errors.New("failed to load nerdctl config")}, nil), + Data: test.WithConfig(nerdtest.NerdctlToml, `# containerd config, not nerdctl config +version = 2`), + }, + }, + } + + tc.Run(t) } diff --git a/cmd/nerdctl/main_test_test.go b/cmd/nerdctl/main_test_test.go new file mode 100644 index 00000000000..a515df48536 --- /dev/null +++ b/cmd/nerdctl/main_test_test.go @@ -0,0 +1,147 @@ +/* + 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 ( + "errors" + "log" + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +// TestTest is testing the test tooling itself +func TestTest(t *testing.T) { + nerdtest.Setup() + + tg := &test.Group{ + { + Description: "failure", + Command: test.RunCommand("undefinedcommand"), + Expected: test.Expects(1, nil, nil), + }, + { + Description: "success", + Command: test.RunCommand("info"), + Expected: test.Expects(0, nil, nil), + }, + { + Description: "failure with single error testing", + Command: test.RunCommand("undefinedcommand"), + Expected: test.Expects(1, []error{errors.New("unknown subcommand")}, nil), + }, + { + Description: "success with contains output testing", + Command: test.RunCommand("info"), + Expected: test.Expects(0, nil, test.Contains("Kernel")), + }, + { + Description: "success with negative output testing", + Command: test.RunCommand("info"), + Expected: test.Expects(0, nil, test.DoesNotContain("foobar")), + }, + // Note that docker annoyingly returns 125 in a few conditions like this + { + Description: "failure with multiple error testing", + Command: test.RunCommand("-fail"), + Expected: test.Expects(-1, []error{errors.New("unknown"), errors.New("shorthand")}, nil), + }, + { + Description: "success with exact output testing", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.CustomCommand("echo", "foobar") + }, + Expected: test.Expects(0, nil, test.Equals("foobar\n")), + }, + { + Description: "data propagation", + Data: test.WithData("status", "uninitialized"), + Setup: func(data test.Data, helpers test.Helpers) { + data.Set("status", data.Get("status")+"-setup") + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + cmd := helpers.CustomCommand("printf", data.Get("status")) + data.Set("status", data.Get("status")+"-command") + return cmd + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("first-run") == "" { + data.Set("first-run", "first cleanup") + return + } + if data.Get("status") != "uninitialized-setup-command" { + log.Fatalf("unexpected status label %q", data.Get("status")) + } + data.Set("status", data.Get("status")+"-cleanup") + }, + SubTests: []*test.Case{ + { + Description: "Subtest data propagation", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.CustomCommand("printf", data.Get("status")) + }, + Expected: test.Expects(0, nil, test.Equals("uninitialized-setup-command")), + }, + }, + Expected: test.Expects(0, nil, test.Equals("uninitialized-setup")), + }, + { + Description: "env propagation and isolation", + Env: map[string]string{ + "GLOBAL_ENV": "in this test", + }, + Setup: func(data test.Data, helpers test.Helpers) { + cmd := helpers.CustomCommand("sh", "-c", "--", "printf \"$GLOBAL_ENV\"") + cmd.Run(&test.Expected{ + Output: test.Equals("in this test"), + }) + cmd.WithEnv(map[string]string{ + "GLOBAL_ENV": "overridden in setup", + }) + cmd.Run(&test.Expected{ + Output: test.Equals("overridden in setup"), + }) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + cmd := helpers.CustomCommand("sh", "-c", "--", "printf \"$GLOBAL_ENV\"") + cmd.Run(&test.Expected{ + Output: test.Equals("in this test"), + }) + cmd.WithEnv(map[string]string{ + "GLOBAL_ENV": "overridden in command", + }) + return cmd + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + cmd := helpers.CustomCommand("sh", "-c", "--", "printf \"$GLOBAL_ENV\"") + cmd.Run(&test.Expected{ + Output: test.Equals("in this test"), + }) + cmd.WithEnv(map[string]string{ + "GLOBAL_ENV": "overridden in cleanup", + }) + cmd.Run(&test.Expected{ + Output: test.Equals("overridden in cleanup"), + }) + }, + Expected: test.Expects(0, nil, test.Equals("overridden in command")), + }, + } + + tg.Run(t) +} diff --git a/cmd/nerdctl/volume/volume_create_test.go b/cmd/nerdctl/volume/volume_create_test.go index a9126f704f7..767f7ac12be 100644 --- a/cmd/nerdctl/volume/volume_create_test.go +++ b/cmd/nerdctl/volume/volume_create_test.go @@ -17,155 +17,97 @@ package volume import ( + "errors" "testing" - "gotest.tools/v3/icmd" - "github.com/containerd/errdefs" - "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestVolumeCreate(t *testing.T) { - t.Parallel() - - base := testutil.NewBase(t) + nerdtest.Setup() - malformed := errdefs.ErrInvalidArgument.Error() - atMost := "at most 1 arg" - exitCodeVariant := 1 - if base.Target == testutil.Docker { - malformed = "invalid" - exitCodeVariant = 125 - } - - testCases := []struct { - description string - command func(tID string) *testutil.Cmd - tearUp func(tID string) - tearDown func(tID string) - expected func(tID string) icmd.Expected - inspect func(t *testing.T, stdout string, stderr string) - dockerIncompatible bool - }{ + tg := &test.Group{ { - description: "arg missing should create anonymous volume", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "create") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, - } - }, + Description: "arg missing should create anonymous volume", + Command: test.RunCommand("volume", "create"), + Expected: test.Expects(0, nil, nil), }, { - description: "invalid identifier should fail", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "create", "∞") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: malformed, - } - }, + Description: "invalid identifier should fail", + Command: test.RunCommand("volume", "create", "∞"), + Expected: test.Expects(1, []error{errdefs.ErrInvalidArgument}, nil), }, { - description: "too many args should fail", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "create", "too", "many") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: atMost, - } - }, + Description: "too many args should fail", + Command: test.RunCommand("volume", "create", "too", "many"), + Expected: test.Expects(1, []error{errors.New("at most 1 arg")}, nil), }, { - description: "success", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "create", tID) + Description: "success", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "create", data.Identifier()) }, - tearDown: func(tID string) { - base.Cmd("volume", "rm", "-f", tID).Run() + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Identifier()) }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, - Out: tID, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Equals(data.Identifier() + "\n"), } }, }, { - description: "success with labels", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "create", "--label", "foo1=baz1", "--label", "foo2=baz2", tID) + Description: "success with labels", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "create", "--label", "foo1=baz1", "--label", "foo2=baz2", data.Identifier()) }, - tearDown: func(tID string) { - base.Cmd("volume", "rm", "-f", tID).Run() + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Identifier()) }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, - Out: tID, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Equals(data.Identifier() + "\n"), } }, }, { - description: "invalid labels", - command: func(tID string) *testutil.Cmd { + Description: "invalid labels", + Command: func(data test.Data, helpers test.Helpers) test.Command { // See https://github.com/containerd/nerdctl/issues/3126 - return base.Cmd("volume", "create", "--label", "a", "--label", "", tID) + return helpers.Command("volume", "create", "--label", "a", "--label", "", data.Identifier()) }, - tearDown: func(tID string) { - base.Cmd("volume", "rm", "-f", tID).Run() + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Identifier()) }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: exitCodeVariant, - Err: malformed, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + // NOTE: docker returns 125 on this + ExitCode: -1, + Errors: []error{errdefs.ErrInvalidArgument}, } }, }, { - description: "creating already existing volume should succeed", - command: func(tID string) *testutil.Cmd { - base.Cmd("volume", "create", tID).AssertOK() - return base.Cmd("volume", "create", tID) + Description: "creating already existing volume should succeed", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("volume", "create", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "create", data.Identifier()) }, - tearDown: func(tID string) { - base.Cmd("volume", "rm", "-f", tID).Run() + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Identifier()) }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, - Out: tID, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Equals(data.Identifier() + "\n"), } }, }, } - for _, test := range testCases { - currentTest := test - t.Run(currentTest.description, func(tt *testing.T) { - tt.Parallel() - - tID := testutil.Identifier(tt) - - if currentTest.tearDown != nil { - currentTest.tearDown(tID) - tt.Cleanup(func() { - currentTest.tearDown(tID) - }) - } - if currentTest.tearUp != nil { - currentTest.tearUp(tID) - } - - cmd := currentTest.command(tID) - cmd.Assert(currentTest.expected(tID)) - }) - } + tg.Run(t) } diff --git a/cmd/nerdctl/volume/volume_inspect_test.go b/cmd/nerdctl/volume/volume_inspect_test.go index 0d4ce4e6d05..edee98be906 100644 --- a/cmd/nerdctl/volume/volume_inspect_test.go +++ b/cmd/nerdctl/volume/volume_inspect_test.go @@ -19,266 +19,185 @@ package volume import ( "crypto/rand" "encoding/json" + "errors" "fmt" "os" "path/filepath" - "strings" "testing" "gotest.tools/v3/assert" - "gotest.tools/v3/icmd" "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func createFileWithSize(base *testutil.Base, vol string, size int64) { - v := base.InspectVolume(vol) +func createFileWithSize(mountPoint string, size int64) error { token := make([]byte, size) _, _ = rand.Read(token) - err := os.WriteFile(filepath.Join(v.Mountpoint, "test-file"), token, 0644) - assert.NilError(base.T, err) + err := os.WriteFile(filepath.Join(mountPoint, "test-file"), token, 0644) + return err } func TestVolumeInspect(t *testing.T) { - t.Parallel() - - base := testutil.NewBase(t) - tID := testutil.Identifier(t) + nerdtest.Setup() var size int64 = 1028 - malformed := errdefs.ErrInvalidArgument.Error() - notFound := errdefs.ErrNotFound.Error() - requireArg := "requires at least 1 arg" - if base.Target == testutil.Docker { - malformed = "no such volume" - notFound = "no such volume" - } - - tearUp := func(t *testing.T) { - base.Cmd("volume", "create", tID).AssertOK() - base.Cmd("volume", "create", "--label", "foo=fooval", "--label", "bar=barval", tID+"-second").AssertOK() - - // Obviously note here that if inspect code gets totally hosed, this entire suite will - // probably fail right here on the tearUp instead of actually testing something - createFileWithSize(base, tID, size) - } - - tearDown := func(t *testing.T) { - base.Cmd("volume", "rm", "-f", tID).Run() - base.Cmd("volume", "rm", "-f", tID+"-second").Run() - } - - tearDown(t) - t.Cleanup(func() { - tearDown(t) - }) - tearUp(t) - - testCases := []struct { - description string - command func(tID string) *testutil.Cmd - tearUp func(tID string) - tearDown func(tID string) - expected func(tID string) icmd.Expected - inspect func(t *testing.T, stdout string, stderr string) - dockerIncompatible bool - }{ - { - description: "arg missing should fail", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "inspect") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: requireArg, - } - }, - }, - { - description: "invalid identifier should fail", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "inspect", "∞") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: malformed, - } - }, - }, - { - description: "non existent volume should fail", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "inspect", "doesnotexist") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: notFound, - } - }, - }, - { - description: "success", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "inspect", tID) - }, - tearDown: func(tID string) { - base.Cmd("volume", "rm", "-f", tID) - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, - Out: tID, - } - }, - inspect: func(t *testing.T, stdout string, stderr string) { - var dc []native.Volume - if err := json.Unmarshal([]byte(stdout), &dc); err != nil { - t.Fatal(err) - } - assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))) - assert.Assert(t, dc[0].Name == tID, fmt.Sprintf("expected name to be %q (was %q)", tID, dc[0].Name)) - assert.Assert(t, dc[0].Labels == nil, fmt.Sprintf("expected labels to be nil and were %v", dc[0].Labels)) - }, - }, - { - description: "inspect labels", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "inspect", tID+"-second") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, - Out: tID, - } - }, - inspect: func(t *testing.T, stdout string, stderr string) { - var dc []native.Volume - if err := json.Unmarshal([]byte(stdout), &dc); err != nil { - t.Fatal(err) - } - - labels := *dc[0].Labels - assert.Assert(t, len(labels) == 2, fmt.Sprintf("two results, not %d", len(labels))) - assert.Assert(t, labels["foo"] == "fooval", fmt.Sprintf("label foo should be fooval, not %s", labels["foo"])) - assert.Assert(t, labels["bar"] == "barval", fmt.Sprintf("label bar should be barval, not %s", labels["bar"])) - }, + tc := &test.Case{ + Description: "Volume inspect", + Setup: func(data test.Data, helpers test.Helpers) { + data.Set("volprefix", data.Identifier()) + helpers.Ensure("volume", "create", data.Identifier()) + helpers.Ensure("volume", "create", "--label", "foo=fooval", "--label", "bar=barval", data.Identifier()+"-second") + // Obviously note here that if inspect code gets totally hosed, this entire suite will + // probably fail right here on the Setup instead of actually testing something + vol := nerdtest.InspectVolume(helpers, data.Identifier()) + err := createFileWithSize(vol.Mountpoint, size) + assert.NilError(t, err, "File creation failed") }, - { - description: "inspect size", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "inspect", "--size", tID) - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, - Out: tID, - } - }, - inspect: func(t *testing.T, stdout string, stderr string) { - var dc []native.Volume - if err := json.Unmarshal([]byte(stdout), &dc); err != nil { - t.Fatal(err) - } - assert.Assert(t, dc[0].Size == size, fmt.Sprintf("expected size to be %d (was %d)", size, dc[0].Size)) - }, - dockerIncompatible: true, - }, - { - description: "multi success", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "inspect", tID, tID+"-second") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, - } - }, - inspect: func(t *testing.T, stdout string, stderr string) { - var dc []native.Volume - if err := json.Unmarshal([]byte(stdout), &dc); err != nil { - t.Fatal(err) - } - assert.Assert(t, len(dc) == 2, fmt.Sprintf("two results, not %d", len(dc))) - assert.Assert(t, dc[0].Name == tID, fmt.Sprintf("expected name to be %q (was %q)", tID, dc[0].Name)) - assert.Assert(t, dc[1].Name == tID+"-second", fmt.Sprintf("expected name to be %q (was %q)", tID+"-second", dc[1].Name)) - }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Identifier()) + helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-second") }, - { - description: "part success multi", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "inspect", "invalid∞", "nonexistent", tID) - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Out: tID, - Err: notFound, - } - }, - inspect: func(t *testing.T, stdout string, stderr string) { - assert.Assert(t, strings.Contains(stderr, notFound)) - assert.Assert(t, strings.Contains(stderr, malformed)) - var dc []native.Volume - if err := json.Unmarshal([]byte(stdout), &dc); err != nil { - t.Fatal(err) - } - assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))) - assert.Assert(t, dc[0].Name == tID, fmt.Sprintf("expected name to be %q (was %q)", tID, dc[0].Name)) - }, - }, - { - description: "multi failure", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "inspect", "invalid∞", "nonexistent") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - } - }, - inspect: func(t *testing.T, stdout string, stderr string) { - assert.Assert(t, strings.Contains(stderr, notFound)) - assert.Assert(t, strings.Contains(stderr, malformed)) + SubTests: []*test.Case{ + { + Description: "arg missing should fail", + Command: test.RunCommand("volume", "inspect"), + Expected: test.Expects(1, []error{errors.New("requires at least 1 arg")}, nil), + }, + { + Description: "invalid identifier should fail", + Command: test.RunCommand("volume", "inspect", "∞"), + Expected: test.Expects(1, []error{errdefs.ErrInvalidArgument}, nil), + }, + { + Description: "non existent volume should fail", + Command: test.RunCommand("volume", "inspect", "doesnotexist"), + Expected: test.Expects(1, []error{errdefs.ErrNotFound}, nil), + }, + { + Description: "success", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "inspect", data.Get("volprefix")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(data.Get("volprefix")), + func(stdout string, info string, t *testing.T) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))+info) + assert.Assert(t, dc[0].Name == data.Get("volprefix"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("volprefix"), dc[0].Name)+info) + assert.Assert(t, dc[0].Labels == nil, fmt.Sprintf("expected labels to be nil and were %v", dc[0].Labels)+info) + }, + ), + } + }, + }, + { + Description: "inspect labels", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "inspect", data.Get("volprefix")+"-second") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(data.Get("volprefix")), + func(stdout string, info string, t *testing.T) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + labels := *dc[0].Labels + assert.Assert(t, len(labels) == 2, fmt.Sprintf("two results, not %d", len(labels))) + assert.Assert(t, labels["foo"] == "fooval", fmt.Sprintf("label foo should be fooval, not %s", labels["foo"])) + assert.Assert(t, labels["bar"] == "barval", fmt.Sprintf("label bar should be barval, not %s", labels["bar"])) + }, + ), + } + }, + }, + { + Description: "inspect size", + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "inspect", "--size", data.Get("volprefix")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(data.Get("volprefix")), + func(stdout string, info string, t *testing.T) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, dc[0].Size == size, fmt.Sprintf("expected size to be %d (was %d)", size, dc[0].Size)) + }, + ), + } + }, + }, + { + Description: "multi success", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "inspect", data.Get("volprefix"), data.Get("volprefix")+"-second") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(data.Get("volprefix")), + test.Contains(data.Get("volprefix")+"-second"), + func(stdout string, info string, t *testing.T) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, len(dc) == 2, fmt.Sprintf("two results, not %d", len(dc))) + assert.Assert(t, dc[0].Name == data.Get("volprefix"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("volprefix"), dc[0].Name)) + assert.Assert(t, dc[1].Name == data.Get("volprefix")+"-second", fmt.Sprintf("expected name to be %q (was %q)", data.Get("volprefix")+"-second", dc[1].Name)) + }, + ), + } + }, + }, + { + Description: "part success multi", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "inspect", "invalid∞", "nonexistent", data.Get("volprefix")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errdefs.ErrNotFound, errdefs.ErrInvalidArgument}, + Output: test.All( + test.Contains(data.Get("volprefix")), + func(stdout string, info string, t *testing.T) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))) + assert.Assert(t, dc[0].Name == data.Get("volprefix"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("volprefix"), dc[0].Name)) + }, + ), + } + }, + }, + { + Description: "multi failure", + Command: test.RunCommand("volume", "inspect", "invalid∞", "nonexistent"), + Expected: test.Expects(1, []error{errdefs.ErrNotFound, errdefs.ErrInvalidArgument}, nil), }, }, } - for _, test := range testCases { - currentTest := test - t.Run(currentTest.description, func(tt *testing.T) { - if currentTest.dockerIncompatible { - testutil.DockerIncompatible(tt) - } - - tt.Parallel() - - // We use the main test tID here - if currentTest.tearDown != nil { - currentTest.tearDown(tID) - tt.Cleanup(func() { - currentTest.tearDown(tID) - }) - } - if currentTest.tearUp != nil { - currentTest.tearUp(tID) - } - - // See https://github.com/containerd/nerdctl/issues/3130 - // We run first to capture the underlying icmd command and output - cmd := currentTest.command(tID) - res := cmd.Run() - cmd.Assert(currentTest.expected(tID)) - if currentTest.inspect != nil { - currentTest.inspect(tt, res.Stdout(), res.Stderr()) - } - }) - } + tc.Run(t) } diff --git a/cmd/nerdctl/volume/volume_list_test.go b/cmd/nerdctl/volume/volume_list_test.go index 6195db2eb13..d0ad6d78463 100644 --- a/cmd/nerdctl/volume/volume_list_test.go +++ b/cmd/nerdctl/volume/volume_list_test.go @@ -17,464 +17,376 @@ package volume import ( - "errors" "fmt" "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/tabutil" - "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func TestVolumeLs(t *testing.T) { - t.Parallel() - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - testutil.DockerIncompatible(t) - - var vol1, vol2, vol3 = tID + "vol-1", tID + "vol-2", tID + "empty" - - tearDown := func() { - base.Cmd("volume", "rm", "-f", vol1).Run() - base.Cmd("volume", "rm", "-f", vol2).Run() - base.Cmd("volume", "rm", "-f", vol3).Run() - } - - tearUp := func() { - base.Cmd("volume", "create", vol1).AssertOK() - base.Cmd("volume", "create", vol2).AssertOK() - base.Cmd("volume", "create", vol3).AssertOK() - createFileWithSize(base, vol1, 102400) - createFileWithSize(base, vol2, 204800) - } - - tearDown() - t.Cleanup(func() { - tearDown() - }) - tearUp() - - base.Cmd("volume", "ls", "--size").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 4 { - return errors.New("expected at least 4 lines") - } - volSizes := map[string]string{ - vol1: "100.0 KiB", - vol2: "200.0 KiB", - vol3: "0.0 B", - } - - var numMatches = 0 - var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") - var err = tab.ParseHeader(lines[0]) - if err != nil { - return err - } - for _, line := range lines { - name, _ := tab.ReadRow(line, "VOLUME NAME") - size, _ := tab.ReadRow(line, "SIZE") - expectSize, ok := volSizes[name] - if !ok { - continue - } - if size != expectSize { - return fmt.Errorf("expected size %s for volume %s, got %s", expectSize, name, size) - } - numMatches++ - } - if len(volSizes) != numMatches { - return fmt.Errorf("expected %d volumes, got: %d", len(volSizes), numMatches) - } - return nil - }) - -} - -func TestVolumeLsFilter(t *testing.T) { - t.Parallel() - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - - var vol1, vol2, vol3, vol4 = tID + "vol-1", tID + "vol-2", tID + "vol-3", tID + "vol-4" - var label1, label2, label3, label4 = tID + "=label-1", tID + "=label-2", tID + "=label-3", tID + "-group=label-4" - - tearDown := func() { - base.Cmd("volume", "rm", "-f", vol1).Run() - base.Cmd("volume", "rm", "-f", vol2).Run() - base.Cmd("volume", "rm", "-f", vol3).Run() - base.Cmd("volume", "rm", "-f", vol4).Run() - } - - tearUp := func() { - base.Cmd("volume", "create", "--label="+label1, "--label="+label4, vol1).AssertOK() - base.Cmd("volume", "create", "--label="+label2, "--label="+label4, vol2).AssertOK() - base.Cmd("volume", "create", "--label="+label3, vol3).AssertOK() - base.Cmd("volume", "create", vol4).AssertOK() - } - - tearDown() - t.Cleanup(func() { - tearDown() - }) - tearUp() - - testCases := []struct { - description string - command func(tID string) - }{ - { - description: "no filter", - command: func(tID string) { - base.Cmd("volume", "ls", "--quiet").AssertOutWithFunc(func(stdout string) error { +func TestVolumeLsSize(t *testing.T) { + nerdtest.Setup() + + tc := &test.Case{ + Description: "Volume ls --size", + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("volume", "create", data.Identifier()+"-1") + helpers.Ensure("volume", "create", data.Identifier()+"-2") + helpers.Ensure("volume", "create", data.Identifier()+"-empty") + vol1 := nerdtest.InspectVolume(helpers, data.Identifier()+"-1") + vol2 := nerdtest.InspectVolume(helpers, data.Identifier()+"-2") + + err := createFileWithSize(vol1.Mountpoint, 102400) + assert.NilError(t, err, "File creation failed") + err = createFileWithSize(vol2.Mountpoint, 204800) + assert.NilError(t, err, "File creation failed") + }, + Command: test.RunCommand("volume", "ls", "--size"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 4 { - return errors.New("expected at least 4 lines") - } - volNames := map[string]struct{}{ - vol1: {}, - vol2: {}, - vol3: {}, - vol4: {}, + assert.Assert(t, len(lines) >= 4, "expected at least 4 lines"+info) + volSizes := map[string]string{ + data.Identifier() + "-1": "100.0 KiB", + data.Identifier() + "-2": "200.0 KiB", + data.Identifier() + "-empty": "0.0 B", } var numMatches = 0 - for _, name := range lines { - _, ok := volNames[name] + var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") + var err = tab.ParseHeader(lines[0]) + assert.NilError(t, err, info) + + for _, line := range lines { + name, _ := tab.ReadRow(line, "VOLUME NAME") + size, _ := tab.ReadRow(line, "SIZE") + expectSize, ok := volSizes[name] if !ok { continue } + assert.Assert(t, size == expectSize, fmt.Sprintf("expected size %s for volume %s, got %s", expectSize, name, size)+info) numMatches++ } - if len(volNames) != numMatches { - return fmt.Errorf("expected %d volumes, got: %d", len(volNames), numMatches) - } - return nil - }) - }, + assert.Assert(t, numMatches == len(volSizes), fmt.Sprintf("expected %d volumes, got: %d", len(volSizes), numMatches)+info) + }, + } }, - { - description: "label=" + tID, - command: func(tID string) { - base.Cmd("volume", "ls", "--quiet", "--filter", "label="+tID).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 3 { - return errors.New("expected at least 3 lines") - } - volNames := map[string]struct{}{ - vol1: {}, - vol2: {}, - vol3: {}, - } - - for _, name := range lines { - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil - }) - }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-1") + helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-2") + helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-empty") }, - { - description: "label=" + label2, - command: func(tID string) { - base.Cmd("volume", "ls", "--quiet", "--filter", "label="+label2).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 1 { - return errors.New("expected at least 1 lines") - } - volNames := map[string]struct{}{ - vol2: {}, - } + } + + tc.Run(t) +} + +func TestVolumeLsFilter(t *testing.T) { + nerdtest.Setup() + + tc := &test.Case{ + Description: "Volume ls", + Setup: func(data test.Data, helpers test.Helpers) { + var vol1, vol2, vol3, vol4 = data.Identifier() + "-1", data.Identifier() + "-2", data.Identifier() + "-3", data.Identifier() + "-4" + var label1, label2, label3, label4 = data.Identifier() + "=label-1", data.Identifier() + "=label-2", data.Identifier() + "=label-3", data.Identifier() + "-group=label-4" + + helpers.Ensure("volume", "create", "--label="+label1, "--label="+label4, vol1) + helpers.Ensure("volume", "create", "--label="+label2, "--label="+label4, vol2) + helpers.Ensure("volume", "create", "--label="+label3, vol3) + helpers.Ensure("volume", "create", vol4) + + err := createFileWithSize(nerdtest.InspectVolume(helpers, vol1).Mountpoint, 409600) + assert.NilError(t, err, "File creation failed") + err = createFileWithSize(nerdtest.InspectVolume(helpers, vol2).Mountpoint, 1024000) + assert.NilError(t, err, "File creation failed") + err = createFileWithSize(nerdtest.InspectVolume(helpers, vol3).Mountpoint, 409600) + assert.NilError(t, err, "File creation failed") + err = createFileWithSize(nerdtest.InspectVolume(helpers, vol4).Mountpoint, 1024000) + assert.NilError(t, err, "File creation failed") + + data.Set("vol1", vol1) + data.Set("vol2", vol2) + data.Set("vol3", vol3) + data.Set("vol4", vol4) + data.Set("mainlabel", data.Identifier()) + data.Set("label1", label1) + data.Set("label2", label2) + data.Set("label3", label3) + data.Set("label4", label4) - for _, name := range lines { - if name == "" { - continue - } - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil - }) - }, }, - { - description: "label=" + tID + "=", - command: func(tID string) { - base.Cmd("volume", "ls", "--quiet", "--filter", "label="+tID+"=").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) > 0 { - for _, name := range lines { - if name != "" { - return fmt.Errorf("unexpected volumes %d found", len(lines)) + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Get("vol1")) + helpers.Anyhow("volume", "rm", "-f", data.Get("vol2")) + helpers.Anyhow("volume", "rm", "-f", data.Get("vol3")) + helpers.Anyhow("volume", "rm", "-f", data.Get("vol4")) + }, + SubTests: []*test.Case{ + { + Description: "No filter", + Command: test.RunCommand("volume", "ls", "--quiet"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 4, "expected at least 4 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + data.Get("vol2"): {}, + data.Get("vol3"): {}, + data.Get("vol4"): {}, } - } + var numMatches = 0 + for _, name := range lines { + _, ok := volNames[name] + if !ok { + continue + } + numMatches++ + } + assert.Assert(t, len(volNames) == numMatches, fmt.Sprintf("expected %d volumes, got: %d", len(volNames), numMatches)) + }, } - return nil - }) + }, }, - }, - { - description: "label=" + label1 + " label=" + label2, - command: func(tID string) { - base.Cmd("volume", "ls", "--quiet", "--filter", "label="+label1, "--filter", "label="+label2).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) > 0 { - for _, name := range lines { - if name != "" { - return fmt.Errorf("unexpected volumes %d found", len(lines)) + { + Description: "Retrieving label=mainlabel", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("mainlabel")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + data.Get("vol2"): {}, + data.Get("vol3"): {}, } - } + for _, name := range lines { + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, } - return nil - }) - + }, }, - }, - { - description: "label=" + tID + " label=" + label4, - command: func(tID string) { - base.Cmd("volume", "ls", "--quiet", "--filter", "label="+tID, "--filter", "label="+label4).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 2 { - return errors.New("expected at least 2 lines") - } - volNames := map[string]struct{}{ - vol1: {}, - vol2: {}, - } - - for _, name := range lines { - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } + { + Description: "Retrieving label=mainlabel=label2", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("label2")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 1, "expected at least 1 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol2"): {}, + } + for _, name := range lines { + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, } - return nil - }) + }, }, - }, - { - description: "name=" + vol1, - command: func(tID string) { - base.Cmd("volume", "ls", "--quiet", "--filter", "name="+vol1).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 1 { - return errors.New("expected at least 1 lines") + { + Description: "Retrieving label=mainlabel=", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("mainlabel")+"=") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + assert.Assert(t, strings.TrimSpace(stdout) == "", "expected no result"+info) + }, } - volNames := map[string]struct{}{ - vol1: {}, - } - - for _, name := range lines { - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } + }, + }, + { + Description: "Retrieving label=mainlabel=label1 and label=mainlabel=label2", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("label1"), "--filter", "label="+data.Get("label2")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + assert.Assert(t, strings.TrimSpace(stdout) == "", "expected no result"+info) + }, } - return nil - }) + }, }, - }, - { - description: "name=vol-3", - command: func(tID string) { - base.Cmd("volume", "ls", "--quiet", "--filter", "name=vol-3"). - AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 1 { - return errors.New("expected at least 1 lines") - } - volNames := map[string]struct{}{ - vol3: {}, - } - - for _, name := range lines { - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) + { + Description: "Retrieving label=mainlabel and label=grouplabel=label4", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("mainlabel"), "--filter", "label="+data.Get("label4")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 2, "expected at least 2 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + data.Get("vol2"): {}, } - } - return nil - }) - }, - }, - { - description: "name=vol2 name=vol1", - command: func(tID string) { - base.Cmd("volume", "ls", "--quiet", "--filter", "name=vol2", "--filter", "name=vol1"). - AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) > 0 { for _, name := range lines { - if name != "" { - return fmt.Errorf("unexpected volumes %d found", len(lines)) - } + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) } - } - return nil - }) - }, - }, - } - - for _, test := range testCases { - currentTest := test - t.Run(currentTest.description, func(tt *testing.T) { - tt.Parallel() - currentTest.command(tID) - }) - } - -} - -func TestVolumeLsFilterSize(t *testing.T) { - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - testutil.DockerIncompatible(t) - - var vol1, vol2, vol3, vol4 = tID + "volsize-1", tID + "volsize-2", tID + "volsize-3", tID + "volsize-4" - var label1, label2, label3, label4 = tID + "=label-1", tID + "=label-2", tID + "=label-3", tID + "-group=label-4" - - tearDown := func() { - base.Cmd("volume", "rm", "-f", vol1).Run() - base.Cmd("volume", "rm", "-f", vol2).Run() - base.Cmd("volume", "rm", "-f", vol3).Run() - base.Cmd("volume", "rm", "-f", vol4).Run() - } - - tearUp := func() { - base.Cmd("volume", "create", "--label="+label1, "--label="+label4, vol1).AssertOK() - base.Cmd("volume", "create", "--label="+label2, "--label="+label4, vol2).AssertOK() - base.Cmd("volume", "create", "--label="+label3, vol3).AssertOK() - base.Cmd("volume", "create", vol4).AssertOK() - - createFileWithSize(base, vol1, 409600) - createFileWithSize(base, vol2, 1024000) - createFileWithSize(base, vol3, 409600) - createFileWithSize(base, vol4, 1024000) - } - - tearDown() - t.Cleanup(func() { - tearDown() - }) - tearUp() - - testCases := []struct { - description string - command func(tID string) - }{ - { - description: "size=1024000", - command: func(tID string) { - base.Cmd("volume", "ls", "--size", "--filter", "size=1024000").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 3 { - return errors.New("expected at least 3 lines") + }, } - - var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") - var err = tab.ParseHeader(lines[0]) - if err != nil { - return err - } - volNames := map[string]struct{}{ - vol2: {}, - vol4: {}, - } - - for _, line := range lines { - name, _ := tab.ReadRow(line, "VOLUME NAME") - if name == "VOLUME NAME" { - continue - } - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } - } - return nil - }) + }, }, - }, - { - description: "size>=1024000 size<=2048000", - command: func(tID string) { - base.Cmd("volume", "ls", "--size", "--filter", "size>=1024000", "--filter", "size<=2048000").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 3 { - return errors.New("expected at least 3 lines") - } - - var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") - var err = tab.ParseHeader(lines[0]) - if err != nil { - return err - } - volNames := map[string]struct{}{ - vol2: {}, - vol4: {}, - } - - for _, line := range lines { - name, _ := tab.ReadRow(line, "VOLUME NAME") - if name == "VOLUME NAME" { - continue - } - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } + { + Description: "Retrieving name=volume1", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "ls", "--quiet", "--filter", "name="+data.Get("vol1")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 1, "expected at least 1 line"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + } + for _, name := range lines { + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, } - return nil - }) + }, }, - }, - { - description: "size>204800 size<1024000", - command: func(tID string) { - base.Cmd("volume", "ls", "--size", "--filter", "size>204800", "--filter", "size<1024000").AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 3 { - return errors.New("expected at least 3 lines") + { + Description: "Retrieving name=volume1 and name=volume2", + // FIXME: https://github.com/containerd/nerdctl/issues/3452 + // Nerdctl filter behavior is broken + Require: nerdtest.Docker, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "ls", "--quiet", "--filter", "name="+data.Get("vol1"), "--filter", "name="+data.Get("vol2")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 2, "expected at least 2 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + data.Get("vol2"): {}, + } + for _, name := range lines { + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, } - - var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") - var err = tab.ParseHeader(lines[0]) - if err != nil { - return err + }, + }, + { + Description: "Retrieving size=1024000", + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "ls", "--size", "--filter", "size=1024000") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol2"): {}, + data.Get("vol4"): {}, + } + var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") + var err = tab.ParseHeader(lines[0]) + assert.NilError(t, err, "Tab reader failed") + for _, line := range lines { + + name, _ := tab.ReadRow(line, "VOLUME NAME") + if name == "VOLUME NAME" { + continue + } + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, } - volNames := map[string]struct{}{ - vol1: {}, - vol3: {}, + }, + }, + { + Description: "Retrieving size>=1024000 size<=2048000", + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "ls", "--size", "--filter", "size>=1024000", "--filter", "size<=2048000") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol2"): {}, + data.Get("vol4"): {}, + } + var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") + var err = tab.ParseHeader(lines[0]) + assert.NilError(t, err, "Tab reader failed") + for _, line := range lines { + + name, _ := tab.ReadRow(line, "VOLUME NAME") + if name == "VOLUME NAME" { + continue + } + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, } - - for _, line := range lines { - name, _ := tab.ReadRow(line, "VOLUME NAME") - if name == "VOLUME NAME" { - continue - } - _, ok := volNames[name] - if !ok { - return fmt.Errorf("unexpected volume %s found", name) - } + }, + }, + { + Description: "Retrieving size>204800 size<1024000", + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "ls", "--size", "--filter", "size>204800", "--filter", "size<1024000") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + data.Get("vol3"): {}, + } + var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") + var err = tab.ParseHeader(lines[0]) + assert.NilError(t, err, "Tab reader failed") + for _, line := range lines { + + name, _ := tab.ReadRow(line, "VOLUME NAME") + if name == "VOLUME NAME" { + continue + } + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, } - return nil - }) + }, }, }, } - - for _, test := range testCases { - currentTest := test - t.Run(currentTest.description, func(tt *testing.T) { - tt.Parallel() - currentTest.command(tID) - }) - } + tc.Run(t) } diff --git a/cmd/nerdctl/volume/volume_namespace_test.go b/cmd/nerdctl/volume/volume_namespace_test.go index dcda29a3648..b20f64984dc 100644 --- a/cmd/nerdctl/volume/volume_namespace_test.go +++ b/cmd/nerdctl/volume/volume_namespace_test.go @@ -19,134 +19,78 @@ package volume import ( "testing" - "gotest.tools/v3/icmd" - "github.com/containerd/errdefs" - "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestVolumeNamespace(t *testing.T) { - testutil.DockerIncompatible(t) - - t.Parallel() - - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - otherBase := testutil.NewBaseWithNamespace(t, tID+"-1") - thirdBase := testutil.NewBaseWithNamespace(t, tID+"-2") - - tearUp := func(t *testing.T) { - base.Cmd("volume", "create", tID).AssertOK() - } - - tearDown := func(t *testing.T) { - base.Cmd("volume", "rm", "-f", tID).Run() - otherBase.Cmd("namespace", "rm", "-f", tID+"-1").Run() - thirdBase.Cmd("namespace", "rm", "-f", tID+"-2").Run() - } - - tearDown(t) - t.Cleanup(func() { - tearDown(t) - }) - tearUp(t) - - testCases := []struct { - description string - command func(tID string) *testutil.Cmd - tearUp func(tID string) - tearDown func(tID string) - expected func(tID string) icmd.Expected - inspect func(t *testing.T, stdout string, stderr string) - dockerIncompatible bool - }{ - { - description: "inspect another namespace volume should fail", - command: func(tID string) *testutil.Cmd { - return otherBase.Cmd("volume", "inspect", tID) - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: errdefs.ErrNotFound.Error(), - } - }, + nerdtest.Setup() + + tg := &test.Case{ + Description: "Namespaces", + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + data.Set("root_namespace", data.Identifier()) + data.Set("root_volume", data.Identifier()) + helpers.Ensure("--namespace", data.Identifier(), "volume", "create", data.Identifier()) }, - { - description: "remove another namespace volume should fail", - command: func(tID string) *testutil.Cmd { - return otherBase.Cmd("volume", "remove", tID) + SubTests: []*test.Case{ + { + Description: "inspect another namespace volume should fail", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "inspect", data.Get("root_volume")) + }, + Expected: test.Expects(1, []error{ + errdefs.ErrNotFound, + }, nil), }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: errdefs.ErrNotFound.Error(), - } + { + Description: "removing another namespace volume should fail", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "remove", data.Get("root_volume")) + }, + Expected: test.Expects(1, []error{ + errdefs.ErrNotFound, + }, nil), }, - }, - { - description: "prune should leave other namespace untouched", - command: func(tID string) *testutil.Cmd { - return otherBase.Cmd("volume", "prune", "-a", "-f") - }, - tearDown: func(tID string) { - // Assert that the volume is here in the base namespace - // both before and after the prune command - base.Cmd("volume", "inspect", tID).AssertOK() - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, - } - }, - }, - { - description: "create with namespace should work", - command: func(tID string) *testutil.Cmd { - return thirdBase.Cmd("volume", "create", tID) + { + Description: "prune should leave another namespace volume untouched", + NoParallel: true, + Command: test.RunCommand("volume", "prune", "-a", "-f"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain(data.Get("root_volume")), + func(stdout string, info string, t *testing.T) { + helpers.Ensure("--namespace", data.Get("root_namespace"), "volume", "inspect", data.Get("root_volume")) + }, + ), + } + }, }, - tearDown: func(tID string) { - thirdBase.Cmd("volume", "remove", "-f", tID).Run() - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, - Out: tID, - } + { + Description: "create with the same name should work, then delete it", + NoParallel: true, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "create", data.Get("root_volume")) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", data.Get("root_volume")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + helpers.Ensure("volume", "inspect", data.Get("root_volume")) + helpers.Ensure("volume", "rm", data.Get("root_volume")) + helpers.Ensure("--namespace", data.Get("root_namespace"), "volume", "inspect", data.Get("root_volume")) + }, + } + }, }, }, } - for _, test := range testCases { - currentTest := test - t.Run(currentTest.description, func(tt *testing.T) { - if currentTest.dockerIncompatible { - testutil.DockerIncompatible(tt) - } - - tt.Parallel() - - // Note that here we are using the main test tID - // since we are testing against the volume created in it - if currentTest.tearDown != nil { - currentTest.tearDown(tID) - tt.Cleanup(func() { - currentTest.tearDown(tID) - }) - } - if currentTest.tearUp != nil { - currentTest.tearUp(tID) - } - - // See https://github.com/containerd/nerdctl/issues/3130 - // We run first to capture the underlying icmd command and output - cmd := currentTest.command(tID) - res := cmd.Run() - cmd.Assert(currentTest.expected(tID)) - if currentTest.inspect != nil { - currentTest.inspect(tt, res.Stdout(), res.Stderr()) - } - }) - } + tg.Run(t) } diff --git a/cmd/nerdctl/volume/volume_prune_linux_test.go b/cmd/nerdctl/volume/volume_prune_linux_test.go index 19632a73992..8898ad30ab4 100644 --- a/cmd/nerdctl/volume/volume_prune_linux_test.go +++ b/cmd/nerdctl/volume/volume_prune_linux_test.go @@ -20,130 +20,90 @@ import ( "strings" "testing" - "gotest.tools/v3/assert" - "gotest.tools/v3/icmd" - "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestVolumePrune(t *testing.T) { - // Volume pruning cannot be parallelized for Docker, since we need namespaces to do that in a way that does interact with other tests - if testutil.GetTarget() != testutil.Docker { - t.Parallel() - } + nerdtest.Setup() + + var setup = func(data test.Data, helpers test.Helpers) { + anonIDBusy := strings.TrimSpace(helpers.Capture("volume", "create")) + anonIDDangling := strings.TrimSpace(helpers.Capture("volume", "create")) + + namedBusy := data.Identifier() + "-busy" + namedDangling := data.Identifier() + "-free" - // FIXME: for an unknown reason, when testing ipv6, calling NewBaseWithNamespace per sub-test, in the tearDown/tearUp methods - // will actually panic the test (also happens with target=docker) - // Calling base here *first* so that it can skip NOW - does seem to workaround the problem - // If you have any idea how to properly do this, feel free to remove the following line and fix the underlying issue - testutil.NewBase(t) + helpers.Ensure("volume", "create", namedBusy) + helpers.Ensure("volume", "create", namedDangling) + helpers.Ensure("run", "--name", data.Identifier(), + "-v", namedBusy+":/whatever", + "-v", anonIDBusy+":/other", testutil.CommonImage) - subTearUp := func(tID string) { - base := testutil.NewBaseWithNamespace(t, tID) - res := base.Cmd("volume", "create").Run() - anonIDBusy := res.Stdout() - base.Cmd("volume", "create").Run() - base.Cmd("volume", "create", tID+"-busy").AssertOK() - base.Cmd("volume", "create", tID+"-free").AssertOK() - base.Cmd("run", "--name", tID, - "-v", tID+"-busy:/whatever", - "-v", anonIDBusy, testutil.CommonImage).AssertOK() + data.Set("anonIDBusy", anonIDBusy) + data.Set("anonIDDangling", anonIDDangling) + data.Set("namedBusy", namedBusy) + data.Set("namedDangling", namedDangling) } - subTearDown := func(tID string) { - base := testutil.NewBaseWithNamespace(t, tID) - base.Cmd("rm", "-f", tID).Run() - base.Cmd("namespace", "remove", "-f", tID).Run() + var cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("rm", "-f", data.Get("anonIDBusy")) + helpers.Anyhow("rm", "-f", data.Get("anonIDDangling")) + helpers.Anyhow("rm", "-f", data.Get("namedBusy")) + helpers.Anyhow("rm", "-f", data.Get("namedDangling")) } - testCases := []struct { - description string - command func(tID string) *testutil.Cmd - tearUp func(tID string) - tearDown func(tID string) - expected func(tID string) icmd.Expected - inspect func(t *testing.T, stdout string, stderr string) - dockerIncompatible bool - }{ + // This set must be marked as private, since we cannot prune without interacting with other tests. + testGroup := &test.Group{ { - description: "prune anonymous only", - command: func(tID string) *testutil.Cmd { - base := testutil.NewBaseWithNamespace(t, tID) - return base.Cmd("volume", "prune", "-f") - }, - tearUp: subTearUp, - tearDown: subTearDown, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, + Description: "prune anonymous only", + Require: nerdtest.Private, + Command: test.RunCommand("volume", "prune", "-f"), + Setup: setup, + Cleanup: cleanup, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain(data.Get("anonIDBusy")), + test.Contains(data.Get("anonIDDangling")), + test.DoesNotContain(data.Get("namedBusy")), + test.DoesNotContain(data.Get("namedDangling")), + func(stdout string, info string, t *testing.T) { + helpers.Ensure("volume", "inspect", data.Get("anonIDBusy")) + helpers.Fail("volume", "inspect", data.Get("anonIDDangling")) + helpers.Ensure("volume", "inspect", data.Get("namedBusy")) + helpers.Ensure("volume", "inspect", data.Get("namedDangling")) + }, + ), } }, - inspect: func(t *testing.T, stdout string, stderr string) { - tID := testutil.Identifier(t) - base := testutil.NewBaseWithNamespace(t, tID) - assert.Assert(base.T, !strings.Contains(stdout, tID+"-free")) - base.Cmd("volume", "inspect", tID+"-free").AssertOK() - assert.Assert(base.T, !strings.Contains(stdout, tID+"-busy")) - base.Cmd("volume", "inspect", tID+"-busy").AssertOK() - // TODO verify the anonymous volumes status - }, }, { - description: "prune all", - command: func(tID string) *testutil.Cmd { - base := testutil.NewBaseWithNamespace(t, tID) - return base.Cmd("volume", "prune", "-f", "--all") - }, - tearUp: subTearUp, - tearDown: subTearDown, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 0, + Description: "prune all", + Require: nerdtest.Private, + Command: test.RunCommand("volume", "prune", "-f", "--all"), + Setup: setup, + Cleanup: cleanup, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain(data.Get("anonIDBusy")), + test.Contains(data.Get("anonIDDangling")), + test.DoesNotContain(data.Get("namedBusy")), + test.Contains(data.Get("namedDangling")), + func(stdout string, info string, t *testing.T) { + helpers.Ensure("volume", "inspect", data.Get("anonIDBusy")) + helpers.Fail("volume", "inspect", data.Get("anonIDDangling")) + helpers.Ensure("volume", "inspect", data.Get("namedBusy")) + helpers.Fail("volume", "inspect", data.Get("namedDangling")) + }, + ), } }, - inspect: func(t *testing.T, stdout string, stderr string) { - tID := testutil.Identifier(t) - base := testutil.NewBaseWithNamespace(t, tID) - assert.Assert(t, !strings.Contains(stdout, tID+"-busy")) - base.Cmd("volume", "inspect", tID+"-busy").AssertOK() - assert.Assert(t, strings.Contains(stdout, tID+"-free")) - base.Cmd("volume", "inspect", tID+"-free").AssertFail() - // TODO verify the anonymous volumes status - }, }, } - for _, test := range testCases { - currentTest := test - t.Run(currentTest.description, func(tt *testing.T) { - if currentTest.dockerIncompatible { - testutil.DockerIncompatible(tt) - } - - if testutil.GetTarget() != testutil.Docker { - tt.Parallel() - } - - subTID := testutil.Identifier(tt) - - if currentTest.tearDown != nil { - currentTest.tearDown(subTID) - tt.Cleanup(func() { - currentTest.tearDown(subTID) - }) - } - if currentTest.tearUp != nil { - currentTest.tearUp(subTID) - } - - // See https://github.com/containerd/nerdctl/issues/3130 - // We run first to capture the underlying icmd command and output - cmd := currentTest.command(subTID) - res := cmd.Run() - cmd.Assert(currentTest.expected(subTID)) - if currentTest.inspect != nil { - currentTest.inspect(tt, res.Stdout(), res.Stderr()) - } - }) - } + testGroup.Run(t) } diff --git a/cmd/nerdctl/volume/volume_remove_linux_test.go b/cmd/nerdctl/volume/volume_remove_linux_test.go index 04c67a131aa..ba775614766 100644 --- a/cmd/nerdctl/volume/volume_remove_linux_test.go +++ b/cmd/nerdctl/volume/volume_remove_linux_test.go @@ -17,16 +17,17 @@ package volume import ( + "errors" "fmt" - "strings" "testing" "gotest.tools/v3/assert" - "gotest.tools/v3/icmd" "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) // TestVolumeRemove does test a large variety of volume remove situations, albeit none of them being @@ -34,91 +35,51 @@ import ( // Behavior in such cases is largely unspecified, as there is no easy way to compare with Docker. // Anyhow, borked filesystem conditions is not something we should be expected to deal with in a smart way. func TestVolumeRemove(t *testing.T) { - t.Parallel() - - base := testutil.NewBase(t) - - inUse := errdefs.ErrFailedPrecondition.Error() - malformed := errdefs.ErrInvalidArgument.Error() - notFound := errdefs.ErrNotFound.Error() - requireArg := "requires at least 1 arg" - if base.Target == testutil.Docker { - malformed = "no such volume" - notFound = "no such volume" - inUse = "volume is in use" - } + nerdtest.Setup() - testCases := []struct { - description string - command func(tID string) *testutil.Cmd - tearUp func(tID string) - tearDown func(tID string) - expected func(tID string) icmd.Expected - inspect func(t *testing.T, stdout string, stderr string) - dockerIncompatible bool - }{ + testGroup := &test.Group{ { - description: "arg missing should fail", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: requireArg, - } - }, + Description: "arg missing should fail", + Command: test.RunCommand("volume", "rm"), + Expected: test.Expects(1, []error{errors.New("requires at least 1 arg")}, nil), }, { - description: "invalid identifier should fail", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm", "∞") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: malformed, - } - }, + Description: "invalid identifier should fail", + Command: test.RunCommand("volume", "rm", "∞"), + Expected: test.Expects(1, []error{errdefs.ErrInvalidArgument}, nil), }, { - description: "non existent volume should fail", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm", "doesnotexist") - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: notFound, - } - }, + Description: "non existent volume should fail", + Command: test.RunCommand("volume", "rm", "doesnotexist"), + Expected: test.Expects(1, []error{errdefs.ErrNotFound}, nil), }, { - description: "busy volume should fail", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm", tID) - }, - tearUp: func(tID string) { - base.Cmd("volume", "create", tID).AssertOK() - base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID), "--name", tID, testutil.CommonImage).AssertOK() + Description: "busy volume should fail", + + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("volume", "create", data.Identifier()) + helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()), + "--name", data.Identifier(), testutil.CommonImage) }, - tearDown: func(tID string) { - base.Cmd("rm", "-f", tID).Run() - base.Cmd("volume", "rm", "-f", tID).Run() + + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "rm", data.Identifier()) }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: inUse, - } + Expected: test.Expects(1, []error{errdefs.ErrFailedPrecondition}, nil), + + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("volume", "rm", "-f", data.Identifier()) }, }, { - description: "busy anonymous volume should fail", - command: func(tID string) *testutil.Cmd { + Description: "busy anonymous volume should fail", + + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()), "--name", data.Identifier(), testutil.CommonImage) // Inspect the container and find the anonymous volume id - inspect := base.InspectContainer(tID) + inspect := nerdtest.InspectContainer(helpers, data.Identifier()) var anonName string for _, v := range inspect.Mounts { if v.Destination == "/volume" { @@ -127,162 +88,142 @@ func TestVolumeRemove(t *testing.T) { } } assert.Assert(t, anonName != "", "Failed to find anonymous volume id") + data.Set("anonName", anonName) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { // Try to remove that anon volume - return base.Cmd("volume", "rm", anonName) + return helpers.Command("volume", "rm", data.Get("anonName")) }, - tearUp: func(tID string) { - // base.Cmd("volume", "create", tID).AssertOK() - base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID), "--name", tID, testutil.CommonImage).AssertOK() - }, - tearDown: func(tID string) { - base.Cmd("rm", "-f", tID).Run() - }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - Err: inUse, - } + Expected: test.Expects(1, []error{errdefs.ErrFailedPrecondition}, nil), + + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) }, }, { - description: "freed volume should succeed", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm", tID) - }, - tearUp: func(tID string) { - base.Cmd("volume", "create", tID).AssertOK() - base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID), "--name", tID, testutil.CommonImage).AssertOK() - base.Cmd("rm", "-f", tID).AssertOK() + Description: "freed volume should succeed", + + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("volume", "create", data.Identifier()) + helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()), "--name", data.Identifier(), testutil.CommonImage) + helpers.Ensure("rm", "-f", data.Identifier()) }, - tearDown: func(tID string) { - base.Cmd("rm", "-f", tID).Run() - base.Cmd("volume", "rm", "-f", tID).Run() + + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "rm", data.Identifier()) }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - Out: tID, + + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Equals(data.Identifier() + "\n"), } }, + + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("volume", "rm", "-f", data.Identifier()) + }, }, { - description: "dangling volume should succeed", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm", tID) + Description: "dangling volume should succeed", + + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "rm", data.Identifier()) }, - tearUp: func(tID string) { - base.Cmd("volume", "create", tID).AssertOK() + + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("volume", "create", data.Identifier()) }, - tearDown: func(tID string) { - base.Cmd("volume", "rm", "-f", tID).Run() + + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Identifier()) }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - Out: tID, + + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Equals(data.Identifier() + "\n"), } }, }, { - description: "part success multi-remove", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm", "invalid∞", "nonexistent", tID+"-busy", tID) + Description: "part success multi-remove", + + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "rm", "invalid∞", "nonexistent", data.Identifier()+"-busy", data.Identifier()) }, - tearUp: func(tID string) { - base.Cmd("volume", "create", tID).AssertOK() - base.Cmd("volume", "create", tID+"-busy").AssertOK() - base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID+"-busy"), "--name", tID, testutil.CommonImage).AssertOK() + + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("volume", "create", data.Identifier()) + helpers.Ensure("volume", "create", data.Identifier()+"-busy") + helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()+"-busy"), "--name", data.Identifier(), testutil.CommonImage) }, - tearDown: func(tID string) { - base.Cmd("rm", "-f", tID).Run() - base.Cmd("volume", "rm", "-f", tID).Run() - base.Cmd("volume", "rm", "-f", tID+"-busy").Run() + + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("volume", "rm", "-f", data.Identifier()) + helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-busy") }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ + + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ ExitCode: 1, - Out: tID, + Errors: []error{ + errdefs.ErrNotFound, + errdefs.ErrFailedPrecondition, + errdefs.ErrInvalidArgument, + }, + Output: test.Equals(data.Identifier() + "\n"), } }, - inspect: func(t *testing.T, stdout string, stderr string) { - assert.Assert(t, strings.Contains(stderr, notFound)) - assert.Assert(t, strings.Contains(stderr, inUse)) - assert.Assert(t, strings.Contains(stderr, malformed)) - }, }, { - description: "success multi-remove", - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm", tID+"-1", tID+"-2") + Description: "success multi-remove", + + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "rm", data.Identifier()+"-1", data.Identifier()+"-2") }, - tearUp: func(tID string) { - base.Cmd("volume", "create", tID+"-1").AssertOK() - base.Cmd("volume", "create", tID+"-2").AssertOK() + + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("volume", "create", data.Identifier()+"-1") + helpers.Ensure("volume", "create", data.Identifier()+"-2") }, - tearDown: func(tID string) { - base.Cmd("volume", "rm", "-f", tID+"-1", tID+"-2").Run() + + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-1", data.Identifier()+"-2") }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - Out: tID + "-1\n" + tID + "-2", + + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Equals(data.Identifier() + "-1\n" + data.Identifier() + "-2" + "\n"), } }, }, { - description: "failing multi-remove", - tearUp: func(tID string) { - base.Cmd("volume", "create", tID+"-busy").AssertOK() - base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", tID+"-busy"), "--name", tID, testutil.CommonImage).AssertOK() - }, - tearDown: func(tID string) { - base.Cmd("rm", "-f", tID).Run() - base.Cmd("volume", "rm", "-f", tID+"-busy").Run() - }, - command: func(tID string) *testutil.Cmd { - return base.Cmd("volume", "rm", "invalid∞", "nonexistent", tID+"-busy") + Description: "failing multi-remove", + + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("volume", "create", data.Identifier()+"-busy") + helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()+"-busy"), "--name", data.Identifier(), testutil.CommonImage) }, - expected: func(tID string) icmd.Expected { - return icmd.Expected{ - ExitCode: 1, - } + + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-busy") }, - inspect: func(t *testing.T, stdout string, stderr string) { - assert.Assert(t, strings.Contains(stderr, notFound)) - assert.Assert(t, strings.Contains(stderr, inUse)) - assert.Assert(t, strings.Contains(stderr, malformed)) + + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("volume", "rm", "invalid∞", "nonexistent", data.Identifier()+"-busy") }, + + Expected: test.Expects(1, []error{ + errdefs.ErrNotFound, + errdefs.ErrFailedPrecondition, + errdefs.ErrInvalidArgument, + }, nil), }, } - for _, test := range testCases { - currentTest := test - t.Run(currentTest.description, func(tt *testing.T) { - if currentTest.dockerIncompatible { - testutil.DockerIncompatible(tt) - } - - tt.Parallel() - - tID := testutil.Identifier(tt) - - if currentTest.tearDown != nil { - currentTest.tearDown(tID) - tt.Cleanup(func() { - currentTest.tearDown(tID) - }) - } - if currentTest.tearUp != nil { - currentTest.tearUp(tID) - } - - // See https://github.com/containerd/nerdctl/issues/3130 - // We run first to capture the underlying icmd command and output - cmd := currentTest.command(tID) - res := cmd.Run() - cmd.Assert(currentTest.expected(tID)) - if currentTest.inspect != nil { - currentTest.inspect(tt, res.Stdout(), res.Stderr()) - } - }) - } + testGroup.Run(t) } From a74f0f3024748fb8a8263efd615970d97f67c13e Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 17 Sep 2024 21:45:09 -0700 Subject: [PATCH 0765/1066] Testtool initial documentation Signed-off-by: apostasie --- .github/workflows/test-canary.yml | 2 +- .github/workflows/test-kube.yml | 2 +- .github/workflows/test.yml | 6 +- README.md | 2 +- docs/{dev/testing.md => testing/README.md} | 5 + docs/testing/tools.md | 364 +++++++++++++++++++++ 6 files changed, 375 insertions(+), 6 deletions(-) rename docs/{dev/testing.md => testing/README.md} (94%) create mode 100644 docs/testing/tools.md diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 7c385edb236..d6ea18306fc 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -112,5 +112,5 @@ jobs: ctrdVersion: ${{ env.CONTAINERD_VERSION }} run: powershell hack/configure-windows-ci.ps1 - name: "Run integration tests" - # See https://github.com/containerd/nerdctl/blob/main/docs/dev/testing.md#about-parallelization + # See https://github.com/containerd/nerdctl/blob/main/docs/testing/README.md#about-parallelization run: go test -p 1 -v ./cmd/nerdctl/... diff --git a/.github/workflows/test-kube.yml b/.github/workflows/test-kube.yml index cb487898173..f42bb7945a0 100644 --- a/.github/workflows/test-kube.yml +++ b/.github/workflows/test-kube.yml @@ -22,7 +22,7 @@ jobs: with: fetch-depth: 1 - name: "Run Kubernetes integration tests" - # See https://github.com/containerd/nerdctl/blob/main/docs/dev/testing.md#about-parallelization + # See https://github.com/containerd/nerdctl/blob/main/docs/testing/README.md#about-parallelization run: | ./hack/build-integration-kubernetes.sh sudo ./_output/nerdctl exec nerdctl-test-control-plane bash -c -- 'export TMPDIR="$HOME"/tmp; mkdir -p "$TMPDIR"; cd /nerdctl-source; /usr/local/go/bin/go test -p 1 ./cmd/nerdctl/... -test.only-kubernetes' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f00e7c85a8d..1501b0fcebf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -290,7 +290,7 @@ jobs: timeout_minutes: 30 max_attempts: 2 retry_on: error - # See https://github.com/containerd/nerdctl/blob/main/docs/dev/testing.md#about-parallelization + # See https://github.com/containerd/nerdctl/blob/main/docs/testing/README.md#about-parallelization command: go test -p 1 -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon - name: "Ensure that the IPv6 integration test suite is compatible with Docker" uses: nick-fields/retry@v3 @@ -298,7 +298,7 @@ jobs: timeout_minutes: 30 max_attempts: 2 retry_on: error - # See https://github.com/containerd/nerdctl/blob/main/docs/dev/testing.md#about-parallelization + # See https://github.com/containerd/nerdctl/blob/main/docs/testing/README.md#about-parallelization command: go test -p 1 -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon -test.only-ipv6 test-integration-windows: @@ -332,7 +332,7 @@ jobs: run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" - # See https://github.com/containerd/nerdctl/blob/main/docs/dev/testing.md#about-parallelization + # See https://github.com/containerd/nerdctl/blob/main/docs/testing/README.md#about-parallelization run: go test -p 1 -v ./cmd/nerdctl/... test-integration-freebsd: diff --git a/README.md b/README.md index ef85dbd54f5..8076cd67446 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ Using `go install github.com/containerd/nerdctl/v2/cmd/nerdctl` is possible, but ### Testing -See [testing nerdctl](docs/dev/testing.md). +See [testing nerdctl](docs/testing/README.md). ### Contributing to nerdctl diff --git a/docs/dev/testing.md b/docs/testing/README.md similarity index 94% rename from docs/dev/testing.md rename to docs/testing/README.md index 190733cb59d..c5bddc99285 100644 --- a/docs/dev/testing.md +++ b/docs/testing/README.md @@ -1,5 +1,10 @@ # Testing nerdctl +This document covers basic usage of nerdctl testing tasks, and generic recommendations +and principles about writing tests. + +For more comprehensive information about nerdctl test tools, see [tools.md](tools.md). + ## Lint ``` diff --git a/docs/testing/tools.md b/docs/testing/tools.md new file mode 100644 index 00000000000..655306dc48b --- /dev/null +++ b/docs/testing/tools.md @@ -0,0 +1,364 @@ +# Nerdctl testing tools + +## Preamble + +The integration test suite in nerdctl is meant to apply to both nerdctl and docker, +and further support additional test properties to target specific contexts (ipv6, kube). + +Basic _usage_ is covered in the [testing docs](testing.md). + +This here covers how to write tests, leveraging nerdctl `pkg/testutil/test` +which has been specifically developed to take care of repetitive tasks, +protect the developer against unintended side effects across tests, and generally +encourage clear testing structure with good debug-ability and a relatively simple API for +most cases. + +## Using `test.Case` + +Starting from scratch, the simplest, basic structure of a new test is: + +```go +package main + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestMyThing(t *testing.T) { + nerdtest.Setup() + + // Declare your test + myTest := &test.Case{ + Description: "A first test", + // This is going to run `nerdctl info` (or `docker info`) + Command: test.RunCommand("info"), + // Verify the command exits with 0, and stdout contains the word `Kernel` + Expected: test.Expects(0, nil, test.Contains("Kernel")), + } + + // Run it + myTest.Run(t) +} +``` + +## Expectations + +There are a handful of helpers for "expectations". + +You already saw two (`test.Expects` and `test.Contains`): + +First, `test.Expects(exitCode int, errors []error, outputCompare Comparator)`, which is +convenient to quickly describe what you expect overall. + +`exitCode` is obvious. + +`errors` is a slice of go `error`, that allows you to compare what is seen on stderr +with existing errors (for example: `errdefs.ErrNotFound`), or more generally +any string you want to match. + +`outputCompare` can be either your own comparison function, or +one of the comparison helper. + +Secondly, `test.Contains`, is a `Comparator`. + +### Comparators + +Besides `test.Contains(string)`, there are a few more: +- `test.DoesNotContain(string)` +- `test.Equals(string)` +- `test.All(comparators ...Comparator)`, which allows you to bundle together a bunch of other comparators + +The following example shows how to implement your own custom `Comparator` +(this is actually the `Equals` comparator). + +```go +package whatever + +import ( + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func MyComparator(compare string) test.Comparator { + return func(stdout string, info string, t *testing.T) { + t.Helper() + assert.Assert(t, stdout == compare, info) + } +} +``` + +Note that you have access to an opaque `info` string. +It contains relevant debugging information in case your comparator is going to fail, +and you should make sure it is displayed. + +### Advanced expectations + +You may want to have expectations that contain a certain piece of data +that is being used in the command or at other stages of your test (Setup). + +For example, creating a container with a certain name, you might want to verify +that this name is then visible in the list of containers. + +To achieve that, you should write your own `Expecter`, leveraging test `Data`. + +Here is an example, where we are using `data.Get("sometestdata")`. + +```go +package main + +import ( + "errors" + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/errdefs" + + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestMyThing(t *testing.T) { + nerdtest.Setup() + + // Declare your test + myTest := &test.Case{ + Description: "A subtest with custom data, manager, and comparator", + Data: test.WithData("sometestdata", "blah"), + Command: test.RunCommand("info"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{ + errors.New("foobla"), + errdefs.ErrNotFound, + }, + Output: func(stdout string, info string, t *testing.T) { + assert.Assert(t, stdout == data.Get("sometestdata"), info) + }, + } + }, + } + + myTest.Run(t) +} +``` + +## On `Data` + +`Data` is provided to first allow storing mutable key-value information that pertain to the test. + +While it can be provided through `WithData(key string, value string)` (or `WithConfig`, see below), +inside the testcase definition, it can also be dynamically manipulated inside `Setup`, or `Command`. + +Note that `Data` additionally exposes the following functions: +- `Identifier()` which returns the unique id associated with the _current_ test (or subtest) +- `TempDir()` which returns the private, temporary directory associated with the test + +... along with the `Get(key)` and `Set(key, value)` methods. + +Secondly, `Data` allows defining and manipulating "configuration" data. + +In the case of nerdctl here, the following configuration options are defined: +- `WithConfig(Docker, NotCompatible)` to flag a test as not compatible +- `WithConfig(Mode, Private)` will entirely isolate the test using a different +namespace, data root, nerdctl config, etc +- `WithConfig(NerdctlToml, "foo")` which allows specifying a custom config +- `WithConfig(DataRoot, "foo")` allowing to point to a custom data-root +- `WithConfig(HostsDir, "foo")` to point to a specific hosts directory +- `WithConfig(Namespace, "foo")` allows passing a specific namespace (otherwise defaults to `nerdctl-test`) + +## Commands + +For simple cases, `test.RunCommand(args ...string)` is the way to go. + +It will execute the binary to test (nerdctl or docker), with the provided arguments, +and will by default get cwd inside the temporary directory associated with the test. + +### Environment + +You can attach custom environment variables for your test in the `Env` property of your +test. + +These will be automatically added to the environment for your command, and also +your setup and cleanup routines (see below). + +If you would like to override the environment specifically for a command, but not for +others (eg: in `Setup` or `Cleanup`), you can do so with custom commands (see below). + +Note that environment as defined statically in the test will be inherited by subtests, +unless explicitly overridden. + +### Working directory + +By default, the working directory of the command will be set to the temporary directory +of the test. + +This behavior can be overridden using custom commands. + +### Custom commands + +Custom commands allow you to manipulate test `Data`, override important aspects +of the command to execute (`Env`, `WorkingDir`), or otherwise give you full control +on what the command does. + +You just need to implement an `Executor`: + +```go +package main + +import ( + "errors" + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/errdefs" + + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestMyThing(t *testing.T) { + nerdtest.Setup() + + // Declare your test + myTest := &test.Case{ + Description: "A subtest with custom data, manager, and comparator", + Data: test.WithData("sometestdata", "blah"), + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("run", "--name", data.Identifier()+data.Get("sometestdata")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{ + errors.New("foobla"), + errdefs.ErrNotFound, + }, + Output: func(stdout string, info string, t *testing.T) { + assert.Assert(t, stdout == data.Get("sometestdata"), info) + }, + } + }, + } + + myTest.Run(t) +} +``` + +### On `helpers` + +Inside a custom `Executor`, `Manager`, or `Butler`, you have access to a collection of +`helpers` to simplify command execution: + +- `helpers.Ensure(args ...string)` will run a command and ensure it exits succesfully +- `helpers.Fail(args ...string)` will run a command and ensure it fails +- `helpers.Anyhow(args ...string)` will run a command but does not care if it succeeds or fails +- `helpers.Capture(args ...string)` will run a command, ensure it is successful, and return the output +- `helpers.Command(args ...string)` will return a command that can then be tested against expectations +- `helpers.CustomCommand(binary string, args ...string)` will do the same for any arbitrary command (not limited to nerdctl) + +## Setup and Cleanup + +Tests routinely require a set of actions to be performed _before_ you can run the +command you want to test. +A setup routine will get executed before your `Command`, and have access to and can +manipulate your test `Data`. + +Conversely, you very likely want to clean things up once your test is done. +While temporary directories are cleaned for you with no action needed on your part, +the app you are testing might have stateful data you may want to remove. +Note that a `Cleanup` routine will get executed twice - after your `Command` has run +its course evidently - but also, pre-emptively, before your `Setup`, so that possible leftovers from +previous runs are taken care of. + +```go +package main + +import ( + "errors" + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/errdefs" + + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestMyThing(t *testing.T) { + nerdtest.Setup() + + // Declare your test + myTest := &test.Case{ + Description: "A subtest with custom data, manager, and comparator", + Data: test.WithData("sometestdata", "blah"), + Setup: func(data *test.Data, helpers test.Helpers){ + helpers.Ensure("volume", "create", "foo") + helpers.Ensure("volume", "create", "bar") + }, + Cleanup: func(data *test.Data, helpers test.Helpers){ + helpers.Anyhow("volume", "rm", "foo") + helpers.Anyhow("volume", "rm", "bar") + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("run", "--name", data.Identifier()+data.Get("sometestdata")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{ + errors.New("foobla"), + errdefs.ErrNotFound, + }, + Output: func(stdout string, info string, t *testing.T) { + assert.Assert(t, stdout == data.Get("sometestdata"), info) + }, + } + }, + } + + myTest.Run(t) +} +``` + +## Subtests + +Subtests are just regular tests, attached to the `SubTests` slice of a test. + +Note that a subtest will inherit its parent `Data` and `Env`, in the state they are at +after the parent test has run its `Setup` and `Command` routines (but before `Cleanup`). +This does _not_ apply to `Identifier()` and `TempDir()`, which are unique to the sub-test. + +Also note that a test does not have to have a `Command`. +This is a convenient pattern if you just need a common `Setup` for a bunch of subtests. + +## Groups + +A `test.Group` is just a convenient way to represent a slice of tests. + +Note that unlike a `test.Case`, a group cannot define properties inherited by +subtests, nor `Setup` or `Cleanup` routines. + +- if you just have a bunch of subtests you want to run, put them in a `test.Group` +- if you want to have a global setup, or otherwise set a common property first for your subtests, use a `test.Case` with `SubTests` + +## Parallelism + +All tests (and subtests) are assumed to be parallelizable. + +You can force a specific `test.Case` to not be run in parallel though, +by setting its `NoParallel` property to `true`. + +Note that if you want better isolation, it is usually better to use +`WithConfig(nerdtest.Mode, nerdtest.Private)` instead. +This will keep the test parallel (for nerdctl), but isolate it in a different context. +For Docker (which does not support namespaces), it is equivalent to passing `NoParallel: true`. From b4f002ca8ab57cf38ba13216e3ec1d102426034a Mon Sep 17 00:00:00 2001 From: Shubharanshu Mahapatra Date: Mon, 23 Sep 2024 13:55:07 +0530 Subject: [PATCH 0766/1066] remove is shareable test Signed-off-by: Shubharanshu Mahapatra --- cmd/nerdctl/builder/builder_build_test.go | 30 ----------------------- 1 file changed, 30 deletions(-) diff --git a/cmd/nerdctl/builder/builder_build_test.go b/cmd/nerdctl/builder/builder_build_test.go index 92a0928ecae..6b9052f9d12 100644 --- a/cmd/nerdctl/builder/builder_build_test.go +++ b/cmd/nerdctl/builder/builder_build_test.go @@ -25,8 +25,6 @@ import ( "gotest.tools/v3/assert" - "github.com/containerd/platforms" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -56,34 +54,6 @@ CMD ["echo", "nerdctl-build-test-string"] base.Cmd("run", "--rm", ignoredImageNamed).AssertFail() } -func TestBuildIsShareableForCompatiblePlatform(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() - - dockerfile := fmt.Sprintf(`FROM %s -CMD ["echo", "nerdctl-build-test-string"] - `, testutil.CommonImage) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", buildCtx, "-t", imageName).AssertErrNotContains("tarball") - - d := platforms.DefaultSpec() - platformConfig := fmt.Sprintf("%s/%s", d.OS, d.Architecture) - base.Cmd("build", buildCtx, "-t", imageName, "--platform", platformConfig).AssertOK() - base.Cmd("build", buildCtx, "-t", imageName, "--platform", platformConfig, "--progress", "plain").AssertErrNotContains("tarball") - - n := platforms.Platform{OS: "linux", Architecture: "arm", Variant: ""} - if n.OS != d.OS && n.Architecture != d.Architecture { - notCompatiblePlatformConfig := fmt.Sprintf("%s/%s", n.OS, n.Architecture) - base.Cmd("build", buildCtx, "-t", imageName, "--platform", notCompatiblePlatformConfig).AssertOK() - base.Cmd("build", buildCtx, "-t", imageName, "--platform", notCompatiblePlatformConfig, "--progress", "plain").AssertErrContains("tarball") - } -} - // TestBuildBaseImage tests if an image can be built on the previously built image. // This isn't currently supported by nerdctl with BuildKit OCI worker. func TestBuildBaseImage(t *testing.T) { From 79067831947275dffc00763d372cff7c6b4fd70a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 22:06:08 +0000 Subject: [PATCH 0767/1066] build(deps): bump github.com/go-viper/mapstructure/v2 Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.2.0 to 2.2.1. - [Release notes](https://github.com/go-viper/mapstructure/releases) - [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md) - [Commits](https://github.com/go-viper/mapstructure/compare/v2.2.0...v2.2.1) --- updated-dependencies: - dependency-name: github.com/go-viper/mapstructure/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5c2b507bf9b..05c27916363 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( github.com/fatih/color v1.17.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/fsnotify/fsnotify v1.7.0 - github.com/go-viper/mapstructure/v2 v2.2.0 + github.com/go-viper/mapstructure/v2 v2.2.1 github.com/ipfs/go-cid v0.4.1 github.com/klauspost/compress v1.17.9 github.com/mattn/go-isatty v0.0.20 diff --git a/go.sum b/go.sum index e2ca9370ee4..4756932a0bb 100644 --- a/go.sum +++ b/go.sum @@ -123,8 +123,8 @@ github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7 github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.2.0 h1:zGE1Kaz78LVwzU0kOfZuqwKKiG1gLkHTZ/cZioHp9po= -github.com/go-viper/mapstructure/v2 v2.2.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= From 845902d658c21df17bc079509d4995b598a8f121 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 00:29:38 +0000 Subject: [PATCH 0768/1066] build(deps): bump github.com/klauspost/compress from 1.17.9 to 1.17.10 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.9 to 1.17.10. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.9...v1.17.10) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 05c27916363..a9ad22c1a96 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/ipfs/go-cid v0.4.1 - github.com/klauspost/compress v1.17.9 + github.com/klauspost/compress v1.17.10 github.com/mattn/go-isatty v0.0.20 github.com/moby/sys/mount v0.3.4 github.com/moby/sys/mountinfo v0.7.2 diff --git a/go.sum b/go.sum index 4756932a0bb..76cccef7005 100644 --- a/go.sum +++ b/go.sum @@ -174,8 +174,8 @@ github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCX github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= +github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= From 93b5999a2acb8be6c813ea550253a44569c87073 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 23 Sep 2024 18:19:02 -0700 Subject: [PATCH 0769/1066] Fix regression from #3446 purported to fix scenarios when people commit simultaneously. However, the lock required a stateDir, sourced from the container label, which does not exist if the container was not created by nerdctl (eg: Kube). This commit fix this, by making sure we have a stateDir label. Signed-off-by: apostasie --- pkg/cmd/container/commit.go | 2 +- pkg/cmd/container/remove.go | 23 +++++++++++++++++------ pkg/containerutil/lock.go | 17 +---------------- pkg/imgutil/commit/commit.go | 27 +++++++++++++++++++++++++-- 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/pkg/cmd/container/commit.go b/pkg/cmd/container/commit.go index 32f78d871be..45a16ac0227 100644 --- a/pkg/cmd/container/commit.go +++ b/pkg/cmd/container/commit.go @@ -57,7 +57,7 @@ func Commit(ctx context.Context, client *containerd.Client, rawRef string, req s if found.MatchCount > 1 { return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) } - imageID, err := commit.Commit(ctx, client, found.Container, opts) + imageID, err := commit.Commit(ctx, client, found.Container, opts, options.GOptions) if err != nil { return err } diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 5acc7465c5a..bc055945824 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -107,8 +107,23 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions return err } + // Get datastore + dataStore, err := clientutil.DataStore(globalOptions.DataRoot, globalOptions.Address) + if err != nil { + return err + } + + // Ensure we do have a stateDir label + stateDir := containerLabels[labels.StateDir] + if stateDir == "" { + stateDir, err = containerutil.ContainerStateDirPath(globalOptions.Namespace, dataStore, c.ID()) + if err != nil { + return err + } + } + // Lock the container state - lf, err := containerutil.Lock(ctx, c) + lf, err := containerutil.Lock(stateDir) if err != nil { return err } @@ -132,11 +147,7 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions if err != nil { return err } - // Get datastore - dataStore, err := clientutil.DataStore(globalOptions.DataRoot, globalOptions.Address) - if err != nil { - return err - } + // Get namestore nameStore, err := namestore.New(dataStore, containerNamespace) if err != nil { diff --git a/pkg/containerutil/lock.go b/pkg/containerutil/lock.go index 896f6f1f618..228b8790575 100644 --- a/pkg/containerutil/lock.go +++ b/pkg/containerutil/lock.go @@ -17,27 +17,12 @@ package containerutil import ( - "context" - "errors" "path/filepath" - "github.com/containerd/containerd/v2/client" - - "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/store" ) -func Lock(ctx context.Context, c client.Container) (store.Store, error) { - containerLabels, err := c.Labels(ctx) - if err != nil { - return nil, err - } - - stateDir := containerLabels[labels.StateDir] - if stateDir == "" { - return nil, errors.New("container is missing statedir label") - } - +func Lock(stateDir string) (store.Store, error) { stor, err := store.New(filepath.Join(stateDir, "oplock"), 0, 0) if err != nil { return nil, err diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index b504035dd22..70a48f81586 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -44,6 +44,8 @@ import ( "github.com/containerd/log" "github.com/containerd/platforms" + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/containerutil" imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" @@ -66,8 +68,29 @@ var ( emptyDigest = digest.Digest("") ) -func Commit(ctx context.Context, client *containerd.Client, container containerd.Container, opts *Opts) (digest.Digest, error) { - lf, err := containerutil.Lock(ctx, container) +func Commit(ctx context.Context, client *containerd.Client, container containerd.Container, opts *Opts, globalOptions types.GlobalCommandOptions) (digest.Digest, error) { + // Get labels + containerLabels, err := container.Labels(ctx) + if err != nil { + return emptyDigest, err + } + + // Get datastore + dataStore, err := clientutil.DataStore(globalOptions.DataRoot, globalOptions.Address) + if err != nil { + return emptyDigest, err + } + + // Ensure we do have a stateDir label + stateDir := containerLabels[labels.StateDir] + if stateDir == "" { + stateDir, err = containerutil.ContainerStateDirPath(globalOptions.Namespace, dataStore, container.ID()) + if err != nil { + return emptyDigest, err + } + } + + lf, err := containerutil.Lock(stateDir) if err != nil { return emptyDigest, err } From 9539f6b0267febe2d2ce7853a6a400f8b9791996 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 24 Sep 2024 21:17:28 -0700 Subject: [PATCH 0770/1066] Add fetch and EnsureAllContent methods Signed-off-by: apostasie --- pkg/cmd/image/ensure.go | 127 +++++++++++++++++++++++++++++++++++++ pkg/imgutil/fetch/fetch.go | 92 +++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 pkg/cmd/image/ensure.go create mode 100644 pkg/imgutil/fetch/fetch.go diff --git a/pkg/cmd/image/ensure.go b/pkg/cmd/image/ensure.go new file mode 100644 index 00000000000..7d5a2eec440 --- /dev/null +++ b/pkg/cmd/image/ensure.go @@ -0,0 +1,127 @@ +/* + 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 image + +import ( + "context" + "errors" + "fmt" + "net/http" + "os" + + distributionref "github.com/distribution/reference" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/log" + + "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/containerdutil" + "github.com/containerd/nerdctl/v2/pkg/errutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" + "github.com/containerd/nerdctl/v2/pkg/imgutil/fetch" + "github.com/containerd/nerdctl/v2/pkg/platformutil" +) + +func EnsureAllContent(ctx context.Context, client *containerd.Client, srcName string, options types.GlobalCommandOptions) error { + // Get the image from the srcName + imageService := client.ImageService() + img, err := imageService.Get(ctx, srcName) + if err != nil { + fmt.Println("Failed getting imageservice") + return err + } + + provider := containerdutil.NewProvider(client) + snapshotter := containerdutil.SnapshotService(client, options.Snapshotter) + // Read the image + imagesList, _ := read(ctx, provider, snapshotter, img.Target) + // Iterate through the list + for _, i := range imagesList { + err = ensureOne(ctx, client, srcName, img.Target, i.platform, options) + if err != nil { + return err + } + } + + return nil +} + +func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, target ocispec.Descriptor, platform ocispec.Platform, options types.GlobalCommandOptions) error { + + named, err := distributionref.ParseDockerRef(rawRef) + if err != nil { + return err + } + refDomain := distributionref.Domain(named) + // if platform == nil { + // platform = platforms.DefaultSpec() + //} + pltf := []ocispec.Platform{platform} + platformComparer := platformutil.NewMatchComparerFromOCISpecPlatformSlice(pltf) + + _, _, _, missing, err := images.Check(ctx, client.ContentStore(), target, platformComparer) + if err != nil { + return err + } + + if len(missing) > 0 { + // Get a resolver + var dOpts []dockerconfigresolver.Opt + if options.InsecureRegistry { + log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain) + dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) + } + dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(options.HostsDir)) + resolver, err := dockerconfigresolver.New(ctx, refDomain, dOpts...) + if err != nil { + return err + } + config := &fetch.Config{ + Resolver: resolver, + RemoteOpts: []containerd.RemoteOpt{}, + Platforms: pltf, + ProgressOutput: os.Stderr, + } + + err = fetch.Fetch(ctx, client, rawRef, config) + + if err != nil { + // In some circumstance (e.g. people just use 80 port to support pure http), the error will contain message like "dial tcp : connection refused". + if !errors.Is(err, http.ErrSchemeMismatch) && !errutil.IsErrConnectionRefused(err) { + return err + } + if options.InsecureRegistry { + log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", refDomain) + dOpts = append(dOpts, dockerconfigresolver.WithPlainHTTP(true)) + resolver, err = dockerconfigresolver.New(ctx, refDomain, dOpts...) + if err != nil { + return err + } + config.Resolver = resolver + return fetch.Fetch(ctx, client, rawRef, config) + } + log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain) + log.G(ctx).Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)") + } + + return err + } + + return nil +} diff --git a/pkg/imgutil/fetch/fetch.go b/pkg/imgutil/fetch/fetch.go new file mode 100644 index 00000000000..c9ab04f5533 --- /dev/null +++ b/pkg/imgutil/fetch/fetch.go @@ -0,0 +1,92 @@ +/* + 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 fetch + +import ( + "context" + "io" + + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/log" + + "github.com/containerd/nerdctl/v2/pkg/imgutil/jobs" + "github.com/containerd/nerdctl/v2/pkg/platformutil" +) + +// Config for content fetch +type Config struct { + // Resolver + Resolver remotes.Resolver + // ProgressOutput to display progress + ProgressOutput io.Writer + // RemoteOpts, e.g. containerd.WithPullUnpack. + // + // Regardless to RemoteOpts, the following opts are always set: + // WithResolver, WithImageHandler, WithSchema1Conversion + // + // RemoteOpts related to unpacking can be set only when len(Platforms) is 1. + RemoteOpts []containerd.RemoteOpt + Platforms []ocispec.Platform // empty for all-platforms +} + +func Fetch(ctx context.Context, client *containerd.Client, ref string, config *Config) error { + ongoing := jobs.New(ref) + + pctx, stopProgress := context.WithCancel(ctx) + progress := make(chan struct{}) + + go func() { + if config.ProgressOutput != nil { + // no progress bar, because it hides some debug logs + jobs.ShowProgress(pctx, ongoing, client.ContentStore(), config.ProgressOutput) + } + close(progress) + }() + + h := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { + if desc.MediaType != images.MediaTypeDockerSchema1Manifest { + ongoing.Add(desc) + } + return nil, nil + }) + + log.G(pctx).WithField("image", ref).Debug("fetching") + platformMC := platformutil.NewMatchComparerFromOCISpecPlatformSlice(config.Platforms) + opts := []containerd.RemoteOpt{ + containerd.WithResolver(config.Resolver), + containerd.WithImageHandler(h), + //nolint:staticcheck + containerd.WithSchema1Conversion, //lint:ignore SA1019 nerdctl should support schema1 as well. + containerd.WithPlatformMatcher(platformMC), + } + opts = append(opts, config.RemoteOpts...) + + // Note that client.Fetch does not unpack + _, err := client.Fetch(pctx, ref, opts...) + + stopProgress() + if err != nil { + return err + } + + <-progress + return nil +} From 8ba7ce7879cf0f32a6cc9828add91cb1defdfba9 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 24 Sep 2024 21:19:28 -0700 Subject: [PATCH 0771/1066] EnsureAllContent on commit Signed-off-by: apostasie --- pkg/imgutil/commit/commit.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/imgutil/commit/commit.go b/pkg/imgutil/commit/commit.go index 70a48f81586..101cf7987f5 100644 --- a/pkg/imgutil/commit/commit.go +++ b/pkg/imgutil/commit/commit.go @@ -46,6 +46,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/containerd/nerdctl/v2/pkg/containerutil" imgutil "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/labels" @@ -126,6 +127,13 @@ func Commit(ctx context.Context, client *containerd.Client, container containerd return emptyDigest, err } + // Ensure all the layers are here: https://github.com/containerd/nerdctl/issues/3425 + err = image.EnsureAllContent(ctx, client, baseImg.Name(), globalOptions) + if err != nil { + log.G(ctx).Warn("Unable to fetch missing layers before committing. " + + "If you try to save or push this image, it might fail. See https://github.com/containerd/nerdctl/issues/3439.") + } + if opts.Pause { task, err := container.Task(ctx, cio.Load) if err != nil { From ef09d191c9acb8fc8de8941468e8b3289b7ce2d2 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 24 Sep 2024 21:19:47 -0700 Subject: [PATCH 0772/1066] EnsureAllContent on convert Signed-off-by: apostasie --- pkg/cmd/image/convert.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/cmd/image/convert.go b/pkg/cmd/image/convert.go index d628c43158a..e320a421be2 100644 --- a/pkg/cmd/image/convert.go +++ b/pkg/cmd/image/convert.go @@ -75,6 +75,12 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa } convertOpts = append(convertOpts, converter.WithPlatform(platMC)) + // Ensure all the layers are here: https://github.com/containerd/nerdctl/issues/3425 + err = EnsureAllContent(ctx, client, srcRawRef, options.GOptions) + if err != nil { + return err + } + estargz := options.Estargz zstd := options.Zstd zstdchunked := options.ZstdChunked From 8e10d879970ac7327c11b3522e36d86ab3d85298 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 24 Sep 2024 21:20:05 -0700 Subject: [PATCH 0773/1066] EnsureAllContent on save Signed-off-by: apostasie --- pkg/cmd/image/save.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/cmd/image/save.go b/pkg/cmd/image/save.go index fc92e0b9eb9..815305ee80c 100644 --- a/pkg/cmd/image/save.go +++ b/pkg/cmd/image/save.go @@ -48,6 +48,13 @@ func Save(ctx context.Context, client *containerd.Client, images []string, optio if found.UniqueImages > 1 { return fmt.Errorf("ambiguous digest ID: multiple IDs found with provided prefix %s", found.Req) } + + // Ensure all the layers are here: https://github.com/containerd/nerdctl/issues/3425 + err = EnsureAllContent(ctx, client, found.Image.Name, options.GOptions) + if err != nil { + return err + } + imgName := found.Image.Name imgDigest := found.Image.Target.Digest.String() if _, ok := savedImages[imgDigest]; !ok { From 1e52bf526f6ea8797e6a323aee1e557cad346dbf Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 24 Sep 2024 21:21:53 -0700 Subject: [PATCH 0774/1066] EnsureAllContent on tag Signed-off-by: apostasie --- pkg/cmd/image/tag.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/pkg/cmd/image/tag.go b/pkg/cmd/image/tag.go index 48929d3694e..70f68acae84 100644 --- a/pkg/cmd/image/tag.go +++ b/pkg/cmd/image/tag.go @@ -22,6 +22,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/errdefs" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" @@ -31,7 +32,7 @@ import ( func Tag(ctx context.Context, client *containerd.Client, options types.ImageTagOptions) error { imageService := client.ImageService() var srcName string - imagewalker := &imagewalker.ImageWalker{ + walker := &imagewalker.ImageWalker{ Client: client, OnFound: func(ctx context.Context, found imagewalker.Found) error { if srcName == "" { @@ -40,7 +41,7 @@ func Tag(ctx context.Context, client *containerd.Client, options types.ImageTagO return nil }, } - matchCount, err := imagewalker.Walk(ctx, options.Source) + matchCount, err := walker.Walk(ctx, options.Source) if err != nil { return err } @@ -59,17 +60,25 @@ func Tag(ctx context.Context, client *containerd.Client, options types.ImageTagO } defer done(ctx) - image, err := imageService.Get(ctx, srcName) + // Ensure all the layers are here: https://github.com/containerd/nerdctl/issues/3425 + err = EnsureAllContent(ctx, client, srcName, options.GOptions) + if err != nil { + log.G(ctx).Warn("Unable to fetch missing layers before committing. " + + "If you try to save or push this image, it might fail. See https://github.com/containerd/nerdctl/issues/3439.") + } + + img, err := imageService.Get(ctx, srcName) if err != nil { return err } - image.Name = target.String() - if _, err = imageService.Create(ctx, image); err != nil { + + img.Name = target.String() + if _, err = imageService.Create(ctx, img); err != nil { if errdefs.IsAlreadyExists(err) { - if err = imageService.Delete(ctx, image.Name); err != nil { + if err = imageService.Delete(ctx, img.Name); err != nil { return err } - if _, err = imageService.Create(ctx, image); err != nil { + if _, err = imageService.Create(ctx, img); err != nil { return err } } else { From 764a2aa51f17461515fdb1fe0ead5a031df0b5e1 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 24 Sep 2024 21:23:04 -0700 Subject: [PATCH 0775/1066] Fix tests and add regression tests for #3425 Signed-off-by: apostasie --- .../container/container_commit_linux_test.go | 46 ++- cmd/nerdctl/image/image_inspect_test.go | 300 ++++++++++-------- cmd/nerdctl/image/image_list_test.go | 3 +- cmd/nerdctl/issues/issues_linux_test.go | 133 ++++++++ hack/build-integration-kubernetes.sh | 19 +- hack/kind.yaml | 2 + pkg/testutil/nerdtest/test.go | 14 + 7 files changed, 374 insertions(+), 143 deletions(-) create mode 100644 cmd/nerdctl/issues/issues_linux_test.go diff --git a/cmd/nerdctl/container/container_commit_linux_test.go b/cmd/nerdctl/container/container_commit_linux_test.go index 24c791d4f60..8a4af41fdcd 100644 --- a/cmd/nerdctl/container/container_commit_linux_test.go +++ b/cmd/nerdctl/container/container_commit_linux_test.go @@ -20,8 +20,6 @@ import ( "strings" "testing" - "gotest.tools/v3/icmd" - "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -35,12 +33,11 @@ It will regularly succeed or fail, making random PR fail the Kube check. func TestKubeCommitPush(t *testing.T) { t.Parallel() - t.Skip("Test that confirm that #827 is still broken is too flaky") - base := testutil.NewBaseForKubernetes(t) tID := testutil.Identifier(t) var containerID string + // var registryIP string setup := func() { testutil.KubectlHelper(base, "run", "--image", testutil.CommonImage, tID, "--", "sleep", "Inf"). @@ -55,10 +52,37 @@ func TestKubeCommitPush(t *testing.T) { cmd := testutil.KubectlHelper(base, "get", "pods", tID, "-o", "jsonpath={ .status.containerStatuses[0].containerID }") cmd.Run() containerID = strings.TrimPrefix(cmd.Out(), "containerd://") + + // This below is missing configuration to allow for plain http communication + // This is left here for future work to successfully start a registry usable in the cluster + /* + // Start a registry + testutil.KubectlHelper(base, "run", "--port", "5000", "--image", testutil.RegistryImageStable, "testregistry"). + AssertOK() + + testutil.KubectlHelper(base, "wait", "pod", "testregistry", "--for=condition=ready", "--timeout=1m"). + AssertOK() + + cmd = testutil.KubectlHelper(base, "get", "pods", tID, "-o", "jsonpath={ .status.hostIPs[0].ip }") + cmd.Run() + registryIP = cmd.Out() + + cmd = testutil.KubectlHelper(base, "apply", "-f", "-", fmt.Sprintf(`apiVersion: v1 + kind: ConfigMap + metadata: + name: local-registry + namespace: nerdctl-test + data: + localRegistryHosting.v1: | + host: "%s:5000" + help: "https://kind.sigs.k8s.io/docs/user/local-registry/" + `, registryIP)) + */ + } tearDown := func() { - testutil.KubectlHelper(base, "delete", "pod", "-f", tID).Run() + testutil.KubectlHelper(base, "delete", "pod", "--all").Run() } tearDown() @@ -66,15 +90,7 @@ func TestKubeCommitPush(t *testing.T) { setup() t.Run("test commit / push on Kube (https://github.com/containerd/nerdctl/issues/827)", func(t *testing.T) { - t.Log("This test is meant to verify that we can commit / push an image from a pod." + - "Currently, this is broken, hence the test assumes it will fail. Once the problem is fixed, we should just" + - "change the expectation to 'success'.") - - base.Cmd("commit", containerID, "registry.example.com/my-app:v1").AssertOK() - // See note above. - base.Cmd("push", "registry.example.com/my-app:v1").Assert(icmd.Expected{ - ExitCode: 1, - Err: "failed to create a tmp single-platform image", - }) + base.Cmd("commit", containerID, "testcommitsave").AssertOK() + base.Cmd("save", "testcommitsave").AssertOK() }) } diff --git a/cmd/nerdctl/image/image_inspect_test.go b/cmd/nerdctl/image/image_inspect_test.go index 14fcb90caf8..95154304d1c 100644 --- a/cmd/nerdctl/image/image_inspect_test.go +++ b/cmd/nerdctl/image/image_inspect_test.go @@ -26,69 +26,52 @@ import ( "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func TestImageInspectContainsSomeStuff(t *testing.T) { - base := testutil.NewBase(t) - - base.Cmd("pull", testutil.CommonImage).AssertOK() - inspect := base.InspectImage(testutil.CommonImage) - - assert.Assert(base.T, len(inspect.RootFS.Layers) > 0) - assert.Assert(base.T, inspect.RootFS.Type != "") - assert.Assert(base.T, inspect.Architecture != "") - assert.Assert(base.T, inspect.Size > 0) -} - -func TestImageInspectWithFormat(t *testing.T) { - base := testutil.NewBase(t) - - base.Cmd("pull", testutil.CommonImage).AssertOK() - - // test RawFormat support - base.Cmd("image", "inspect", testutil.CommonImage, "--format", "{{.Id}}").AssertOK() - - // test typedFormat support - base.Cmd("image", "inspect", testutil.CommonImage, "--format", "{{.ID}}").AssertOK() -} - -func inspectImageHelper(base *testutil.Base, identifier ...string) []dockercompat.Image { - args := append([]string{"image", "inspect"}, identifier...) - cmdResult := base.Cmd(args...).Run() - assert.Equal(base.T, cmdResult.ExitCode, 0) - var dc []dockercompat.Image - if err := json.Unmarshal([]byte(cmdResult.Stdout()), &dc); err != nil { - base.T.Fatal(err) +func TestImageInspectSimpleCases(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Description: "TestImageInspect", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + }, + SubTests: []*test.Case{ + { + Description: "Contains some stuff", + Command: test.RunCommand("image", "inspect", testutil.CommonImage), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Image + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Assert(t, len(dc[0].RootFS.Layers) > 0, info) + assert.Assert(t, dc[0].Architecture != "", info) + assert.Assert(t, dc[0].Size > 0, info) + }), + }, + { + Description: "RawFormat support (.Id)", + Command: test.RunCommand("image", "inspect", testutil.CommonImage, "--format", "{{.Id}}"), + Expected: test.Expects(0, nil, nil), + }, + { + Description: "typedFormat support (.ID)", + Command: test.RunCommand("image", "inspect", testutil.CommonImage, "--format", "{{.ID}}"), + Expected: test.Expects(0, nil, nil), + }, + }, } - return dc + + testCase.Run(t) } func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { - testutil.DockerIncompatible(t) + nerdtest.Setup() - if runtime.GOOS == "windows" { - t.Skip("Windows is not supported for this test right now") - } - - base := testutil.NewBase(t) - - // Overall, we need a clean slate before doing these lookups. - // More specifically, because we trigger https://github.com/containerd/nerdctl/issues/3016 - // we cannot do selective rmi, so, just nuke everything - ids := base.Cmd("image", "list", "-q").Out() - allIDs := strings.Split(ids, "\n") - for _, id := range allIDs { - id = strings.TrimSpace(id) - if id != "" { - base.Cmd("rmi", "-f", id).Run() - } - } - - base.Cmd("pull", "alpine", "--platform", "linux/amd64").AssertOK() - base.Cmd("pull", "busybox", "--platform", "linux/amd64").AssertOK() - base.Cmd("pull", "busybox:stable", "--platform", "linux/amd64").AssertOK() - base.Cmd("pull", "registry-1.docker.io/library/busybox", "--platform", "linux/amd64").AssertOK() - base.Cmd("pull", "registry-1.docker.io/library/busybox:stable", "--platform", "linux/amd64").AssertOK() + platform := runtime.GOOS + "/" + runtime.GOARCH tags := []string{ "", @@ -102,76 +85,141 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { "registry-1.docker.io/library/busybox", } - // Build reference values for comparison - reference := inspectImageHelper(base, "busybox") - assert.Equal(base.T, 1, len(reference)) - // Extract image sha - sha := strings.TrimPrefix(reference[0].RepoDigests[0], "busybox@sha256:") - - differentReference := inspectImageHelper(base, "alpine") - assert.Equal(base.T, 1, len(differentReference)) - - // Testing all name and tags variants - for _, name := range names { - for _, tag := range tags { - t.Logf("Testing %s", name+tag) - result := inspectImageHelper(base, name+tag) - assert.Equal(base.T, 1, len(result)) - assert.Equal(base.T, reference[0].ID, result[0].ID) - } - } - - // Testing all name and tags variants, with a digest - for _, name := range names { - for _, tag := range tags { - t.Logf("Testing %s", name+tag+"@"+sha) - result := inspectImageHelper(base, name+tag+"@sha256:"+sha) - assert.Equal(base.T, 1, len(result)) - assert.Equal(base.T, reference[0].ID, result[0].ID) - } - } - - // Testing repo digest and short digest with or without prefix - for _, id := range []string{"sha256:" + sha, sha, sha[0:8], "sha256:" + sha[0:8]} { - t.Logf("Testing %s", id) - result := inspectImageHelper(base, id) - assert.Equal(base.T, 1, len(result)) - assert.Equal(base.T, reference[0].ID, result[0].ID) + testCase := &test.Case{ + Description: "TestImageInspectDifferentValidReferencesForTheSameImage", + Require: test.Require( + test.Not(nerdtest.Docker), + test.Not(test.Windows), + // We need a clean slate + nerdtest.Private, + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "alpine", "--platform", platform) + helpers.Ensure("pull", "busybox", "--platform", platform) + helpers.Ensure("pull", "busybox:stable", "--platform", platform) + helpers.Ensure("pull", "registry-1.docker.io/library/busybox", "--platform", platform) + helpers.Ensure("pull", "registry-1.docker.io/library/busybox:stable", "--platform", platform) + }, + SubTests: []*test.Case{ + { + Description: "name and tags +/- sha combinations", + Command: test.RunCommand("image", "inspect", "busybox"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Image + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + reference := dc[0].ID + sha := strings.TrimPrefix(dc[0].RepoDigests[0], "busybox@sha256:") + + for _, name := range names { + for _, tag := range tags { + it := nerdtest.InspectImage(helpers, name+tag) + assert.Equal(t, it.ID, reference) + it = nerdtest.InspectImage(helpers, name+tag+"@sha256:"+sha) + assert.Equal(t, it.ID, reference) + } + } + }, + } + }, + }, + { + Description: "by digest, short or long, with or without prefix", + Command: test.RunCommand("image", "inspect", "busybox"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Image + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + reference := dc[0].ID + sha := strings.TrimPrefix(dc[0].RepoDigests[0], "busybox@sha256:") + + for _, id := range []string{"sha256:" + sha, sha, sha[0:8], "sha256:" + sha[0:8]} { + it := nerdtest.InspectImage(helpers, id) + assert.Equal(t, it.ID, reference) + } + + // Now, tag alpine with a short id + // Build reference values for comparison + alpine := nerdtest.InspectImage(helpers, "alpine") + + // Demonstrate image name precedence over digest lookup + // Using the shortened sha should no longer get busybox, but rather the newly tagged Alpine + helpers.Ensure("tag", "alpine", sha[0:8]) + it := nerdtest.InspectImage(helpers, sha[0:8]) + assert.Equal(t, it.ID, alpine.ID, alpine.ID+" vs "+it.ID) + }, + } + }, + }, + { + Description: "prove that wrong references with correct digest do not get resolved", + Command: test.RunCommand("image", "inspect", "busybox"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Image + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + sha := strings.TrimPrefix(dc[0].RepoDigests[0], "busybox@sha256:") + + for _, id := range []string{"doesnotexist", "doesnotexist:either", "busybox:bogustag"} { + cmd := helpers.Command("image", "inspect", id+"@sha256:"+sha) + cmd.Run(&test.Expected{ + Output: test.Equals(""), + }) + } + }, + } + }, + }, + { + Description: "prove that invalid reference return no result without crashing", + Command: test.RunCommand("image", "inspect", "busybox"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Image + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + + for _, id := range []string{"∞∞∞∞∞∞∞∞∞∞", "busybox:∞∞∞∞∞∞∞∞∞∞"} { + cmd := helpers.Command("image", "inspect", id) + cmd.Run(&test.Expected{ + Output: test.Equals(""), + }) + } + }, + } + }, + }, + { + Description: "retrieving multiple entries at once", + Command: test.RunCommand("image", "inspect", "busybox", "busybox", "busybox:stable"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Image + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 3, len(dc), "Unexpectedly did not get 3 results\n"+info) + reference := nerdtest.InspectImage(helpers, "busybox") + assert.Equal(t, dc[0].ID, reference.ID) + assert.Equal(t, dc[1].ID, reference.ID) + assert.Equal(t, dc[2].ID, reference.ID) + }, + } + }, + }, + }, } - // Demonstrate image name precedence over digest lookup - // Using the shortened sha should no longer get busybox, but rather the newly tagged Alpine - t.Logf("Testing (alpine tagged) %s", sha[0:8]) - // Tag a different image with the short id - base.Cmd("tag", "alpine", sha[0:8]).AssertOK() - result := inspectImageHelper(base, sha[0:8]) - assert.Equal(base.T, 1, len(result)) - assert.Equal(base.T, differentReference[0].ID, result[0].ID) - - // Prove that wrong references with an existing digest do not get retrieved when asking by digest - for _, id := range []string{"doesnotexist", "doesnotexist:either", "busybox:bogustag"} { - t.Logf("Testing %s", id+"@"+sha) - args := append([]string{"image", "inspect"}, id+"@"+sha) - cmdResult := base.Cmd(args...).Run() - assert.Equal(base.T, cmdResult.ExitCode, 0) - assert.Equal(base.T, cmdResult.Stdout(), "") - } - - // Prove that invalid reference return no result without crashing - for _, id := range []string{"∞∞∞∞∞∞∞∞∞∞", "busybox:∞∞∞∞∞∞∞∞∞∞"} { - t.Logf("Testing %s", id) - args := append([]string{"image", "inspect"}, id) - cmdResult := base.Cmd(args...).Run() - assert.Equal(base.T, cmdResult.ExitCode, 0) - assert.Equal(base.T, cmdResult.Stdout(), "") - } - - // Retrieving multiple entries at once - t.Logf("Testing %s", "busybox busybox busybox:stable") - result = inspectImageHelper(base, "busybox", "busybox", "busybox:stable") - assert.Equal(base.T, 3, len(result)) - assert.Equal(base.T, reference[0].ID, result[0].ID) - assert.Equal(base.T, reference[0].ID, result[1].ID) - assert.Equal(base.T, reference[0].ID, result[2].ID) - + testCase.Run(t) } diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index 72e902fa62b..93cd9a7965a 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -125,7 +125,8 @@ func TestImagesFilterDangling(t *testing.T) { testutil.RequiresBuild(t) testutil.RegisterBuildCacheCleanup(t) base := testutil.NewBase(t) - base.Cmd("images", "prune", "--all").AssertOK() + base.Cmd("container", "prune", "-f").AssertOK() + base.Cmd("image", "prune", "--all", "-f").AssertOK() dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-notag-string"] diff --git a/cmd/nerdctl/issues/issues_linux_test.go b/cmd/nerdctl/issues/issues_linux_test.go new file mode 100644 index 00000000000..72f68b707b5 --- /dev/null +++ b/cmd/nerdctl/issues/issues_linux_test.go @@ -0,0 +1,133 @@ +/* + 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 issues is meant to document testing for complex scenarios type of issues that cannot simply be ascribed +// to a specific package. +package issues + +import ( + "fmt" + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" + "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" +) + +func TestMain(m *testing.M) { + testutil.M(m) +} + +func TestIssue3425(t *testing.T) { + nerdtest.Setup() + + var registry *testregistry.RegistryServer + + testCase := &test.Case{ + Description: "TestIssue3425", + Setup: func(data test.Data, helpers test.Helpers) { + base := testutil.NewBase(t) + registry = testregistry.NewWithNoAuth(base, 0, false) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if registry != nil { + registry.Cleanup(nil) + } + }, + SubTests: []*test.Case{ + { + Description: "with tag", + Require: nerdtest.Private, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("image", "pull", testutil.CommonImage) + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage) + helpers.Ensure("image", "rm", "-f", testutil.CommonImage) + helpers.Ensure("image", "pull", testutil.CommonImage) + helpers.Ensure("tag", testutil.CommonImage, fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("rmi", "-f", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("push", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "with commit", + Require: nerdtest.Private, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("image", "pull", testutil.CommonImage) + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "touch", "/something") + helpers.Ensure("image", "rm", "-f", testutil.CommonImage) + helpers.Ensure("image", "pull", testutil.CommonImage) + helpers.Ensure("commit", data.Identifier(), fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("rmi", "-f", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("push", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "with save", + Require: nerdtest.Private, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("image", "pull", testutil.CommonImage) + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage) + helpers.Ensure("image", "rm", "-f", testutil.CommonImage) + helpers.Ensure("image", "pull", testutil.CommonImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("save", testutil.CommonImage) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "with convert", + Require: test.Require( + nerdtest.Private, + test.Not(test.Windows), + test.Not(nerdtest.Docker), + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("image", "pull", testutil.CommonImage) + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage) + helpers.Ensure("image", "rm", "-f", testutil.CommonImage) + helpers.Ensure("image", "pull", testutil.CommonImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("image", "convert", "--oci", "--estargz", testutil.CommonImage, data.Identifier()) + }, + Expected: test.Expects(0, nil, nil), + }, + }, + } + + testCase.Run(t) +} diff --git a/hack/build-integration-kubernetes.sh b/hack/build-integration-kubernetes.sh index 0fa32457b21..e41f13fcf7f 100755 --- a/hack/build-integration-kubernetes.sh +++ b/hack/build-integration-kubernetes.sh @@ -23,6 +23,7 @@ readonly root GO_VERSION=1.23 KIND_VERSION=v0.24.0 +CNI_PLUGINS_VERSION=v1.5.1 [ "$(uname -m)" == "aarch64" ] && GOARCH=arm64 || GOARCH=amd64 @@ -53,6 +54,19 @@ install::kubectl(){ host::install "$temp"/kubectl } +install::cni(){ + local version="$1" + local temp + temp="$(fs::mktemp "install")" + + http::get "$temp"/cni.tgz "https://github.com/containernetworking/plugins/releases/download/$version/cni-plugins-${GOOS:-linux}-${GOARCH:-amd64}-$version.tgz" + sudo mkdir -p /opt/cni/bin + sudo tar xzf "$temp"/cni.tgz -C /opt/cni/bin + mkdir -p ~/opt/cni/bin + tar xzf "$temp"/cni.tgz -C ~/opt/cni/bin + rm "$temp"/cni.tgz +} + exec::kind(){ local args=() [ ! "$_rootful" ] || args=(sudo env PATH="$PATH" KIND_EXPERIMENTAL_PROVIDER="$KIND_EXPERIMENTAL_PROVIDER") @@ -85,6 +99,9 @@ main(){ PATH=$(pwd)/_output:"$PATH" export PATH + # Add CNI plugins + install::cni "$CNI_PLUGINS_VERSION" + # 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 @@ -97,4 +114,4 @@ main(){ exec::kind create cluster --name nerdctl-test --config=./hack/kind.yaml } -main "$@" \ No newline at end of file +main "$@" diff --git a/hack/kind.yaml b/hack/kind.yaml index 1695fafdb88..c6439c02458 100644 --- a/hack/kind.yaml +++ b/hack/kind.yaml @@ -10,3 +10,5 @@ nodes: containerPath: /usr/local/go - hostPath: . containerPath: /nerdctl-source + - hostPath: /opt/cni + containerPath: /opt/cni diff --git a/pkg/testutil/nerdtest/test.go b/pkg/testutil/nerdtest/test.go index a2f7a5bd3c2..812ff08591d 100644 --- a/pkg/testutil/nerdtest/test.go +++ b/pkg/testutil/nerdtest/test.go @@ -170,6 +170,20 @@ func InspectNetwork(helpers test.Helpers, name string, args ...string) dockercom return dc[0] } +func InspectImage(helpers test.Helpers, name string) dockercompat.Image { + var dc []dockercompat.Image + cmd := helpers.Command("image", "inspect", name) + cmd.Run(&test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + }, + }) + return dc[0] +} + func nerdctlSetup(testCase *test.Case, t *testing.T) test.Command { t.Helper() From f363e6f04d05e08c8e5466cdb565656561b6225b Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 22 Sep 2024 11:07:02 -0700 Subject: [PATCH 0776/1066] Migrate system tests to new tooling Signed-off-by: apostasie --- .../system/system_events_linux_test.go | 128 +++++++--------- cmd/nerdctl/system/system_info_test.go | 69 +++++---- cmd/nerdctl/system/system_prune_linux_test.go | 144 +++++++++--------- 3 files changed, 174 insertions(+), 167 deletions(-) diff --git a/cmd/nerdctl/system/system_events_linux_test.go b/cmd/nerdctl/system/system_events_linux_test.go index 5838e710866..c12d0161576 100644 --- a/cmd/nerdctl/system/system_events_linux_test.go +++ b/cmd/nerdctl/system/system_events_linux_test.go @@ -17,96 +17,84 @@ package system import ( - "fmt" - "strings" "testing" "time" - "gotest.tools/v3/assert" - "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -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 testEventFilterExecutor(data test.Data, helpers test.Helpers) test.Command { + cmd := helpers.Command("events", "--filter", data.Get("filter"), "--format", "json") + cmd.Background(1 * time.Second) + helpers.Ensure("run", "--rm", testutil.CommonImage) + return cmd } func TestEventFilters(t *testing.T) { + nerdtest.Setup() - type testCase struct { - name string - args []string - nerdctlOut string - dockerOut string - dockerSkip bool - } - testCases := []testCase{ + testGroup := &test.Group{ { - name: "CapitializedFilter", - args: []string{"event=START"}, - nerdctlOut: "\"Status\":\"start\"", - dockerOut: "\"status\":\"start\"", - dockerSkip: true, + Description: "CapitalizedFilter", + Require: test.Not(nerdtest.Docker), + Command: testEventFilterExecutor, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("output")), + } + }, + Data: test.WithData("filter", "event=START"). + Set("output", "\"Status\":\"start\""), }, { - name: "StartEventFilter", - args: []string{"event=start"}, - nerdctlOut: "\"Status\":\"start\"", - dockerOut: "\"status\":\"start\"", - dockerSkip: false, + Description: "StartEventFilter", + Command: testEventFilterExecutor, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("output")), + } + }, + Data: test.WithData("filter", "event=start"). + Set("output", "tatus\":\"start\""), }, { - name: "UnsupportedEventFilter", - args: []string{"event=unknown"}, - nerdctlOut: "\"Status\":\"unknown\"", - dockerSkip: true, + Description: "UnsupportedEventFilter", + Require: test.Not(nerdtest.Docker), + Command: testEventFilterExecutor, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("output")), + } + }, + Data: test.WithData("filter", "event=unknown"). + Set("output", "\"Status\":\"unknown\""), }, { - name: "StatusFilter", - args: []string{"status=start"}, - nerdctlOut: "\"Status\":\"start\"", - dockerOut: "\"status\":\"start\"", - dockerSkip: false, + Description: "StatusFilter", + Command: testEventFilterExecutor, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("output")), + } + }, + Data: test.WithData("filter", "status=start"). + Set("output", "tatus\":\"start\""), }, { - name: "UnsupportedStatusFilter", - args: []string{"status=unknown"}, - nerdctlOut: "\"Status\":\"unknown\"", - dockerSkip: true, + Description: "UnsupportedStatusFilter", + Require: test.Not(nerdtest.Docker), + Command: testEventFilterExecutor, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("output")), + } + }, + Data: test.WithData("filter", "status=unknown"). + Set("output", "\"Status\":\"unknown\""), }, } - 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) - } - }) - } + testGroup.Run(t) } diff --git a/cmd/nerdctl/system/system_info_test.go b/cmd/nerdctl/system/system_info_test.go index 3a10033930d..3c8f5c252da 100644 --- a/cmd/nerdctl/system/system_info_test.go +++ b/cmd/nerdctl/system/system_info_test.go @@ -21,41 +21,56 @@ import ( "fmt" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func testInfoJSON(stdout string) error { - var info dockercompat.Info - if err := json.Unmarshal([]byte(stdout), &info); err != nil { - return err - } +func testInfoComparator(stdout string, info string, t *testing.T) { + var dinf dockercompat.Info + err := json.Unmarshal([]byte(stdout), &dinf) + assert.NilError(t, err, "failed to unmarshal stdout"+info) unameM := infoutil.UnameM() - if info.Architecture != unameM { - return fmt.Errorf("expected info.Architecture to be %q, got %q", unameM, info.Architecture) - } - return nil + assert.Assert(t, dinf.Architecture == unameM, fmt.Sprintf("expected info.Architecture to be %q, got %q", unameM, dinf.Architecture)+info) } func TestInfo(t *testing.T) { - base := testutil.NewBase(t) - base.Cmd("info", "--format", "{{json .}}").AssertOutWithFunc(testInfoJSON) -} + nerdtest.Setup() -func TestInfoConvenienceForm(t *testing.T) { - testutil.DockerIncompatible(t) // until https://github.com/docker/cli/pull/3355 gets merged - base := testutil.NewBase(t) - base.Cmd("info", "--format", "json").AssertOutWithFunc(testInfoJSON) -} - -func TestInfoWithNamespace(t *testing.T) { - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - base.Args = nil // unset "--namespace=nerdctl-test" - - base.Cmd("info").AssertOutContains("Namespace: default") + testGroup := &test.Group{ + { + Description: "info", + Command: test.RunCommand("info", "--format", "{{json .}}"), + Expected: test.Expects(0, nil, testInfoComparator), + }, + { + Description: "info convenience form", + Command: test.RunCommand("info", "--format", "json"), + Expected: test.Expects(0, nil, testInfoComparator), + }, + { + Description: "info with namespace", + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command().Clear().WithBinary("nerdctl").WithArgs("info") + }, + Expected: test.Expects(0, nil, test.Contains("Namespace: default")), + }, + { + Description: "info with namespace env var", + Env: map[string]string{ + "CONTAINERD_NAMESPACE": "test", + }, + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command().Clear().WithBinary("nerdctl").WithArgs("info") + }, + Expected: test.Expects(0, nil, test.Contains("Namespace: test")), + }, + } - base.Env = append(base.Env, "CONTAINERD_NAMESPACE=test") - base.Cmd("info").AssertOutContains("Namespace: test") + testGroup.Run(t) } diff --git a/cmd/nerdctl/system/system_prune_linux_test.go b/cmd/nerdctl/system/system_prune_linux_test.go index d792282398f..40d08f1beea 100644 --- a/cmd/nerdctl/system/system_prune_linux_test.go +++ b/cmd/nerdctl/system/system_prune_linux_test.go @@ -17,86 +17,90 @@ package system import ( - "bytes" "fmt" - "io" - "os" - "os/exec" "strings" "testing" - "github.com/containerd/log" + "gotest.tools/v3/assert" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestSystemPrune(t *testing.T) { - testutil.RequiresBuild(t) - // FIXME: using a dedicated namespace does not work with rootful (because of buildkit running) - // t.Parallel() - // namespaceID := testutil.Identifier(t) - // base := testutil.NewBaseWithNamespace(t, namespaceID) - base := testutil.NewBase(t) - base.Cmd("container", "prune", "-f").AssertOK() - base.Cmd("network", "prune", "-f").AssertOK() - base.Cmd("volume", "prune", "-f").AssertOK() - base.Cmd("image", "prune", "-f", "--all").AssertOK() - - nID := testutil.Identifier(t) - base.Cmd("network", "create", nID).AssertOK() - defer base.Cmd("network", "rm", nID).Run() - - vID := testutil.Identifier(t) - base.Cmd("volume", "create", vID).AssertOK() - defer base.Cmd("volume", "rm", vID).Run() - - vID2 := base.Cmd("volume", "create").Out() - defer base.Cmd("volume", "rm", vID2).Run() - - tID := testutil.Identifier(t) - base.Cmd("run", "-v", fmt.Sprintf("%s:/volume", vID), "--net", nID, - "--name", tID, testutil.CommonImage).AssertOK() - defer base.Cmd("rm", "-f", tID).Run() - - base.Cmd("ps", "-a").AssertOutContains(tID) - base.Cmd("images").AssertOutContains(testutil.ImageRepo(testutil.CommonImage)) - - base.Cmd("system", "prune", "-f", "--volumes", "--all").AssertOK() - base.Cmd("volume", "ls").AssertOutContains(vID) // docker system prune --all --volume does not prune named volume - base.Cmd("volume", "ls").AssertOutNotContains(vID2) // docker system prune --all --volume prune anonymous volume - base.Cmd("ps", "-a").AssertOutNotContains(tID) - base.Cmd("network", "ls").AssertOutNotContains(nID) - base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) - - if testutil.GetTarget() != testutil.Nerdctl { - t.Skip("test skipped for buildkitd is not available with docker-compatible tests") + nerdtest.Setup() + + testGroup := &test.Group{ + { + Description: "volume prune all success", + // Private because of prune evidently + Require: nerdtest.Private, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("volume", "create", data.Identifier()) + anonIdentifier := helpers.Capture("volume", "create") + helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()), + "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) + + data.Set("anonIdentifier", anonIdentifier) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + helpers.Anyhow("volume", "rm", data.Identifier()) + helpers.Anyhow("volume", "rm", data.Get("anonIdentifier")) + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.RunCommand("system", "prune", "-f", "--volumes", "--all"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + volumes := helpers.Capture("volume", "ls") + networks := helpers.Capture("network", "ls") + images := helpers.Capture("images") + containers := helpers.Capture("ps", "-a") + assert.Assert(t, strings.Contains(volumes, data.Identifier()), volumes) + assert.Assert(t, !strings.Contains(volumes, data.Get("anonIdentifier")), volumes) + assert.Assert(t, !strings.Contains(containers, data.Identifier()), containers) + assert.Assert(t, !strings.Contains(networks, data.Identifier()), networks) + assert.Assert(t, !strings.Contains(images, testutil.CommonImage), images) + }, + } + }, + }, + { + Description: "buildkit", + // FIXME: using a dedicated namespace does not work with rootful (because of buildkitd) + NoParallel: true, + // buildkitd is not available with docker + Require: test.Require(nerdtest.Build, test.Not(nerdtest.Docker)), + // FIXME: this test will happily say "green" even if the command actually fails to do its duty + // if there is nothing in the build cache. + // Ensure with setup here that we DO build something first + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("system", "prune", "-f", "--volumes", "--all") + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + buildctlBinary, err := buildkitutil.BuildctlBinary() + if err != nil { + t.Fatal(err) + } + + host, err := buildkitutil.GetBuildkitHost(testutil.Namespace) + if err != nil { + t.Fatal(err) + } + + buildctlArgs := buildkitutil.BuildctlBaseArgs(host) + buildctlArgs = append(buildctlArgs, "du") + + return helpers.CustomCommand(buildctlBinary, buildctlArgs...) + }, + Expected: test.Expects(0, nil, test.Contains("Total:\t\t0B")), + }, } - buildctlBinary, err := buildkitutil.BuildctlBinary() - if err != nil { - t.Fatal(err) - } - host, err := buildkitutil.GetBuildkitHost(testutil.Namespace) - if err != nil { - t.Fatal(err) - } - - buildctlArgs := buildkitutil.BuildctlBaseArgs(host) - buildctlArgs = append(buildctlArgs, "du") - log.L.Debugf("running %s %v", buildctlBinary, buildctlArgs) - buildctlCmd := exec.Command(buildctlBinary, buildctlArgs...) - buildctlCmd.Env = os.Environ() - stdout := bytes.NewBuffer(nil) - buildctlCmd.Stdout = stdout - if err := buildctlCmd.Run(); err != nil { - t.Fatal(err) - } - readAll, err := io.ReadAll(stdout) - if err != nil { - t.Fatal(err) - } - if !strings.Contains(string(readAll), "Total:\t\t0B") { - t.Errorf("buildkit cache is not pruned: %s", string(readAll)) - } + testGroup.Run(t) } From 36ab583296919c947508f049fa1e287afcd9e160 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 22 Sep 2024 11:07:14 -0700 Subject: [PATCH 0777/1066] Migrate network tests to new tooling Signed-off-by: apostasie --- .../network/network_create_linux_test.go | 131 +++++++----- cmd/nerdctl/network/network_inspect_test.go | 131 +++++++----- .../network/network_list_linux_test.go | 109 +++++----- .../network/network_prune_linux_test.go | 57 ++++-- .../network/network_remove_linux_test.go | 193 ++++++++++-------- 5 files changed, 373 insertions(+), 248 deletions(-) diff --git a/cmd/nerdctl/network/network_create_linux_test.go b/cmd/nerdctl/network/network_create_linux_test.go index adf61d67c11..ae590d94836 100644 --- a/cmd/nerdctl/network/network_create_linux_test.go +++ b/cmd/nerdctl/network/network_create_linux_test.go @@ -17,66 +17,93 @@ package network import ( - "fmt" "net" + "strings" "testing" "gotest.tools/v3/assert" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + ipv6helper "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func TestNetworkCreateWithMTU(t *testing.T) { - testNetwork := testutil.Identifier(t) - base := testutil.NewBase(t) - - args := []string{ - "network", "create", testNetwork, - "--driver", "bridge", "--opt", "com.docker.network.driver.mtu=9216", - } - base.Cmd(args...).AssertOK() - defer base.Cmd("network", "rm", testNetwork).AssertOK() - - base.Cmd("run", "--rm", "--net", testNetwork, testutil.AlpineImage, "ifconfig", "eth0").AssertOutContains("MTU:9216") -} - func TestNetworkCreate(t *testing.T) { - base := testutil.NewBase(t) - testNetwork := testutil.Identifier(t) - - base.Cmd("network", "create", testNetwork).AssertOK() - defer base.Cmd("network", "rm", testNetwork).AssertOK() - - net := base.InspectNetwork(testNetwork) - assert.Equal(t, len(net.IPAM.Config), 1) - - base.Cmd("run", "--rm", "--net", testNetwork, testutil.CommonImage, "ip", "route").AssertOutContains(net.IPAM.Config[0].Subnet) - - base.Cmd("network", "create", testNetwork+"-1").AssertOK() - defer base.Cmd("network", "rm", testNetwork+"-1").AssertOK() - - base.Cmd("run", "--rm", "--net", testNetwork+"-1", testutil.CommonImage, "ip", "route").AssertOutNotContains(net.IPAM.Config[0].Subnet) -} - -func TestNetworkCreateIPv6(t *testing.T) { - base := testutil.NewBaseWithIPv6Compatible(t) - testNetwork := testutil.Identifier(t) - - subnetStr := "2001:db8:8::/64" - _, subnet, err := net.ParseCIDR(subnetStr) - assert.Assert(t, err == nil) - - base.Cmd("network", "create", "--ipv6", "--subnet", subnetStr, testNetwork).AssertOK() - t.Cleanup(func() { - base.Cmd("network", "rm", testNetwork).Run() - }) + nerdtest.Setup() + + testGroup := &test.Group{ + { + Description: "Network create", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + netw := nerdtest.InspectNetwork(helpers, data.Identifier()) + assert.Equal(t, len(netw.IPAM.Config), 1) + data.Set("subnet", netw.IPAM.Config[0].Subnet) + + helpers.Ensure("network", "create", data.Identifier()+"-1") + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + helpers.Anyhow("network", "rm", data.Identifier()+"-1") + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + data.Set("container2", helpers.Capture("run", "--rm", "--net", data.Identifier()+"-1", testutil.AlpineImage, "ip", "route")) + return helpers.Command("run", "--rm", "--net", data.Identifier(), testutil.AlpineImage, "ip", "route") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Errors: nil, + Output: func(stdout string, info string, t *testing.T) { + assert.Assert(t, strings.Contains(stdout, data.Get("subnet")), info) + assert.Assert(t, !strings.Contains(data.Get("container2"), data.Get("subnet")), info) + }, + } + }, + }, + { + Description: "Network create with MTU", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier(), "--driver", "bridge", "--opt", "com.docker.network.driver.mtu=9216") + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("run", "--rm", "--net", data.Identifier(), testutil.AlpineImage, "ifconfig", "eth0") + }, + Expected: test.Expects(0, nil, test.Contains("MTU:9216")), + }, + { + Description: "Network create with ipv6", + Require: nerdtest.OnlyIPv6, + Setup: func(data test.Data, helpers test.Helpers) { + subnetStr := "2001:db8:8::/64" + data.Set("subnetStr", subnetStr) + _, _, err := net.ParseCIDR(subnetStr) + assert.Assert(t, err == nil) + + helpers.Ensure("network", "create", data.Identifier(), "--ipv6", "--subnet", subnetStr) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("run", "--rm", "--net", data.Identifier(), testutil.CommonImage, "ip", "addr", "show", "dev", "eth0") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + _, subnet, _ := net.ParseCIDR(data.Get("subnetStr")) + ip := ipv6helper.FindIPv6(stdout) + assert.Assert(t, subnet.Contains(ip), info) + }, + } + }, + }, + } - base.Cmd("run", "--rm", "--net", testNetwork, testutil.CommonImage, "ip", "addr", "show", "dev", "eth0").AssertOutWithFunc(func(stdout string) error { - ip := helpers.FindIPv6(stdout) - if subnet.Contains(ip) { - return nil - } - return fmt.Errorf("expected subnet %s include ip %s", subnet, ip) - }) + testGroup.Run(t) } diff --git a/cmd/nerdctl/network/network_inspect_test.go b/cmd/nerdctl/network/network_inspect_test.go index 1f91f09963e..4aa6147d063 100644 --- a/cmd/nerdctl/network/network_inspect_test.go +++ b/cmd/nerdctl/network/network_inspect_test.go @@ -17,78 +17,101 @@ package network import ( - "runtime" + "encoding/json" + "errors" "testing" "gotest.tools/v3/assert" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestNetworkInspect(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("IPAMConfig not implemented on Windows yet") - } + nerdtest.Setup() - testNetwork := testutil.Identifier(t) const ( testSubnet = "10.24.24.0/24" testGateway = "10.24.24.1" testIPRange = "10.24.24.0/25" ) - base := testutil.NewBase(t) - defer base.Cmd("network", "rm", testNetwork).Run() - - args := []string{ - "network", "create", "--label", "tag=testNetwork", "--subnet", testSubnet, - "--gateway", testGateway, "--ip-range", testIPRange, - testNetwork, - } - base.Cmd(args...).AssertOK() - got := base.InspectNetwork(testNetwork) - - assert.DeepEqual(base.T, testNetwork, got.Name) - - expectedLabels := map[string]string{ - "tag": "testNetwork", - } - assert.DeepEqual(base.T, expectedLabels, got.Labels) - - expectedIPAM := dockercompat.IPAM{ - Config: []dockercompat.IPAMConfig{ - { - Subnet: testSubnet, - Gateway: testGateway, - IPRange: testIPRange, + testGroup := &test.Group{ + { + Description: "Test network inspect", + // IPAMConfig is not implemented on Windows yet + Require: test.Not(test.Windows), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", "--label", "tag=testNetwork", "--subnet", testSubnet, + "--gateway", testGateway, "--ip-range", testIPRange, data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("network", "inspect", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + got := dc[0] + + assert.Equal(t, got.Name, data.Identifier(), info) + assert.Equal(t, got.Labels["tag"], "testNetwork", info) + assert.Equal(t, len(got.IPAM.Config), 1, info) + assert.Equal(t, got.IPAM.Config[0].Subnet, testSubnet, info) + assert.Equal(t, got.IPAM.Config[0].Gateway, testGateway, info) + assert.Equal(t, got.IPAM.Config[0].IPRange, testIPRange, info) + }, + } }, }, - } - assert.DeepEqual(base.T, expectedIPAM, got.IPAM) -} - -func TestNetworkWithNamespace(t *testing.T) { - testutil.DockerIncompatible(t) - - t.Parallel() - - tID := testutil.Identifier(t) - base := testutil.NewBase(t) - baseOther := testutil.NewBaseWithNamespace(t, tID) + { + Description: "Test network with namespace", + Require: test.Not(nerdtest.Docker), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + helpers.Anyhow("namespace", "remove", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("network", "create", data.Identifier()) + }, - tearDown := func() { - base.Cmd("network", "rm", tID).Run() - baseOther.Cmd("namespace", "remove", tID).Run() + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + cmd := helpers.Command().Clear().WithBinary("nerdctl").WithArgs("--namespace", data.Identifier()) + + cmd.Clone().WithArgs("network", "inspect", data.Identifier()).Run(&test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("no such network")}, + }) + + cmd.Clone().WithArgs("network", "remove", data.Identifier()).Run(&test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("no such network")}, + }) + + cmd.Clone().WithArgs("network", "ls").Run(&test.Expected{ + Output: test.DoesNotContain(data.Identifier()), + }) + + cmd.Clone().WithArgs("network", "prune", "-f").Run(&test.Expected{ + Output: test.DoesNotContain(data.Identifier()), + }) + }, + } + }, + }, } - tearDown() - t.Cleanup(tearDown) - - base.Cmd("network", "create", tID).AssertOK() - // Other namespace cannot inspect, prune, see, or remove this network - baseOther.Cmd("network", "inspect", tID).AssertFail() - baseOther.Cmd("network", "prune", "-f").AssertOutNotContains(tID) - baseOther.Cmd("network", "ls").AssertOutNotContains(tID) - baseOther.Cmd("network", "remove", tID).AssertFail() + testGroup.Run(t) } diff --git a/cmd/nerdctl/network/network_list_linux_test.go b/cmd/nerdctl/network/network_list_linux_test.go index 62927f04b3f..a9d2f0124eb 100644 --- a/cmd/nerdctl/network/network_list_linux_test.go +++ b/cmd/nerdctl/network/network_list_linux_test.go @@ -17,60 +17,77 @@ package network import ( - "errors" - "fmt" "strings" "testing" - "github.com/containerd/nerdctl/v2/pkg/testutil" + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestNetworkLsFilter(t *testing.T) { - t.Parallel() - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - - var net1, net2 = tID + "net-1", tID + "net-2" - var label1 = tID + "=label-1" - netID1 := base.Cmd("network", "create", "--label="+label1, net1).Out() - defer base.Cmd("network", "rm", "-f", netID1).Run() - - netID2 := base.Cmd("network", "create", net2).Out() - defer base.Cmd("network", "rm", "-f", netID2).Run() + nerdtest.Setup() - base.Cmd("network", "ls", "--quiet", "--filter", "label="+tID).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 1 { - return errors.New("expected at least 1 lines") - } - netNames := map[string]struct{}{ - netID1[:12]: {}, - } + testCase := &test.Case{ + Description: "Test network list", + Setup: func(data test.Data, helpers test.Helpers) { + data.Set("identifier", data.Identifier()) + data.Set("label", data.Identifier()+"=label-1") + data.Set("netID1", helpers.Capture("network", "create", "--label="+data.Get("label"), data.Identifier()+"-1")) + data.Set("netID2", helpers.Capture("network", "create", data.Identifier()+"-2")) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()+"-1") + helpers.Anyhow("network", "rm", data.Identifier()+"-2") + }, + SubTests: []*test.Case{ + { + Description: "filter label", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("network", "ls", "--quiet", "--filter", "label="+data.Get("label")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 1, info) + netNames := map[string]struct{}{ + data.Get("netID1")[:12]: {}, + } - for _, name := range lines { - _, ok := netNames[name] - if !ok { - return fmt.Errorf("unexpected netume %s found", name) - } - } - return nil - }) + for _, name := range lines { + _, ok := netNames[name] + assert.Assert(t, ok, info) + } + }, + } + }, + }, + { + Description: "filter name", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("network", "ls", "--quiet", "--filter", "name="+data.Get("identifier")+"-2") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 1, info) + netNames := map[string]struct{}{ + data.Get("netID2")[:12]: {}, + } - base.Cmd("network", "ls", "--quiet", "--filter", "name="+net2).AssertOutWithFunc(func(stdout string) error { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 1 { - return errors.New("expected at least 1 lines") - } - netNames := map[string]struct{}{ - netID2[:12]: {}, - } + for _, name := range lines { + _, ok := netNames[name] + assert.Assert(t, ok, info) + } + }, + } + }, + }, + }, + } - for _, name := range lines { - _, ok := netNames[name] - if !ok { - return fmt.Errorf("unexpected netume %s found", name) - } - } - return nil - }) + testCase.Run(t) } diff --git a/cmd/nerdctl/network/network_prune_linux_test.go b/cmd/nerdctl/network/network_prune_linux_test.go index cb137c4c68f..1692ac55053 100644 --- a/cmd/nerdctl/network/network_prune_linux_test.go +++ b/cmd/nerdctl/network/network_prune_linux_test.go @@ -20,19 +20,52 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestNetworkPrune(t *testing.T) { - base := testutil.NewBase(t) - testNetwork := testutil.Identifier(t) - base.Cmd("network", "create", testNetwork).AssertOK() - defer base.Cmd("network", "prune", "-f").Run() - - tID := testutil.Identifier(t) - base.Cmd("run", "-d", "--net", testNetwork, "--name", tID, testutil.NginxAlpineImage).AssertOK() - defer base.Cmd("rm", "-f", tID).Run() - - base.Cmd("network", "prune", "-f").AssertOutNotContains(testNetwork) - base.Cmd("stop", tID).AssertOK() - base.Cmd("network", "prune", "-f").AssertOutContains(testNetwork) + nerdtest.Setup() + + testGroup := &test.Group{ + { + Description: "Prune does not collect started container network", + Require: nerdtest.Private, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Command: test.RunCommand("network", "prune", "-f"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.DoesNotContain(data.Identifier()), + } + }, + }, + { + Description: "Prune does collect stopped container network", + Require: nerdtest.Private, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) + helpers.Ensure("stop", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Command: test.RunCommand("network", "prune", "-f"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Identifier()), + } + }, + }, + } + + testGroup.Run(t) } diff --git a/cmd/nerdctl/network/network_remove_linux_test.go b/cmd/nerdctl/network/network_remove_linux_test.go index 7b8acb7b4b8..9e5bbaf200a 100644 --- a/cmd/nerdctl/network/network_remove_linux_test.go +++ b/cmd/nerdctl/network/network_remove_linux_test.go @@ -17,99 +17,124 @@ package network import ( + "errors" "testing" "github.com/vishvananda/netlink" "gotest.tools/v3/assert" - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestNetworkRemove(t *testing.T) { - if rootlessutil.IsRootless() { - t.Skip("test skipped for remove rootless network") + nerdtest.Setup() + + testCase := &test.Case{ + Description: "TestNetworkRemove", + Require: test.Not(nerdtest.Rootless), + SubTests: []*test.Case{ + { + Description: "Simple network remove", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + data.Set("netID", nerdtest.InspectNetwork(helpers, data.Identifier()).ID) + helpers.Ensure("run", "--rm", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) + // Verity the network is here + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.NilError(t, err, "failed to find network br-"+data.Get("netID")[:12], "%v") + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("network", "rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.Error(t, err, "Link not found", info) + }, + } + }, + }, + { + Description: "Network remove when linked to container", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("network", "rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("is in use")}, + } + }, + }, + { + Description: "Network remove by id", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + data.Set("netID", nerdtest.InspectNetwork(helpers, data.Identifier()).ID) + helpers.Ensure("run", "--rm", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) + // Verity the network is here + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.NilError(t, err, "failed to find network br-"+data.Get("netID")[:12], "%v") + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("network", "rm", data.Get("netID")) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.Error(t, err, "Link not found", info) + }, + } + }, + }, + { + Description: "Network remove by short id", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + data.Set("netID", nerdtest.InspectNetwork(helpers, data.Identifier()).ID) + helpers.Ensure("run", "--rm", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) + // Verity the network is here + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.NilError(t, err, "failed to find network br-"+data.Get("netID")[:12], "%v") + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("network", "rm", data.Get("netID")[:12]) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.Error(t, err, "Link not found", info) + }, + } + }, + }, + }, } - base := testutil.NewBase(t) - networkName := testutil.Identifier(t) - base.Cmd("network", "create", networkName).AssertOK() - defer base.Cmd("network", "rm", networkName).Run() - - networkID := base.InspectNetwork(networkName).ID - - tID := testutil.Identifier(t) - base.Cmd("run", "--rm", "--net", networkName, "--name", tID, testutil.CommonImage).AssertOK() - - _, err := netlink.LinkByName("br-" + networkID[:12]) - assert.NilError(t, err) - - base.Cmd("network", "rm", networkName).AssertOK() - - _, err = netlink.LinkByName("br-" + networkID[:12]) - assert.Error(t, err, "Link not found") -} - -func TestNetworkRemoveWhenLinkWithContainer(t *testing.T) { - if rootlessutil.IsRootless() { - t.Skip("test skipped for remove rootless network") - } - base := testutil.NewBase(t) - networkName := testutil.Identifier(t) - - base.Cmd("network", "create", networkName).AssertOK() - defer base.Cmd("network", "rm", networkName).AssertOK() - - tID := testutil.Identifier(t) - base.Cmd("run", "-d", "--net", networkName, "--name", tID, testutil.AlpineImage, "sleep", "infinity").AssertOK() - defer base.Cmd("rm", "-f", tID).Run() - base.Cmd("network", "rm", networkName).AssertFail() -} - -func TestNetworkRemoveById(t *testing.T) { - if rootlessutil.IsRootless() { - t.Skip("test skipped for remove rootless network") - } - base := testutil.NewBase(t) - networkName := testutil.Identifier(t) - - base.Cmd("network", "create", networkName).AssertOK() - defer base.Cmd("network", "rm", networkName).Run() - - networkID := base.InspectNetwork(networkName).ID - - tID := testutil.Identifier(t) - base.Cmd("run", "--rm", "--net", networkName, "--name", tID, testutil.CommonImage).AssertOK() - - _, err := netlink.LinkByName("br-" + networkID[:12]) - assert.NilError(t, err) - - base.Cmd("network", "rm", networkID).AssertOK() - - _, err = netlink.LinkByName("br-" + networkID[:12]) - assert.Error(t, err, "Link not found") -} - -func TestNetworkRemoveByShortId(t *testing.T) { - if rootlessutil.IsRootless() { - t.Skip("test skipped for remove rootless network") - } - base := testutil.NewBase(t) - networkName := testutil.Identifier(t) - - base.Cmd("network", "create", networkName).AssertOK() - defer base.Cmd("network", "rm", networkName).Run() - - networkID := base.InspectNetwork(networkName).ID - - tID := testutil.Identifier(t) - base.Cmd("run", "--rm", "--net", networkName, "--name", tID, testutil.CommonImage).AssertOK() - - _, err := netlink.LinkByName("br-" + networkID[:12]) - assert.NilError(t, err) - - base.Cmd("network", "rm", networkID[:12]).AssertOK() - - _, err = netlink.LinkByName("br-" + networkID[:12]) - assert.Error(t, err, "Link not found") + testCase.Run(t) } From 0aef2f2e4956a1023d680e58f94e65c5eb328aed Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 22 Sep 2024 11:07:28 -0700 Subject: [PATCH 0778/1066] Migrate completion tests to new tooling Signed-off-by: apostasie --- .../completion/completion_linux_test.go | 224 ++++++++++++++---- 1 file changed, 180 insertions(+), 44 deletions(-) diff --git a/cmd/nerdctl/completion/completion_linux_test.go b/cmd/nerdctl/completion/completion_linux_test.go index 8abb5483964..234c9a21ebc 100644 --- a/cmd/nerdctl/completion/completion_linux_test.go +++ b/cmd/nerdctl/completion/completion_linux_test.go @@ -20,53 +20,189 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestCompletion(t *testing.T) { - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - const gsc = "__complete" - // cmd is executed with base.Args={"--namespace=nerdctl-test"} - base.Cmd(gsc, "--cgroup-manager", "").AssertOutContains("cgroupfs\n") - base.Cmd(gsc, "--snapshotter", "").AssertOutContains("native\n") - base.Cmd(gsc, "").AssertOutContains("run\t") - base.Cmd(gsc, "run", "-").AssertOutContains("--network\t") - base.Cmd(gsc, "run", "--n").AssertOutContains("--network\t") - base.Cmd(gsc, "run", "--ne").AssertOutContains("--network\t") - base.Cmd(gsc, "run", "--net", "").AssertOutContains("host\n") - base.Cmd(gsc, "run", "-it", "--net", "").AssertOutContains("host\n") - base.Cmd(gsc, "run", "-it", "--rm", "--net", "").AssertOutContains("host\n") - base.Cmd(gsc, "run", "--restart", "").AssertOutContains("always\n") - base.Cmd(gsc, "network", "rm", "").AssertOutNotContains("host\n") // host is unremovable - base.Cmd(gsc, "run", "--cap-add", "").AssertOutContains("sys_admin\n") - base.Cmd(gsc, "run", "--cap-add", "").AssertOutNotContains("CAP_SYS_ADMIN\n") // invalid form + nerdtest.Setup() - // Tests with an image - base.Cmd("pull", testutil.AlpineImage).AssertOK() - base.Cmd(gsc, "run", "-i", "").AssertOutContains(testutil.AlpineImage) - base.Cmd(gsc, "run", "-it", "").AssertOutContains(testutil.AlpineImage) - base.Cmd(gsc, "run", "-it", "--rm", "").AssertOutContains(testutil.AlpineImage) + testCase := &test.Case{ + Description: "Base completion", + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.AlpineImage) + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("volume", "create", data.Identifier()) + data.Set("identifier", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + helpers.Anyhow("volume", "rm", data.Identifier()) + }, + SubTests: []*test.Case{ + { + Description: "--cgroup-manager", + Command: test.RunCommand("__complete", "--cgroup-manager", ""), + Expected: test.Expects(0, nil, test.Contains("cgroupfs\n")), + }, + { + Description: "--snapshotter", + Command: test.RunCommand("__complete", "--snapshotter", ""), + Expected: test.Expects(0, nil, test.Contains("native\n")), + }, + { + Description: "empty", + Command: test.RunCommand("__complete", ""), + Expected: test.Expects(0, nil, test.Contains("run\t")), + }, + { + Description: "run -", + Command: test.RunCommand("__complete", "run", "-"), + Expected: test.Expects(0, nil, test.Contains("--network\t")), + }, + { + Description: "run --n", + Command: test.RunCommand("__complete", "run", "--n"), + Expected: test.Expects(0, nil, test.Contains("--network\t")), + }, + { + Description: "run --ne", + Command: test.RunCommand("__complete", "run", "--ne"), + Expected: test.Expects(0, nil, test.Contains("--network\t")), + }, + { + Description: "run --net", + Command: test.RunCommand("__complete", "run", "--net", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains("host\n"), + test.Contains(data.Get("identifier")+"\n"), + ), + } + }, + }, + { + Description: "run -it --net", + Command: test.RunCommand("__complete", "run", "-it", "--net", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains("host\n"), + test.Contains(data.Get("identifier")+"\n"), + ), + } + }, + }, + { + Description: "run -ti --rm --net", + Command: test.RunCommand("__complete", "run", "-it", "--rm", "--net", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains("host\n"), + test.Contains(data.Get("identifier")+"\n"), + ), + } + }, + }, + { + Description: "run --restart", + Command: test.RunCommand("__complete", "run", "--restart", ""), + Expected: test.Expects(0, nil, test.Contains("always\n")), + }, + { + Description: "network --rm", + Command: test.RunCommand("__complete", "network", "rm", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain("host\n"), + test.Contains(data.Get("identifier")+"\n"), + ), + } + }, + }, + { + Description: "run --cap-add", + Command: test.RunCommand("__complete", "run", "--cap-add", ""), + Expected: test.Expects(0, nil, test.All( + test.Contains("sys_admin\n"), + test.DoesNotContain("CAP_SYS_ADMIN\n"), + )), + }, + { + Description: "volume inspect", + Command: test.RunCommand("__complete", "volume", "inspect", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("identifier") + "\n"), + } + }, + }, + { + Description: "volume rm", + Command: test.RunCommand("__complete", "volume", "rm", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("identifier") + "\n"), + } + }, + }, + { + Description: "no namespace --cgroup-manager", + Command: func(data test.Data, helpers test.Helpers) test.Command { + cmd := helpers.Command() + cmd.Clear() + cmd.WithBinary("nerdctl") + cmd.WithArgs("__complete", "--cgroup-manager", "") + return cmd + }, + Expected: test.Expects(0, nil, test.Contains("cgroupfs\n")), + }, + { + Description: "no namespace empty", + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command().Clear().WithBinary("nerdctl").WithArgs("__complete", "") + }, + Expected: test.Expects(0, nil, test.Contains("run\t")), + }, + { + Description: "namespace space empty", + Command: func(data test.Data, helpers test.Helpers) test.Command { + // mind {"--namespace=nerdctl-test"} vs {"--namespace", "nerdctl-test"} + return helpers.Command().Clear().WithBinary("nerdctl"). + WithArgs("__complete", "--namespace", testutil.Namespace, "") + }, + Expected: test.Expects(0, nil, test.Contains("run\t")), + }, + { + Description: "run -i", + Command: test.RunCommand("__complete", "run", "-i", ""), + Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage)), + }, + { + Description: "run -it", + Command: test.RunCommand("__complete", "run", "-it", ""), + Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage)), + }, + { + Description: "run -it --rm", + Command: test.RunCommand("__complete", "run", "-it", "--rm", ""), + Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage)), + }, + { + Description: "namespace run -i", + Command: func(data test.Data, helpers test.Helpers) test.Command { + // mind {"--namespace=nerdctl-test"} vs {"--namespace", "nerdctl-test"} + return helpers.Command().Clear().WithBinary("nerdctl"). + WithArgs("__complete", "--namespace", testutil.Namespace, "run", "-i", "") + }, + Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage+"\n")), + }, + }, + } - // Tests with a network - testNetworkName := "nerdctl-test-completion" - defer base.Cmd("network", "rm", testNetworkName).Run() - base.Cmd("network", "create", testNetworkName).AssertOK() - base.Cmd(gsc, "network", "rm", "").AssertOutContains(testNetworkName) - base.Cmd(gsc, "run", "--net", "").AssertOutContains(testNetworkName) - - // Tests with a volume - testVolumekName := "nerdctl-test-completion" - defer base.Cmd("volume", "rm", testVolumekName).Run() - base.Cmd("volume", "create", testVolumekName).AssertOK() - base.Cmd(gsc, "volume", "inspect", "").AssertOutContains(testVolumekName) - base.Cmd(gsc, "volume", "rm", "").AssertOutContains(testVolumekName) - - // Tests with raw base (without Args={"--namespace=nerdctl-test"}) - rawBase := testutil.NewBase(t) - rawBase.Args = nil // unset "--namespace=nerdctl-test" - rawBase.Cmd(gsc, "--cgroup-manager", "").AssertOutContains("cgroupfs\n") - rawBase.Cmd(gsc, "").AssertOutContains("run\t") - // mind {"--namespace=nerdctl-test"} vs {"--namespace", "nerdctl-test"} - rawBase.Cmd(gsc, "--namespace", testutil.Namespace, "").AssertOutContains("run\t") - rawBase.Cmd(gsc, "--namespace", testutil.Namespace, "run", "-i", "").AssertOutContains(testutil.AlpineImage) + testCase.Run(t) } From f231be8ebd8007b80d80094e714b0659bc664c05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Sep 2024 22:23:24 +0000 Subject: [PATCH 0779/1066] build(deps): bump actions/checkout from 4.1.7 to 4.2.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 4.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.7...v4.2.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/project.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test-canary.yml | 8 ++++---- .github/workflows/test-kube.yml | 2 +- .github/workflows/test.yml | 20 +++++++++---------- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 4227fb6a228..a4fe5259f56 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.0 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml index fa53effc688..d9de8b3114e 100644 --- a/.github/workflows/project.yml +++ b/.github/workflows/project.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d46f8827757..71c30eb3b9f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 - uses: actions/setup-go@v5 with: go-version: 1.23.x diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index d6ea18306fc..37dfd898fd7 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -19,7 +19,7 @@ jobs: runs-on: "ubuntu-24.04" timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - name: Set GO env @@ -40,7 +40,7 @@ jobs: runs-on: "ubuntu-24.04" timeout-minutes: 40 steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -74,7 +74,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - name: Set GO env @@ -97,7 +97,7 @@ jobs: - run: go install ./cmd/nerdctl # This here is solely to get the cni install script, which has not been modified in 3+ years. # There is little to no reason to update this to latest containerd - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: repository: containerd/containerd ref: "v1.7.19" diff --git a/.github/workflows/test-kube.yml b/.github/workflows/test-kube.yml index f42bb7945a0..d76ea903ca0 100644 --- a/.github/workflows/test-kube.yml +++ b/.github/workflows/test-kube.yml @@ -18,7 +18,7 @@ jobs: runs-on: "ubuntu-24.04" timeout-minutes: 40 steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - name: "Run Kubernetes integration tests" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1501b0fcebf..1936fb6885e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -78,7 +78,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -120,7 +120,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - name: Enable ipv4 and ipv6 forwarding @@ -207,7 +207,7 @@ jobs: } EOT sudo systemctl restart apparmor.service - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -244,7 +244,7 @@ jobs: matrix: go-version: ["1.22.x", "1.23.x"] steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -259,7 +259,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -308,7 +308,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -317,7 +317,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 with: repository: containerd/containerd ref: v1.7.19 @@ -342,7 +342,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.0 - uses: actions/cache@v4 with: path: /root/.vagrant.d From 2a8d4ae07bdfd42d6e61006d42e8be146b7a256f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:37:09 +0000 Subject: [PATCH 0780/1066] build(deps): bump docker/build-push-action from 6.7.0 to 6.8.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.7.0 to 6.8.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.7.0...v6.8.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index a4fe5259f56..6488ec23fd7 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.7.0 + uses: docker/build-push-action@v6.8.0 with: context: . platforms: linux/amd64,linux/arm64 From 12e63b5d5219ddd3b4a62f56960c0f69caaafd83 Mon Sep 17 00:00:00 2001 From: xyz-li Date: Thu, 26 Sep 2024 16:43:26 +0800 Subject: [PATCH 0781/1066] [fix] filter images panic Signed-off-by: xyz-li --- cmd/nerdctl/image/image_list_test.go | 2 ++ pkg/imgutil/filtering.go | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index 72e902fa62b..2e9824b8206 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -110,6 +110,8 @@ LABEL version=0.1`, testutil.CommonImage) base.Cmd("images", "--filter", fmt.Sprintf("since=%s", testutil.CommonImage)).AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) base.Cmd("images", "--filter", fmt.Sprintf("since=%s", testutil.CommonImage), testutil.CommonImage).AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) base.Cmd("images", "--filter", fmt.Sprintf("since=%s", testutil.CommonImage), testutil.CommonImage).AssertOutNotContains(tempName) + base.Cmd("images", "--filter", fmt.Sprintf("since=%s:%s", "non-exists-image", "non-exists-image")).AssertOutContains(tempName) + base.Cmd("images", "--filter", fmt.Sprintf("before=%s:%s", "non-exists-image", "non-exists-image")).AssertOutContains(tempName) } base.Cmd("images", "--filter", "label=foo=bar").AssertOutContains(tempName) base.Cmd("images", "--filter", "label=foo=bar1").AssertOutNotContains(tempName) diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index 05d178a4fe5..473a382642f 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -150,10 +150,12 @@ func FilterByCreatedAt(ctx context.Context, client *containerd.Client, before [] if err != nil { return []images.Image{}, err } - maxTime = beforeImages[0].CreatedAt - for _, image := range beforeImages { - if image.CreatedAt.After(maxTime) { - maxTime = image.CreatedAt + if len(beforeImages) > 0 { + maxTime = beforeImages[0].CreatedAt + for _, image := range beforeImages { + if image.CreatedAt.After(maxTime) { + maxTime = image.CreatedAt + } } } } @@ -163,10 +165,12 @@ func FilterByCreatedAt(ctx context.Context, client *containerd.Client, before [] if err != nil { return []images.Image{}, err } - minTime = sinceImages[0].CreatedAt - for _, image := range sinceImages { - if image.CreatedAt.Before(minTime) { - minTime = image.CreatedAt + if len(sinceImages) > 0 { + minTime = sinceImages[0].CreatedAt + for _, image := range sinceImages { + if image.CreatedAt.Before(minTime) { + minTime = image.CreatedAt + } } } } From 2c2745e85751f467bd9089830d8bd8bc33d063ed Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Tue, 24 Sep 2024 00:01:03 +0900 Subject: [PATCH 0782/1066] fix: Cleaning up orphaned directories and files when containers creation fails When trying to create new containers, the following directories are created based on the new container ID: - `/var/lib/nerdctl/1935db59/containers//` - `/var/lib/nerdctl/1935db59/etchosts//` When containers with existing names are attempted to be created, the processes fail. However, in the events of failures, these directories are not cleaned up. This issue is reported in the following: - https://github.com/containerd/nerdctl/issues/2993 This commit resolves the issue by cleaning up the mentioned directories when containers creation fails. Also, It has also been modified so that the following directory is also cleaned up when the container is removed. - `/var/lib/nerdctl/1935db59/etchosts//` Note that tests of logic to fix bug in Issue #2993 are added based on the following testing principles. - https://github.com/containerd/nerdctl/blob/main/docs/testing/tools.md Signed-off-by: Hayato Kiwata --- .../container/container_create_linux_test.go | 126 ++++++++++++++++++ pkg/cmd/container/create.go | 70 ++++++---- pkg/cmd/container/remove.go | 2 +- pkg/dnsutil/hostsstore/hostsstore.go | 15 +-- 4 files changed, 181 insertions(+), 32 deletions(-) diff --git a/cmd/nerdctl/container/container_create_linux_test.go b/cmd/nerdctl/container/container_create_linux_test.go index e3e2122bf80..234b2170db1 100644 --- a/cmd/nerdctl/container/container_create_linux_test.go +++ b/cmd/nerdctl/container/container_create_linux_test.go @@ -17,14 +17,22 @@ package container import ( + "errors" "fmt" + "os" + "path/filepath" "strings" "testing" + "github.com/opencontainers/go-digest" "gotest.tools/v3/assert" + "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestCreate(t *testing.T) { @@ -174,3 +182,121 @@ func TestCreateWithTty(t *testing.T) { withTtyContainer := base.InspectContainer(withTtyContainerName) assert.Equal(base.T, 0, withTtyContainer.State.ExitCode) } + +// TestIssue2993 tests https://github.com/containerd/nerdctl/issues/2993 +func TestIssue2993(t *testing.T) { + testutil.DockerIncompatible(t) + + nerdtest.Setup() + + const ( + containersPathKey = "containersPath" + etchostsPathKey = "etchostsPath" + ) + + getAddrHash := func(addr string) string { + const addrHashLen = 8 + + d := digest.SHA256.FromString(addr) + h := d.Encoded()[0:addrHashLen] + + return h + } + + testCase := &test.Group{ + { + Description: "Issue #2993 - nerdctl no longer leaks containers and etchosts directories and files when container creation fails.", + Require: nerdtest.Private, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") + + dataRoot := string(data.ReadConfig(nerdtest.DataRoot)) + h := getAddrHash(defaults.DefaultAddress) + dataStore := filepath.Join(dataRoot, h) + namespace := data.Identifier() + + containersPath := filepath.Join(dataStore, "containers", namespace) + containersDirs, err := os.ReadDir(containersPath) + assert.NilError(t, err) + assert.Equal(t, len(containersDirs), 1) + + etchostsPath := filepath.Join(dataStore, "etchosts", namespace) + etchostsDirs, err := os.ReadDir(etchostsPath) + assert.NilError(t, err) + assert.Equal(t, len(etchostsDirs), 1) + + data.Set(containersPathKey, containersPath) + data.Set(etchostsPathKey, etchostsPath) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("run", "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("is already used by ID")}, + Output: func(stdout string, info string, t *testing.T) { + containersDirs, err := os.ReadDir(data.Get(containersPathKey)) + assert.NilError(t, err) + assert.Equal(t, len(containersDirs), 1) + + etchostsDirs, err := os.ReadDir(data.Get(etchostsPathKey)) + assert.NilError(t, err) + assert.Equal(t, len(etchostsDirs), 1) + }, + } + }, + }, + { + Description: "Issue #2993 - nerdctl no longer leaks containers and etchosts directories and files when containers are removed.", + Require: nerdtest.Private, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") + + dataRoot := string(data.ReadConfig(nerdtest.DataRoot)) + h := getAddrHash(defaults.DefaultAddress) + dataStore := filepath.Join(dataRoot, h) + namespace := data.Identifier() + + containersPath := filepath.Join(dataStore, "containers", namespace) + containersDirs, err := os.ReadDir(containersPath) + assert.NilError(t, err) + assert.Equal(t, len(containersDirs), 1) + + etchostsPath := filepath.Join(dataStore, "etchosts", namespace) + etchostsDirs, err := os.ReadDir(etchostsPath) + assert.NilError(t, err) + assert.Equal(t, len(etchostsDirs), 1) + + data.Set(containersPathKey, containersPath) + data.Set(etchostsPathKey, etchostsPath) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("rm", "-f", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Errors: []error{}, + Output: func(stdout string, info string, t *testing.T) { + containersDirs, err := os.ReadDir(data.Get(containersPathKey)) + assert.NilError(t, err) + assert.Equal(t, len(containersDirs), 0) + + etchostsDirs, err := os.ReadDir(data.Get(etchostsPathKey)) + assert.NilError(t, err) + assert.Equal(t, len(etchostsDirs), 0) + }, + } + }, + }, + } + + testCase.Run(t) +} diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 328fe7e6f6a..ec23038274a 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -46,6 +46,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/image" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" "github.com/containerd/nerdctl/v2/pkg/flagutil" "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/imgutil" @@ -118,7 +119,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa platformOpts, err := setPlatformOptions(ctx, client, id, netManager.NetworkOptions().UTSNamespace, &internalLabels, options) if err != nil { - return nil, nil, err + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), err } opts = append(opts, platformOpts...) @@ -130,7 +131,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa } ocispecPlatforms, err := platformutil.NewOCISpecPlatformSlice(false, platformSS) if err != nil { - return nil, nil, err + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), err } rawRef := args[0] @@ -141,13 +142,13 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa ensuredImage, err = image.EnsureImage(ctx, client, rawRef, options.ImagePullOpt) if err != nil { - return nil, nil, err + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), err } } rootfsOpts, rootfsCOpts, err := generateRootfsOpts(args, id, ensuredImage, options) if err != nil { - return nil, nil, err + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), err } opts = append(opts, rootfsOpts...) cOpts = append(cOpts, rootfsCOpts...) @@ -158,12 +159,12 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa envs, err := flagutil.MergeEnvFileAndOSEnv(options.EnvFile, options.Env) if err != nil { - return nil, nil, err + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), err } if options.Interactive { if options.Detach { - return nil, nil, errors.New("currently flag -i and -d cannot be specified together (FIXME)") + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), errors.New("currently flag -i and -d cannot be specified together (FIXME)") } } @@ -174,7 +175,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa var mountOpts []oci.SpecOpts mountOpts, internalLabels.anonVolumes, internalLabels.mountPoints, err = generateMountOpts(ctx, client, ensuredImage, volStore, options) if err != nil { - return nil, nil, err + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), err } opts = append(opts, mountOpts...) @@ -186,30 +187,30 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa // 3, nerdctl start/restart demo logConfig, err := generateLogConfig(dataStore, id, options.LogDriver, options.LogOpt, options.GOptions.Namespace) if err != nil { - return nil, nil, err + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), err } internalLabels.logURI = logConfig.LogURI restartOpts, err := generateRestartOpts(ctx, client, options.Restart, logConfig.LogURI, options.InRun) if err != nil { - return nil, nil, err + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), err } cOpts = append(cOpts, restartOpts...) if err = netManager.VerifyNetworkOptions(ctx); err != nil { - return nil, nil, fmt.Errorf("failed to verify networking settings: %s", err) + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), fmt.Errorf("failed to verify networking settings: %s", err) } netOpts, netNewContainerOpts, err := netManager.ContainerNetworkingOpts(ctx, id) if err != nil { - return nil, nil, fmt.Errorf("failed to generate networking spec options: %s", err) + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), fmt.Errorf("failed to generate networking spec options: %s", err) } opts = append(opts, netOpts...) cOpts = append(cOpts, netNewContainerOpts...) netLabelOpts, err := netManager.InternalNetworkingOptionLabels(ctx) if err != nil { - return nil, nil, fmt.Errorf("failed to generate internal networking labels: %s", err) + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), fmt.Errorf("failed to generate internal networking labels: %s", err) } envs = append(envs, "HOSTNAME="+netLabelOpts.Hostname) @@ -230,37 +231,37 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa if runtime.GOOS != "windows" { hookOpt, err := withNerdctlOCIHook(options.NerdctlCmd, options.NerdctlArgs) if err != nil { - return nil, nil, err + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } opts = append(opts, hookOpt) } uOpts, err := generateUserOpts(options.User) if err != nil { - return nil, nil, err + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } opts = append(opts, uOpts...) gOpts, err := generateGroupsOpts(options.GroupAdd) if err != nil { - return nil, nil, err + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } opts = append(opts, gOpts...) umaskOpts, err := generateUmaskOpts(options.Umask) if err != nil { - return nil, nil, err + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } opts = append(opts, umaskOpts...) rtCOpts, err := generateRuntimeCOpts(options.GOptions.CgroupManager, options.Runtime) if err != nil { - return nil, nil, err + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } cOpts = append(cOpts, rtCOpts...) lCOpts, err := withContainerLabels(options.Label, options.LabelFile, ensuredImage) if err != nil { - return nil, nil, err + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } cOpts = append(cOpts, lCOpts...) @@ -276,10 +277,10 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa if options.Name != "" { containerNameStore, err = namestore.New(dataStore, options.GOptions.Namespace) if err != nil { - return nil, nil, err + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } if err := containerNameStore.Acquire(options.Name, id); err != nil { - return nil, nil, err + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } } internalLabels.name = options.Name @@ -287,14 +288,14 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa internalLabels.extraHosts = strutil.DedupeStrSlice(netManager.NetworkOptions().AddHost) for i, host := range internalLabels.extraHosts { if _, err := dockercliopts.ValidateExtraHost(host); err != nil { - return nil, nil, err + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } parts := strings.SplitN(host, ":", 2) // If the IP Address is a string called "host-gateway", replace this value with the IP address stored // in the daemon level HostGateway IP config variable. if len(parts) == 2 && parts[1] == dockeropts.HostGatewayName { if options.GOptions.HostGatewayIP == "" { - return nil, nil, fmt.Errorf("unable to derive the IP value for host-gateway") + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), fmt.Errorf("unable to derive the IP value for host-gateway") } parts[1] = options.GOptions.HostGatewayIP internalLabels.extraHosts[i] = fmt.Sprintf(`%s:%s`, parts[0], parts[1]) @@ -304,7 +305,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa // TODO: abolish internal labels and only use annotations ilOpt, err := withInternalLabels(internalLabels) if err != nil { - return nil, nil, err + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } cOpts = append(cOpts, ilOpt) @@ -817,6 +818,29 @@ func generateLogConfig(dataStore string, id string, logDriver string, logOpt []s return logConfig, nil } +func generateRemoveStateDirFunc(ctx context.Context, id string, internalLabels internalLabels) func() { + return func() { + if rmErr := os.RemoveAll(internalLabels.stateDir); rmErr != nil { + log.G(ctx).WithError(rmErr).Warnf("failed to remove container %q state dir %q", id, internalLabels.stateDir) + } + } +} + +func generateRemoveOrphanedDirsFunc(ctx context.Context, id, dataStore string, internalLabels internalLabels) func() { + return func() { + if rmErr := os.RemoveAll(internalLabels.stateDir); rmErr != nil { + log.G(ctx).WithError(rmErr).Warnf("failed to remove container %q state dir %q", id, internalLabels.stateDir) + } + + hs, err := hostsstore.New(dataStore, internalLabels.namespace) + if err != nil { + log.G(ctx).WithError(err).Warnf("failed to instantiate hostsstore for %q", internalLabels.namespace) + } else if err = hs.Delete(id); err != nil { + log.G(ctx).WithError(err).Warnf("failed to remove an etchosts directory for container %q", id) + } + } +} + func generateGcFunc(ctx context.Context, container containerd.Container, ns, id, name, dataStore string, containerErr error, containerNameStore namestore.NameStore, netManager containerutil.NetworkOptionsManager, internalLabels internalLabels) func() { return func() { if containerErr == nil { diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index bc055945824..d425b718972 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -233,7 +233,7 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions hs, err := hostsstore.New(dataStore, containerNamespace) if err != nil { log.G(ctx).WithError(err).Warnf("failed to instantiate hostsstore for %q", containerNamespace) - } else if err = hs.DeallocHostsFile(id); err != nil { + } else if err = hs.Delete(id); err != nil { // De-allocate hosts file - soft failure log.G(ctx).WithError(err).Warnf("failed to remove hosts file for container %q", id) } diff --git a/pkg/dnsutil/hostsstore/hostsstore.go b/pkg/dnsutil/hostsstore/hostsstore.go index 7e32e561468..507f93ec708 100644 --- a/pkg/dnsutil/hostsstore/hostsstore.go +++ b/pkg/dnsutil/hostsstore/hostsstore.go @@ -89,7 +89,7 @@ type Store interface { Release(id string) error Update(id, newName string) error HostsPath(id string) (location string, err error) - DeallocHostsFile(id string) (err error) + Delete(id string) (err error) AllocHostsFile(id string, content []byte) (location string, err error) } @@ -185,14 +185,13 @@ func (x *hostsStore) AllocHostsFile(id string, content []byte) (location string, return x.safeStore.Location(id, hostsFile) } -func (x *hostsStore) DeallocHostsFile(id string) (err error) { - defer func() { - if err != nil { - err = errors.Join(ErrHostsStore, err) - } - }() +func (x *hostsStore) Delete(id string) (err error) { + err = x.safeStore.WithLock(func() error { return x.safeStore.Delete(id) }) + if err != nil { + err = errors.Join(ErrHostsStore, err) + } - return x.safeStore.WithLock(func() error { return x.safeStore.Delete(id, hostsFile) }) + return err } func (x *hostsStore) HostsPath(id string) (location string, err error) { From befd089a8851d94a6a318f1bccb7fbac0d41ec17 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 22:05:29 +0000 Subject: [PATCH 0783/1066] build(deps): bump docker/build-push-action from 6.8.0 to 6.9.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.8.0 to 6.9.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.8.0...v6.9.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 6488ec23fd7..dca7c9d1c0f 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -61,7 +61,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.8.0 + uses: docker/build-push-action@v6.9.0 with: context: . platforms: linux/amd64,linux/arm64 From f32152692dcea5e697d6c510a98a47301cbadedf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 22:07:43 +0000 Subject: [PATCH 0784/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.3.2 to 0.3.3. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Changelog](https://github.com/cyphar/filepath-securejoin/blob/main/CHANGELOG.md) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.3.2...v0.3.3) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a9ad22c1a96..1c811b3f725 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.8.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.3.2 + github.com/cyphar/filepath-securejoin v0.3.3 github.com/distribution/reference v0.6.0 github.com/docker/cli v27.3.1+incompatible github.com/docker/docker v27.3.1+incompatible diff --git a/go.sum b/go.sum index 76cccef7005..e49b4cb68bc 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.3.2 h1:QhZu5AxQ+o1XZH0Ye05YzvJ0kAdK6VQc0z9NNMek7gc= -github.com/cyphar/filepath-securejoin v0.3.2/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= +github.com/cyphar/filepath-securejoin v0.3.3 h1:lofZkCEVFIBe0KcdQOzFs8Soy9oaHOWl4gGtPI+gCFc= +github.com/cyphar/filepath-securejoin v0.3.3/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= From 7b64f827b514860a8eb43aa879f40b7c886f2cd0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 22:15:34 +0000 Subject: [PATCH 0785/1066] build(deps): bump github.com/containerd/containerd/v2 Bumps [github.com/containerd/containerd/v2](https://github.com/containerd/containerd) from 2.0.0-rc.4 to 2.0.0-rc.5. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v2.0.0-rc.4...v2.0.0-rc.5) --- updated-dependencies: - dependency-name: github.com/containerd/containerd/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 1c811b3f725..fe7331f2ce1 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0-rc.3 - github.com/containerd/containerd/v2 v2.0.0-rc.4 + github.com/containerd/containerd/v2 v2.0.0-rc.5 github.com/containerd/continuity v0.4.3 github.com/containerd/errdefs v0.1.0 github.com/containerd/fifo v1.1.0 @@ -130,14 +130,14 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect - go.opentelemetry.io/otel v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect + go.opentelemetry.io/otel v1.30.0 // indirect + go.opentelemetry.io/otel/metric v1.30.0 // indirect + go.opentelemetry.io/otel/trace v1.30.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/mod v0.20.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 // indirect - google.golang.org/grpc v1.65.0 // indirect + golang.org/x/mod v0.21.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/grpc v1.67.0 // indirect google.golang.org/protobuf v1.34.2 // indirect lukechampine.com/blake3 v1.3.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index e49b4cb68bc..69738d2f271 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,8 @@ github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd/api v1.8.0-rc.3 h1:q9MyeXmuAGEyKmUGYvvFftNX1RQhfTLsAvYK+SQHQso= github.com/containerd/containerd/api v1.8.0-rc.3/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= -github.com/containerd/containerd/v2 v2.0.0-rc.4 h1:Bvto4h5i2VZkQ+L5SrGupg5ilQ+zkVPILdjf9RWMego= -github.com/containerd/containerd/v2 v2.0.0-rc.4/go.mod h1:p35nJi4Pl9ibzuoVOPc3MputVh6Gbp9xoDg9VHz6/YI= +github.com/containerd/containerd/v2 v2.0.0-rc.5 h1:ejHlOWce4MxQr+lGXdbCCyOZIWqIq027DjXI73SUwg8= +github.com/containerd/containerd/v2 v2.0.0-rc.5/go.mod h1:biu3ZtJwDHEdVxxho680KtHqFfk8WPA1hULNf/vJ7Lw= 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= @@ -321,14 +321,14 @@ go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdH go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= 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.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= +go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= +go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= +go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= +go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= +go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= +go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= 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= @@ -346,8 +346,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= 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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -409,15 +409,15 @@ 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/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4 h1:OsSGQeIIsyOEOimVxLEIL4rwGcnrjOydQaiA2bOnZUM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240805194559-2c9e96a0b5d4/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= 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= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= +google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From c661d16e93f3debf2ba574c1b463fd64ddc16f59 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 1 Oct 2024 21:34:58 -0700 Subject: [PATCH 0786/1066] Fix broken TestImageInspectDifferentValidReferencesForTheSameImage As of 10/01/2024, busybox latest tag (1.37.0) is no longer the same thing as stable (1.36.1). It is unclear if that was made on purpose, or a problem with Docker publication process. Signed-off-by: apostasie --- cmd/nerdctl/image/image_inspect_test.go | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/cmd/nerdctl/image/image_inspect_test.go b/cmd/nerdctl/image/image_inspect_test.go index 95154304d1c..5a0f7111a28 100644 --- a/cmd/nerdctl/image/image_inspect_test.go +++ b/cmd/nerdctl/image/image_inspect_test.go @@ -18,7 +18,6 @@ package image import ( "encoding/json" - "runtime" "strings" "testing" @@ -71,16 +70,12 @@ func TestImageInspectSimpleCases(t *testing.T) { func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { nerdtest.Setup() - platform := runtime.GOOS + "/" + runtime.GOARCH - tags := []string{ "", ":latest", - ":stable", } names := []string{ "busybox", - "library/busybox", "docker.io/library/busybox", "registry-1.docker.io/library/busybox", } @@ -94,11 +89,9 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { nerdtest.Private, ), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", "alpine", "--platform", platform) - helpers.Ensure("pull", "busybox", "--platform", platform) - helpers.Ensure("pull", "busybox:stable", "--platform", platform) - helpers.Ensure("pull", "registry-1.docker.io/library/busybox", "--platform", platform) - helpers.Ensure("pull", "registry-1.docker.io/library/busybox:stable", "--platform", platform) + helpers.Ensure("pull", "alpine") + helpers.Ensure("pull", "busybox") + helpers.Ensure("pull", "registry-1.docker.io/library/busybox") }, SubTests: []*test.Case{ { @@ -150,9 +143,11 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { // Demonstrate image name precedence over digest lookup // Using the shortened sha should no longer get busybox, but rather the newly tagged Alpine + // FIXME: this is triggering https://github.com/containerd/nerdctl/issues/3016 + // We cannot get rid of that image now, which does break local testing helpers.Ensure("tag", "alpine", sha[0:8]) it := nerdtest.InspectImage(helpers, sha[0:8]) - assert.Equal(t, it.ID, alpine.ID, alpine.ID+" vs "+it.ID) + assert.Equal(t, it.ID, alpine.ID) }, } }, @@ -202,18 +197,17 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { }, { Description: "retrieving multiple entries at once", - Command: test.RunCommand("image", "inspect", "busybox", "busybox", "busybox:stable"), + Command: test.RunCommand("image", "inspect", "busybox", "busybox"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: func(stdout string, info string, t *testing.T) { var dc []dockercompat.Image err := json.Unmarshal([]byte(stdout), &dc) assert.NilError(t, err, "Unable to unmarshal output\n"+info) - assert.Equal(t, 3, len(dc), "Unexpectedly did not get 3 results\n"+info) + assert.Equal(t, 2, len(dc), "Unexpectedly did not get 2 results\n"+info) reference := nerdtest.InspectImage(helpers, "busybox") assert.Equal(t, dc[0].ID, reference.ID) assert.Equal(t, dc[1].ID, reference.ID) - assert.Equal(t, dc[2].ID, reference.ID) }, } }, From 9d0f54a567749ed84b54a5c0d5620bc88126d794 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 07:16:08 +0000 Subject: [PATCH 0787/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.12.6 to 0.12.7 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.12.6 to 0.12.7. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.6...v0.12.7) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fe7331f2ce1..0638c63fe97 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ go 1.22.0 require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 - github.com/Microsoft/hcsshim v0.12.6 + github.com/Microsoft/hcsshim v0.12.7 github.com/compose-spec/compose-go/v2 v2.2.0 github.com/containerd/accelerated-container-image v1.2.2 github.com/containerd/cgroups/v3 v3.0.3 diff --git a/go.sum b/go.sum index 69738d2f271..5888b21f15a 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+ github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= 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.12.6 h1:qEnZjoHXv+4/s0LmKZWE0/AiZmMWEIkFfWBSf1a0wlU= -github.com/Microsoft/hcsshim v0.12.6/go.mod h1:ZABCLVcvLMjIkzr9rUGcQ1QA0p0P3Ps+d3N1g2DsFfk= +github.com/Microsoft/hcsshim v0.12.7 h1:MP6R1spmjxTE4EU4J3YsrTxn8CjvN9qwjTKJXldFaRg= +github.com/Microsoft/hcsshim v0.12.7/go.mod h1:HPbAuJ9BvQYYZbB4yEQcyGIsTP5L4yHKeO9XO149AEM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= From 5cdb3e0b3edda017f97ea5f9a640dcf084151fab Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 1 Oct 2024 21:38:06 -0700 Subject: [PATCH 0788/1066] Fix login persistence regression against Hub Login no longer persists for Docker Hub, as a mistake in the code was not using the special case Docker Hub key to save in the store. Signed-off-by: apostasie --- pkg/imgutil/dockerconfigresolver/credentialsstore.go | 2 +- pkg/imgutil/dockerconfigresolver/credentialsstore_test.go | 2 ++ pkg/imgutil/dockerconfigresolver/registryurl_test.go | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/imgutil/dockerconfigresolver/credentialsstore.go b/pkg/imgutil/dockerconfigresolver/credentialsstore.go index 86e5393a20f..b08deba271c 100644 --- a/pkg/imgutil/dockerconfigresolver/credentialsstore.go +++ b/pkg/imgutil/dockerconfigresolver/credentialsstore.go @@ -83,7 +83,7 @@ func (cs *CredentialsStore) Store(registryURL *RegistryURL, credentials *Credent if registryURL.Namespace != nil { credentials.ServerAddress = fmt.Sprintf("%s%s?%s", registryURL.Host, registryURL.Path, registryURL.RawQuery) } else { - credentials.ServerAddress = registryURL.Host + credentials.ServerAddress = registryURL.CanonicalIdentifier() } // XXX future namespaced url likely require special handling here diff --git a/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go b/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go index 6e83bc30584..a9890dffdcd 100644 --- a/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go +++ b/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go @@ -393,3 +393,5 @@ func TestWorkingCredentialsStore(t *testing.T) { }) } + +// TODO: add more tests that write credentials (specifically to hub locations) to verify they use the canonical id properly diff --git a/pkg/imgutil/dockerconfigresolver/registryurl_test.go b/pkg/imgutil/dockerconfigresolver/registryurl_test.go index 02bb0eb64c4..d10a02028e2 100644 --- a/pkg/imgutil/dockerconfigresolver/registryurl_test.go +++ b/pkg/imgutil/dockerconfigresolver/registryurl_test.go @@ -38,6 +38,11 @@ func TestURLParsingAndID(t *testing.T) { address: "whatever://", error: ErrUnsupportedScheme, }, + { + address: "", + identifier: "https://index.docker.io/v1/", + allIDs: []string{"https://index.docker.io/v1/"}, + }, { address: "https://index.docker.io/v1/", identifier: "https://index.docker.io/v1/", From 544991a0d642df27a93022c058d37e2e30c6707e Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 1 Oct 2024 22:14:31 -0700 Subject: [PATCH 0789/1066] Fix Docker Hub push regression Signed-off-by: apostasie --- pkg/imgutil/dockerconfigresolver/registryurl.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/imgutil/dockerconfigresolver/registryurl.go b/pkg/imgutil/dockerconfigresolver/registryurl.go index 57566aee58d..4a1ecfccbdf 100644 --- a/pkg/imgutil/dockerconfigresolver/registryurl.go +++ b/pkg/imgutil/dockerconfigresolver/registryurl.go @@ -102,8 +102,10 @@ func (rn *RegistryURL) AllIdentifiers() []string { // Docker behavior: if the domain was index.docker.io over 443, we are allowed to additionally read the canonical // docker credentials - if rn.Hostname() == "index.docker.io" && rn.Port() == standardHTTPSPort { - fullList = append(fullList, dockerIndexServer) + if rn.Port() == standardHTTPSPort { + if rn.Hostname() == "index.docker.io" || rn.Hostname() == "registry-1.docker.io" { + fullList = append(fullList, dockerIndexServer) + } } // Add legacy variants From 03c9de576608c72b73f9b559d1cb82f4859a2d88 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 1 Oct 2024 17:25:23 -0700 Subject: [PATCH 0790/1066] Update to containerd 2 rc.5 Signed-off-by: apostasie --- .github/workflows/test.yml | 6 +++--- Dockerfile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1936fb6885e..06c04a9685d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -69,10 +69,10 @@ jobs: containerd: v1.7.19 runner: "ubuntu-22.04" - ubuntu: 24.04 - containerd: v2.0.0-rc.4 + containerd: v2.0.0-rc.5 runner: "ubuntu-24.04" - ubuntu: 24.04 - containerd: v2.0.0-rc.4 + containerd: v2.0.0-rc.5 runner: github-arm64-2c-8gb env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" @@ -179,7 +179,7 @@ jobs: rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 24.04 - containerd: v2.0.0-rc.4 + containerd: v2.0.0-rc.5 rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 24.04 diff --git a/Dockerfile b/Dockerfile index 36ff9c41381..dcd8e5995ba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v2.0.0-rc.4 +ARG CONTAINERD_VERSION=v2.0.0-rc.5 ARG RUNC_VERSION=v1.1.14 ARG CNI_PLUGINS_VERSION=v1.5.1 From bfeeabe5d3757425b00d0e159a7508cde154d22d Mon Sep 17 00:00:00 2001 From: Manu Gupta Date: Tue, 1 Oct 2024 20:43:13 -0700 Subject: [PATCH 0791/1066] 3452: Filter Volumes by name if any of the names match Signed-off-by: Manu Gupta --- cmd/nerdctl/volume/volume_list_test.go | 3 --- pkg/cmd/volume/list.go | 21 +++++++++++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/cmd/nerdctl/volume/volume_list_test.go b/cmd/nerdctl/volume/volume_list_test.go index d0ad6d78463..8f5892cb6d9 100644 --- a/cmd/nerdctl/volume/volume_list_test.go +++ b/cmd/nerdctl/volume/volume_list_test.go @@ -270,9 +270,6 @@ func TestVolumeLsFilter(t *testing.T) { }, { Description: "Retrieving name=volume1 and name=volume2", - // FIXME: https://github.com/containerd/nerdctl/issues/3452 - // Nerdctl filter behavior is broken - Require: nerdtest.Docker, Command: func(data test.Data, helpers test.Helpers) test.Command { return helpers.Command("volume", "ls", "--quiet", "--filter", "name="+data.Get("vol1"), "--filter", "name="+data.Get("vol2")) }, diff --git a/pkg/cmd/volume/list.go b/pkg/cmd/volume/list.go index b934f0a9614..bb0654ba5b2 100644 --- a/pkg/cmd/volume/list.go +++ b/pkg/cmd/volume/list.go @@ -269,15 +269,28 @@ func volumeMatchesFilter(vol native.Volume, labelFilterFuncs []func(*map[string] return false } } - for _, nameFilterFunc := range nameFilterFuncs { - if !nameFilterFunc(vol.Name) { - return false - } + + if !anyMatch(vol.Name, nameFilterFuncs) { + return false } + for _, sizeFilterFunc := range sizeFilterFuncs { if !sizeFilterFunc(vol.Size) { return false } } + return true } + +func anyMatch[T any](vol T, filters []func(T) bool) bool { + if len(filters) == 0 { + return true + } + for _, f := range filters { + if f(vol) { + return true + } + } + return false +} From 703bd581786131d4ed8fa62b87bf55fddd6fe9e0 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 3 Oct 2024 00:05:40 -0700 Subject: [PATCH 0792/1066] Fix IPFS missing layer issue Signed-off-by: apostasie --- cmd/nerdctl/issues/issues_linux_test.go | 41 +++++++++++++++++++++++++ pkg/cmd/image/ensure.go | 2 -- pkg/cmd/image/push.go | 13 +++++++- pkg/ipfs/image.go | 7 +---- 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/cmd/nerdctl/issues/issues_linux_test.go b/cmd/nerdctl/issues/issues_linux_test.go index 72f68b707b5..6e8939f8467 100644 --- a/cmd/nerdctl/issues/issues_linux_test.go +++ b/cmd/nerdctl/issues/issues_linux_test.go @@ -20,8 +20,13 @@ package issues import ( "fmt" + "os" + "path/filepath" "testing" + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" "github.com/containerd/nerdctl/v2/pkg/testutil/test" @@ -37,6 +42,16 @@ func TestIssue3425(t *testing.T) { var registry *testregistry.RegistryServer + var ipfsPath string + if rootlessutil.IsRootless() { + var err error + ipfsPath, err = rootlessutil.XDGDataHome() + ipfsPath = filepath.Join(ipfsPath, "ipfs") + assert.NilError(t, err) + } else { + ipfsPath = filepath.Join(os.Getenv("HOME"), ".ipfs") + } + testCase := &test.Case{ Description: "TestIssue3425", Setup: func(data test.Data, helpers test.Helpers) { @@ -126,6 +141,32 @@ func TestIssue3425(t *testing.T) { }, Expected: test.Expects(0, nil, nil), }, + { + Description: "with ipfs", + Require: test.Require( + nerdtest.Private, + test.Not(test.Windows), + test.Not(nerdtest.Docker), + test.Binary("ipfs"), + ), + Env: map[string]string{ + "IPFS_PATH": ipfsPath, + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("image", "pull", testutil.CommonImage) + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage) + helpers.Ensure("image", "rm", "-f", testutil.CommonImage) + helpers.Ensure("image", "pull", testutil.CommonImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("image", "push", "ipfs://"+testutil.CommonImage) + }, + Expected: test.Expects(0, nil, nil), + }, }, } diff --git a/pkg/cmd/image/ensure.go b/pkg/cmd/image/ensure.go index 7d5a2eec440..e622ba04e62 100644 --- a/pkg/cmd/image/ensure.go +++ b/pkg/cmd/image/ensure.go @@ -19,7 +19,6 @@ package image import ( "context" "errors" - "fmt" "net/http" "os" @@ -43,7 +42,6 @@ func EnsureAllContent(ctx context.Context, client *containerd.Client, srcName st imageService := client.ImageService() img, err := imageService.Get(ctx, srcName) if err != nil { - fmt.Println("Failed getting imageservice") return err } diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index 266313a9e04..03966feec1b 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -61,6 +61,17 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options } log.G(ctx).Infof("pushing image %q to IPFS", ref) + parsedRef, err := distributionref.ParseDockerRef(ref) + if err != nil { + return err + } + + // Ensure all the layers are here: https://github.com/containerd/nerdctl/issues/3489 + err = EnsureAllContent(ctx, client, parsedRef.String(), options.GOptions) + if err != nil { + return err + } + var ipfsPath string if options.IpfsAddress != "" { dir, err := os.MkdirTemp("", "apidirtmp") @@ -78,7 +89,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options if options.Estargz { layerConvert = eStargzConvertFunc() } - c, err := ipfs.Push(ctx, client, ref, layerConvert, options.AllPlatforms, options.Platforms, options.IpfsEnsureImage, ipfsPath) + c, err := ipfs.Push(ctx, client, parsedRef.String(), layerConvert, options.AllPlatforms, options.Platforms, options.IpfsEnsureImage, ipfsPath) if err != nil { log.G(ctx).WithError(err).Warnf("ipfs push failed") return err diff --git a/pkg/ipfs/image.go b/pkg/ipfs/image.go index ca944e279c3..84d73bda32e 100644 --- a/pkg/ipfs/image.go +++ b/pkg/ipfs/image.go @@ -37,7 +37,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" - "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) const ipfsPathEnv = "IPFS_PATH" @@ -93,11 +92,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, layerCo log.G(ctx).WithError(err).Warnf("failed to ensure the existence of image %q", rawRef) } } - ref, err := referenceutil.ParseAny(rawRef) - if err != nil { - return "", err - } - return ipfs.PushWithIPFSPath(ctx, client, ref.String(), layerConvert, platMC, &ipath) + return ipfs.PushWithIPFSPath(ctx, client, rawRef, layerConvert, platMC, &ipath) } // ensureContentsOfIPFSImage ensures that the entire contents of an existing IPFS image are fully downloaded to containerd. From bd1eefa6a54fe73847369fe954e39ad80c88adf3 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 3 Oct 2024 11:19:50 -0700 Subject: [PATCH 0793/1066] Make CreateNetwork safer wrt concurrency Signed-off-by: apostasie --- pkg/netutil/netutil.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index bdaab110f28..bafc1385c3e 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -253,16 +253,17 @@ type cniNetworkConfig struct { func (e *CNIEnv) CreateNetwork(opts types.NetworkCreateOptions) (*NetworkConfig, error) { //nolint:revive var net *NetworkConfig - netMap, err := e.NetworkMap() - if err != nil { - return nil, err - } - - if _, ok := netMap[opts.Name]; ok { - return nil, errdefs.ErrAlreadyExists - } fn := func() error { + netMap, err := e.NetworkMap() + if err != nil { + return err + } + + if _, ok := netMap[opts.Name]; ok { + return errdefs.ErrAlreadyExists + } + ipam, err := e.generateIPAM(opts.IPAMDriver, opts.Subnets, opts.Gateway, opts.IPRange, opts.IPAMOptions, opts.IPv6) if err != nil { return err @@ -277,7 +278,7 @@ func (e *CNIEnv) CreateNetwork(opts types.NetworkCreateOptions) (*NetworkConfig, } return e.writeNetworkConfig(net) } - err = lockutil.WithDirLock(e.NetconfPath, fn) + err := lockutil.WithDirLock(e.NetconfPath, fn) if err != nil { return nil, err } From 346b492be4c1a660565be6f61fff91caec926b02 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 25 Sep 2024 13:20:21 -0700 Subject: [PATCH 0794/1066] Test tooling fixes As we make progress rewriting tests, the new tooling needs to adapt. In a shell, this is: - introducing (more) `Requirements`, with a better API - update documentation - fix some t.Helper calls - fix broken stdin implementation - do cleanup custom namespaces properly - change hashing function - disable "private" implying custom data root which is more trouble than is worth - minor cleanups Signed-off-by: apostasie --- docs/testing/tools.md | 56 ++++++-- pkg/testutil/nerdtest/helpers.go | 119 +++++++++++++++++ pkg/testutil/nerdtest/requirements.go | 143 +++++++++++++++++++++ pkg/testutil/nerdtest/test.go | 177 ++++++-------------------- pkg/testutil/test/case.go | 2 +- pkg/testutil/test/command.go | 11 +- pkg/testutil/test/data.go | 30 +++-- pkg/testutil/test/requirement.go | 71 +++++------ pkg/testutil/test/test.go | 2 +- 9 files changed, 411 insertions(+), 200 deletions(-) create mode 100644 pkg/testutil/nerdtest/helpers.go create mode 100644 pkg/testutil/nerdtest/requirements.go diff --git a/docs/testing/tools.md b/docs/testing/tools.md index 655306dc48b..36cee3c0510 100644 --- a/docs/testing/tools.md +++ b/docs/testing/tools.md @@ -5,7 +5,7 @@ The integration test suite in nerdctl is meant to apply to both nerdctl and docker, and further support additional test properties to target specific contexts (ipv6, kube). -Basic _usage_ is covered in the [testing docs](testing.md). +Basic _usage_ is covered in the [testing docs](README.md). This here covers how to write tests, leveraging nerdctl `pkg/testutil/test` which has been specifically developed to take care of repetitive tasks, @@ -166,9 +166,6 @@ Note that `Data` additionally exposes the following functions: Secondly, `Data` allows defining and manipulating "configuration" data. In the case of nerdctl here, the following configuration options are defined: -- `WithConfig(Docker, NotCompatible)` to flag a test as not compatible -- `WithConfig(Mode, Private)` will entirely isolate the test using a different -namespace, data root, nerdctl config, etc - `WithConfig(NerdctlToml, "foo")` which allows specifying a custom config - `WithConfig(DataRoot, "foo")` allowing to point to a custom data-root - `WithConfig(HostsDir, "foo")` to point to a specific hosts directory @@ -358,7 +355,50 @@ All tests (and subtests) are assumed to be parallelizable. You can force a specific `test.Case` to not be run in parallel though, by setting its `NoParallel` property to `true`. -Note that if you want better isolation, it is usually better to use -`WithConfig(nerdtest.Mode, nerdtest.Private)` instead. -This will keep the test parallel (for nerdctl), but isolate it in a different context. -For Docker (which does not support namespaces), it is equivalent to passing `NoParallel: true`. +Note that if you want better isolation, it is usually better to use the requirement +`nerdtest.Private` instead of `NoParallel` (see below). + +## Requirements + +`test.Case` has a `Require` property that allow enforcing specific, per-test requirements. + +Here are a few: +```go +test.Windows // a test runs only on Windows (or Not(Windows)) +test.Linux // a test runs only on Linux +test.Darwin // a test runs only on Darwin +test.OS(name string) // a test runs only on the OS `name` +test.Binary(name string) // a test requires the bin `name` to be in the PATH +test.Not(req Requirement) // a test runs only if the opposite of the requirement `req` is fulfilled +test.Require(req ...Requirement) // a test runs only if all requirements are fulfilled + +nerdtest.Docker // a test only run on Docker - normally used with test.Not(nerdtest.Docker) +nerdtest.Soci // a test requires the soci snapshotter +nerdtest.Rootless // a test requires Rootless (or Not(Rootless), indicating it requires Rootful) +nerdtest.Build // a test requires buildkit +nerdtest.CGroup // a test requires cgroup +nerdtest.OnlyIPv6 // a test is meant to run solely in the ipv6 environment +nerdtest.NerdctlNeedsFixing // indicates that a test cannot be run on nerdctl yet as a fix is required +nerdtest.Private // see below +``` + +### About `nerdtest.Private` + +While all requirements above are self-descriptive or obvious, and are going to skip +tests for environments that do not match the requirements, `nerdtest.Private` is a +special case. + +What it does when required is: create a private namespace, data-root, hosts-dir, nerdctl.toml and +DOCKER_CONFIG that is private to the test. + +Note that subtests are going to inherit that environment as well. + +If the target is Docker - which does not support namespaces for eg - asking for `private` +will merely disable parallelization. + +The purpose of private is to provide a truly clean-room environment for tests +that are guaranteed to have side effects on others, or that do require an exclusive, pristine +environment. + +Using private is generally preferable to disabling parallelization, as doing the latter +would slow down the run and won't have the same guarantees about the environment. diff --git a/pkg/testutil/nerdtest/helpers.go b/pkg/testutil/nerdtest/helpers.go new file mode 100644 index 00000000000..346a6c9122a --- /dev/null +++ b/pkg/testutil/nerdtest/helpers.go @@ -0,0 +1,119 @@ +/* + 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 nerdtest + +import ( + "encoding/json" + "testing" + "time" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +// InspectContainer is a helper that can be used inside custom commands or Setup +func InspectContainer(helpers test.Helpers, name string) dockercompat.Container { + var dc []dockercompat.Container + cmd := helpers.Command("container", "inspect", name) + cmd.Run(&test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + }, + }) + return dc[0] +} + +func InspectVolume(helpers test.Helpers, name string, args ...string) native.Volume { + var dc []native.Volume + cmdArgs := append([]string{"volume", "inspect"}, args...) + cmdArgs = append(cmdArgs, name) + + cmd := helpers.Command(cmdArgs...) + cmd.Run(&test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + }, + }) + return dc[0] +} + +func InspectNetwork(helpers test.Helpers, name string, args ...string) dockercompat.Network { + var dc []dockercompat.Network + cmdArgs := append([]string{"network", "inspect"}, args...) + cmdArgs = append(cmdArgs, name) + + cmd := helpers.Command(cmdArgs...) + cmd.Run(&test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + }, + }) + return dc[0] +} + +func InspectImage(helpers test.Helpers, name string) dockercompat.Image { + var dc []dockercompat.Image + cmd := helpers.Command("image", "inspect", name) + cmd.Run(&test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + }, + }) + return dc[0] +} + +func EnsureContainerStarted(helpers test.Helpers, con string) { + const ( + maxRetry = 5 + sleep = time.Second + ) + for i := 0; i < maxRetry; i++ { + count := i + cmd := helpers.Command("container", "inspect", con) + cmd.Run(&test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Container + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + if dc[0].State.Running { + return + } + if count == maxRetry-1 { + t.Fatalf("conainer %s not running", con) + } + time.Sleep(sleep) + }, + }) + } +} diff --git a/pkg/testutil/nerdtest/requirements.go b/pkg/testutil/nerdtest/requirements.go new file mode 100644 index 00000000000..f75f3e8b7f7 --- /dev/null +++ b/pkg/testutil/nerdtest/requirements.go @@ -0,0 +1,143 @@ +/* + 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 nerdtest + +import ( + "encoding/json" + "fmt" + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +var ipv6 test.ConfigKey = "IPv6Test" +var only test.ConfigValue = "Only" +var mode test.ConfigKey = "Mode" +var modePrivate test.ConfigValue = "Private" + +var OnlyIPv6 = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { + ret = testutil.GetEnableIPv6() + if !ret { + mess = "runner skips IPv6 compatible tests in the non-IPv6 environment" + } + data.WithConfig(ipv6, only) + return ret, mess +}) + +var Private = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { + data.WithConfig(mode, modePrivate) + return true, "private mode" +}) + +var Soci = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { + ret = false + mess = "soci is not enabled" + (&test.GenericCommand{}). + WithT(t). + WithBinary(testutil.GetTarget()). + WithArgs("info", "--format", "{{ json . }}"). + Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dinf dockercompat.Info + err := json.Unmarshal([]byte(stdout), &dinf) + assert.NilError(t, err, "failed to parse docker info") + for _, p := range dinf.Plugins.Storage { + if p == "soci" { + ret = true + mess = "soci is enabled" + } + } + }, + }) + + return ret, mess +}) + +var Docker = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { + ret = testutil.GetTarget() == testutil.Docker + if ret { + mess = "current target is docker" + } else { + mess = "current target is not docker" + } + return ret, mess +}) + +var NerdctlNeedsFixing = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { + ret = testutil.GetTarget() == testutil.Docker + if ret { + mess = "current target is docker" + } else { + mess = "current target is nerdctl, but it is currently broken and not working for this" + } + return ret, mess +}) + +var Rootless = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { + // Make sure we DO not return "IsRootless true" for docker + ret = testutil.GetTarget() != testutil.Docker && rootlessutil.IsRootless() + if ret { + mess = "environment is rootless" + } else { + mess = "environment is rootful" + } + return ret, mess +}) + +var Build = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { + // FIXME: shouldn't we run buildkitd in a container? At least for testing, that would be so much easier than + // against the host install + ret = true + mess = "buildkitd is enabled" + if testutil.GetTarget() == testutil.Nerdctl { + _, err := buildkitutil.GetBuildkitHost(testutil.Namespace) + if err != nil { + ret = false + mess = fmt.Sprintf("buildkitd is not enabled: %+v", err) + } + } + return ret, mess +}) + +var CGroup = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { + ret = true + mess = "cgroup is enabled" + (&test.GenericCommand{}). + WithT(t). + WithBinary(testutil.GetTarget()). + WithArgs("info", "--format", "{{ json . }}"). + Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dinf dockercompat.Info + err := json.Unmarshal([]byte(stdout), &dinf) + assert.NilError(t, err, "failed to parse docker info") + switch dinf.CgroupDriver { + case "none", "": + ret = false + mess = "cgroup is none" + } + }, + }) + + return ret, mess +}) diff --git a/pkg/testutil/nerdtest/test.go b/pkg/testutil/nerdtest/test.go index 812ff08591d..78046cb9cca 100644 --- a/pkg/testutil/nerdtest/test.go +++ b/pkg/testutil/nerdtest/test.go @@ -17,18 +17,12 @@ package nerdtest import ( - "encoding/json" - "fmt" "os" "path/filepath" "testing" "gotest.tools/v3/assert" - "github.com/containerd/nerdctl/v2/pkg/buildkitutil" - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" - "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) @@ -39,64 +33,11 @@ func Setup() { // Nerdctl specific config key and values var NerdctlToml test.ConfigKey = "NerdctlToml" +var DockerConfig test.ConfigKey = "DockerConfig" var HostsDir test.ConfigKey = "HostsDir" var DataRoot test.ConfigKey = "DataRoot" var Namespace test.ConfigKey = "Namespace" -var Mode test.ConfigKey = "Mode" -var ModePrivate test.ConfigValue = "Private" -var IPv6 test.ConfigKey = "IPv6Test" -var Only test.ConfigValue = "Only" - -var OnlyIPv6 = test.MakeRequirement(func(data test.Data) (ret bool, mess string) { - ret = testutil.GetEnableIPv6() - if !ret { - mess = "runner skips IPv6 compatible tests in the non-IPv6 environment" - } - data.WithConfig(IPv6, Only) - return ret, mess -}) - -var Private = test.MakeRequirement(func(data test.Data) (ret bool, mess string) { - data.WithConfig(Mode, ModePrivate) - return true, "" -}) - -var Docker = test.MakeRequirement(func(data test.Data) (ret bool, mess string) { - ret = testutil.GetTarget() == testutil.Docker - if ret { - mess = "current target is docker" - } else { - mess = "current target is not docker" - } - return ret, mess -}) - -var Rootless = test.MakeRequirement(func(data test.Data) (ret bool, mess string) { - ret = rootlessutil.IsRootless() - if ret { - mess = "environment is rootless" - } else { - mess = "environment is rootful" - } - return ret, mess -}) - -var Build = test.MakeRequirement(func(data test.Data) (ret bool, mess string) { - // FIXME: shouldn't we run buildkitd in a container? At least for testing, that would be so much easier than - // against the host install - ret = true - mess = "" - if testutil.GetTarget() == testutil.Nerdctl { - _, err := buildkitutil.GetBuildkitHost(testutil.Namespace) - if err != nil { - ret = false - mess = fmt.Sprintf("test requires buildkitd: %+v", err) - } - } - return ret, mess -}) - type NerdCommand struct { test.GenericCommand // FIXME: annoying - forces custom Clone, etc @@ -121,69 +62,6 @@ func (nc *NerdCommand) Clone() test.Command { } } -// InspectContainer is a helper that can be used inside custom commands or Setup -func InspectContainer(helpers test.Helpers, name string) dockercompat.Container { - var dc []dockercompat.Container - cmd := helpers.Command("container", "inspect", name) - cmd.Run(&test.Expected{ - ExitCode: 0, - Output: func(stdout string, info string, t *testing.T) { - err := json.Unmarshal([]byte(stdout), &dc) - assert.NilError(t, err, "Unable to unmarshal output\n"+info) - assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) - }, - }) - return dc[0] -} - -func InspectVolume(helpers test.Helpers, name string, args ...string) native.Volume { - var dc []native.Volume - cmdArgs := append([]string{"volume", "inspect"}, args...) - cmdArgs = append(cmdArgs, name) - - cmd := helpers.Command(cmdArgs...) - cmd.Run(&test.Expected{ - ExitCode: 0, - Output: func(stdout string, info string, t *testing.T) { - err := json.Unmarshal([]byte(stdout), &dc) - assert.NilError(t, err, "Unable to unmarshal output\n"+info) - assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) - }, - }) - return dc[0] -} - -func InspectNetwork(helpers test.Helpers, name string, args ...string) dockercompat.Network { - var dc []dockercompat.Network - cmdArgs := append([]string{"network", "inspect"}, args...) - cmdArgs = append(cmdArgs, name) - - cmd := helpers.Command(cmdArgs...) - cmd.Run(&test.Expected{ - ExitCode: 0, - Output: func(stdout string, info string, t *testing.T) { - err := json.Unmarshal([]byte(stdout), &dc) - assert.NilError(t, err, "Unable to unmarshal output\n"+info) - assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) - }, - }) - return dc[0] -} - -func InspectImage(helpers test.Helpers, name string) dockercompat.Image { - var dc []dockercompat.Image - cmd := helpers.Command("image", "inspect", name) - cmd.Run(&test.Expected{ - ExitCode: 0, - Output: func(stdout string, info string, t *testing.T) { - err := json.Unmarshal([]byte(stdout), &dc) - assert.NilError(t, err, "Unable to unmarshal output\n"+info) - assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) - }, - }) - return dc[0] -} - func nerdctlSetup(testCase *test.Case, t *testing.T) test.Command { t.Helper() @@ -192,11 +70,11 @@ func nerdctlSetup(testCase *test.Case, t *testing.T) test.Command { var pvNamespace string inherited := false - if dt.ReadConfig(IPv6) != Only && testutil.GetEnableIPv6() { + if dt.ReadConfig(ipv6) != only && testutil.GetEnableIPv6() { t.Skip("runner skips non-IPv6 compatible tests in the IPv6 environment") } - if dt.ReadConfig(Mode) == ModePrivate { + if dt.ReadConfig(mode) == modePrivate { // If private was inherited, we already got a configured namespace if dt.ReadConfig(Namespace) != "" { pvNamespace = string(dt.ReadConfig(Namespace)) @@ -208,7 +86,8 @@ func nerdctlSetup(testCase *test.Case, t *testing.T) test.Command { testCase.Env["DOCKER_CONFIG"] = testCase.Data.TempDir() testCase.Env["NERDCTL_TOML"] = filepath.Join(testCase.Data.TempDir(), "nerdctl.toml") dt.WithConfig(HostsDir, test.ConfigValue(testCase.Data.TempDir())) - dt.WithConfig(DataRoot, test.ConfigValue(testCase.Data.TempDir())) + // Setting data root is more trouble than anything and does not significantly increase isolation + // dt.WithConfig(DataRoot, test.ConfigValue(testCase.Data.TempDir())) } testUtilBase = testutil.NewBaseWithNamespace(t, pvNamespace) if testUtilBase.Target == testutil.Docker { @@ -224,11 +103,19 @@ func nerdctlSetup(testCase *test.Case, t *testing.T) test.Command { // If we were passed custom content for NerdctlToml, save it // Not happening if this is not nerdctl of course - if testUtilBase.Target == testutil.Nerdctl && dt.ReadConfig(NerdctlToml) != "" { - dest := filepath.Join(testCase.Data.TempDir(), "nerdctl.toml") - testCase.Env["NERDCTL_TOML"] = dest - err := os.WriteFile(dest, []byte(dt.ReadConfig(NerdctlToml)), 0400) - assert.NilError(t, err, "failed to write custom nerdctl toml file for test") + if testUtilBase.Target == testutil.Nerdctl { + if dt.ReadConfig(NerdctlToml) != "" { + dest := filepath.Join(testCase.Data.TempDir(), "nerdctl.toml") + testCase.Env["NERDCTL_TOML"] = dest + err := os.WriteFile(dest, []byte(dt.ReadConfig(NerdctlToml)), 0400) + assert.NilError(t, err, "failed to write custom nerdctl toml file for test") + } + if dt.ReadConfig(DockerConfig) != "" { + dest := filepath.Join(testCase.Data.TempDir(), "config.json") + testCase.Env["DOCKER_CONFIG"] = filepath.Dir(dest) + err := os.WriteFile(dest, []byte(dt.ReadConfig(DockerConfig)), 0400) + assert.NilError(t, err, "failed to write custom docker config json file for test") + } } // Build the base @@ -242,21 +129,37 @@ func nerdctlSetup(testCase *test.Case, t *testing.T) test.Command { if testUtilBase.Target == testutil.Nerdctl { if dt.ReadConfig(HostsDir) != "" { - baseCommand.GenericCommand.WithArgs("--hosts-dir=" + string(dt.ReadConfig(HostsDir))) + baseCommand.WithArgs("--hosts-dir=" + string(dt.ReadConfig(HostsDir))) } if dt.ReadConfig(DataRoot) != "" { - baseCommand.GenericCommand.WithArgs("--data-root=" + string(dt.ReadConfig(DataRoot))) + baseCommand.WithArgs("--data-root=" + string(dt.ReadConfig(DataRoot))) } } // If we were in a custom namespace, not inherited - make sure we clean up the namespace - // FIXME: this is broken, and custom namespaces are not cleaned properly if testUtilBase.Target == testutil.Nerdctl && pvNamespace != "" && !inherited { cleanup := func() { - cl := baseCommand.Clone() - cl.WithArgs("namespace", "remove", pvNamespace) - cl.Run(nil) + // Stop all containers, then prune everything + containerList := baseCommand.Clone() + containerList.WithArgs("ps", "-q") + containerList.Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + if stdout != "" { + containerRm := baseCommand.Clone() + containerRm.WithArgs("rm", "-f", stdout) + containerRm.Run(&test.Expected{}) + } + }, + }) + + systemPrune := baseCommand.Clone() + systemPrune.WithArgs("system", "prune", "-f", "--all", "--volumes") + systemPrune.Run(&test.Expected{}) + + cleanNamespace := baseCommand.Clone() + cleanNamespace.WithArgs("namespace", "remove", pvNamespace) + cleanNamespace.Run(nil) } cleanup() t.Cleanup(cleanup) diff --git a/pkg/testutil/test/case.go b/pkg/testutil/test/case.go index eed35a929f6..36384c6962b 100644 --- a/pkg/testutil/test/case.go +++ b/pkg/testutil/test/case.go @@ -133,7 +133,7 @@ func (test *Case) seal(t *testing.T) { // Check the requirements if test.Require != nil { - test.Require(test.Data, t) + test.Require(test.Data, true, t) } } diff --git a/pkg/testutil/test/command.go b/pkg/testutil/test/command.go index 6fbb1779d52..3e1b840db6e 100644 --- a/pkg/testutil/test/command.go +++ b/pkg/testutil/test/command.go @@ -128,7 +128,9 @@ func (gc *GenericCommand) Run(expect *Expected) { func (gc *GenericCommand) boot() icmd.Cmd { // This is a helper function, not to appear in the debugging output - gc.t.Helper() + if gc.t != nil { + gc.t.Helper() + } binary := gc.mainBinary args := gc.mainArgs @@ -155,6 +157,10 @@ func (gc *GenericCommand) boot() icmd.Cmd { icmdCmd.Dir = gc.tempDir } + if gc.stdin != nil { + icmdCmd.Stdin = gc.stdin + } + // Attach any extra env we have for k, v := range gc.Env { icmdCmd.Env = append(icmdCmd.Env, fmt.Sprintf("%s=%s", k, v)) @@ -182,8 +188,9 @@ func (gc *GenericCommand) Clear() Command { return gc } -func (gc *GenericCommand) WithT(t *testing.T) { +func (gc *GenericCommand) WithT(t *testing.T) Command { gc.t = t + return gc } func (gc *GenericCommand) WithTempDir(tempDir string) { diff --git a/pkg/testutil/test/data.go b/pkg/testutil/test/data.go index 99f2aa041ad..a2cc2d58b87 100644 --- a/pkg/testutil/test/data.go +++ b/pkg/testutil/test/data.go @@ -19,6 +19,7 @@ package test import ( "crypto/sha256" "fmt" + "regexp" "strings" "testing" ) @@ -116,17 +117,26 @@ func (dt *data) getConfig() map[ConfigKey]ConfigValue { return dt.config } -func defaultIdentifierHashing(name string) string { - s := strings.ReplaceAll(name, " ", "_") - s = strings.ReplaceAll(s, "/", "_") - s = strings.ReplaceAll(s, "-", "_") - s = strings.ReplaceAll(s, ",", "_") - s = strings.ToLower(s) - if len(s) > 76 { - s = fmt.Sprintf("%x", sha256.Sum256([]byte(s))) +func defaultIdentifierHashing(names ...string) string { + // Notes: identifier MAY be used for namespaces, image names, etc. + // So, the rules are stringent on what it can contain. + replaceWith := []byte("-") + name := strings.ToLower(strings.Join(names, string(replaceWith))) + // Ensure we have a unique identifier despite characters replacements (well, as unique as the names collection being passed) + signature := fmt.Sprintf("%x", sha256.Sum256([]byte(name)))[0:8] + // Make sure we do not use any unsafe characters + safeName := regexp.MustCompile(`[^a-z0-9-]+`) + // And we avoid repeats of the separator + noRepeat := regexp.MustCompile(fmt.Sprintf(`[%s]{2,}`, replaceWith)) + sn := safeName.ReplaceAll([]byte(name), replaceWith) + sn = noRepeat.ReplaceAll(sn, replaceWith) + // Do not allow trailing or leading dash (as that may stutter) + name = strings.Trim(string(sn), string(replaceWith)) + // Ensure we will never go above 76 characters in length (with signature) + if len(name) > 67 { + name = name[0:67] } - - return s + return name + "-" + signature } // TODO: allow to pass custom hashing methods? diff --git a/pkg/testutil/test/requirement.go b/pkg/testutil/test/requirement.go index 1acad13af28..c148fef1914 100644 --- a/pkg/testutil/test/requirement.go +++ b/pkg/testutil/test/requirement.go @@ -23,11 +23,11 @@ import ( "testing" ) -func MakeRequirement(fn func(data Data) (bool, string)) Requirement { - return func(data Data, t *testing.T) (bool, string) { - ret, mess := fn(data) +func MakeRequirement(fn func(data Data, t *testing.T) (bool, string)) Requirement { + return func(data Data, skip bool, t *testing.T) (bool, string) { + ret, mess := fn(data, t) - if t != nil && !ret { + if skip && !ret { t.Helper() t.Skipf("Test skipped as %s", mess) } @@ -37,7 +37,7 @@ func MakeRequirement(fn func(data Data) (bool, string)) Requirement { } func Binary(name string) Requirement { - return MakeRequirement(func(data Data) (ret bool, mess string) { + return MakeRequirement(func(data Data, t *testing.T) (ret bool, mess string) { mess = fmt.Sprintf("executable %q has been found in PATH", name) ret = true if _, err := exec.LookPath(name); err != nil { @@ -50,8 +50,8 @@ func Binary(name string) Requirement { } func OS(os string) Requirement { - return MakeRequirement(func(data Data) (ret bool, mess string) { - mess = fmt.Sprintf("current operating is %q", runtime.GOOS) + return MakeRequirement(func(data Data, t *testing.T) (ret bool, mess string) { + mess = fmt.Sprintf("current operating system is %q", runtime.GOOS) ret = true if runtime.GOOS != os { ret = false @@ -61,49 +61,38 @@ func OS(os string) Requirement { }) } -var Windows = MakeRequirement(func(data Data) (ret bool, mess string) { - ret = runtime.GOOS == "windows" - if ret { - mess = "operating system is Windows" - } else { - mess = "operating system is not Windows" - } - return ret, mess -}) - -var Linux = MakeRequirement(func(data Data) (ret bool, mess string) { - ret = runtime.GOOS == "linux" - if ret { - mess = "operating system is Linux" - } else { - mess = "operating system is not Linux" - } - return ret, mess -}) - -var Darwin = MakeRequirement(func(data Data) (ret bool, mess string) { - ret = runtime.GOOS == "darwin" - if ret { - mess = "operating system is Darwin" - } else { - mess = "operating system is not Darwin" - } - return ret, mess -}) +func Arch(arch string) Requirement { + return MakeRequirement(func(data Data, t *testing.T) (ret bool, mess string) { + mess = fmt.Sprintf("current architecture is %q", runtime.GOARCH) + ret = true + if runtime.GOARCH != arch { + ret = false + } + + return ret, mess + }) +} + +var Amd64 = Arch("amd64") +var Arm64 = Arch("arm64") +var Windows = OS("windows") +var Linux = OS("linux") +var Darwin = OS("darwin") func Not(requirement Requirement) Requirement { - return MakeRequirement(func(data Data) (ret bool, mess string) { - b, mess := requirement(data, nil) + return MakeRequirement(func(data Data, t *testing.T) (ret bool, mess string) { + b, mess := requirement(data, false, t) + return !b, mess }) } func Require(thing ...Requirement) Requirement { - return func(data Data, t *testing.T) (ret bool, mess string) { + return func(data Data, skip bool, t *testing.T) (ret bool, mess string) { for _, th := range thing { - b, m := th(data, nil) + b, m := th(data, false, t) if !b { - if t != nil { + if skip { t.Helper() t.Skipf("Test skipped as %s", m) } diff --git a/pkg/testutil/test/test.go b/pkg/testutil/test/test.go index 2e6743be8e6..858563be789 100644 --- a/pkg/testutil/test/test.go +++ b/pkg/testutil/test/test.go @@ -24,7 +24,7 @@ import ( // A Requirement is a function that can evaluate random requirement and possibly skip a test // See test.MakeRequirement to make your own -type Requirement func(data Data, t *testing.T) (bool, string) +type Requirement func(data Data, skip bool, t *testing.T) (bool, string) // A Butler is the function signature meant to be attached to a Setup or Cleanup routine for a test.Case type Butler func(data Data, helpers Helpers) From 19fa3d934c0bee7f4cca3d2c5ed627c23a2298ee Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 25 Sep 2024 14:03:17 -0700 Subject: [PATCH 0795/1066] Increase delay of delayOnceReader to reduce flakyness of TestAttach Signed-off-by: apostasie --- pkg/testutil/testutil_linux.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index 0629abbdac2..dce9431e021 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -126,7 +126,7 @@ func NewDelayOnceReader(wrapped io.Reader) io.Reader { func (r *delayOnceReader) Read(p []byte) (int, error) { // FIXME: this is obviously not exact science. At 1 second, it will fail regularly on the CI under load. - r.once.Do(func() { time.Sleep(2 * time.Second) }) + r.once.Do(func() { time.Sleep(5 * time.Second) }) n, err := r.wrapped.Read(p) if errors.Is(err, io.EOF) { time.Sleep(time.Second) From 5ce1e4b69f9d24b85acd0ac51102d0f35834973c Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 25 Sep 2024 20:35:26 -0700 Subject: [PATCH 0796/1066] Fix parallelism for docker Signed-off-by: apostasie --- .../network/network_prune_linux_test.go | 77 ++++++----- cmd/nerdctl/system/system_prune_linux_test.go | 128 +++++++++--------- cmd/nerdctl/volume/volume_prune_linux_test.go | 94 +++++++------ 3 files changed, 156 insertions(+), 143 deletions(-) diff --git a/cmd/nerdctl/network/network_prune_linux_test.go b/cmd/nerdctl/network/network_prune_linux_test.go index 1692ac55053..333b3aefd95 100644 --- a/cmd/nerdctl/network/network_prune_linux_test.go +++ b/cmd/nerdctl/network/network_prune_linux_test.go @@ -27,45 +27,50 @@ import ( func TestNetworkPrune(t *testing.T) { nerdtest.Setup() - testGroup := &test.Group{ - { - Description: "Prune does not collect started container network", - Require: nerdtest.Private, - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("network", "rm", data.Identifier()) - }, - Command: test.RunCommand("network", "prune", "-f"), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.DoesNotContain(data.Identifier()), - } - }, - }, - { - Description: "Prune does collect stopped container network", - Require: nerdtest.Private, - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) - helpers.Ensure("stop", data.Identifier()) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("network", "rm", data.Identifier()) + testCase := &test.Case{ + Description: "TestNetworkPrune", + Require: nerdtest.Private, + + SubTests: []*test.Case{ + { + Description: "Prune does not collect started container network", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Command: test.RunCommand("network", "prune", "-f"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.DoesNotContain(data.Identifier()), + } + }, }, - Command: test.RunCommand("network", "prune", "-f"), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.Contains(data.Identifier()), - } + { + Description: "Prune does collect stopped container network", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) + helpers.Ensure("stop", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Command: test.RunCommand("network", "prune", "-f"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Identifier()), + } + }, }, }, } - testGroup.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/system/system_prune_linux_test.go b/cmd/nerdctl/system/system_prune_linux_test.go index 40d08f1beea..dbf78726fcd 100644 --- a/cmd/nerdctl/system/system_prune_linux_test.go +++ b/cmd/nerdctl/system/system_prune_linux_test.go @@ -32,75 +32,79 @@ import ( func TestSystemPrune(t *testing.T) { nerdtest.Setup() - testGroup := &test.Group{ - { - Description: "volume prune all success", - // Private because of prune evidently - Require: nerdtest.Private, - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("volume", "create", data.Identifier()) - anonIdentifier := helpers.Capture("volume", "create") - helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()), - "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) + testCase := &test.Case{ + Description: "TestSystemPrune", + NoParallel: true, + SubTests: []*test.Case{ + { + Description: "volume prune all success", + // Private because of prune evidently + Require: nerdtest.Private, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("volume", "create", data.Identifier()) + anonIdentifier := helpers.Capture("volume", "create") + helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()), + "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) - data.Set("anonIdentifier", anonIdentifier) + data.Set("anonIdentifier", anonIdentifier) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + helpers.Anyhow("volume", "rm", data.Identifier()) + helpers.Anyhow("volume", "rm", data.Get("anonIdentifier")) + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.RunCommand("system", "prune", "-f", "--volumes", "--all"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + volumes := helpers.Capture("volume", "ls") + networks := helpers.Capture("network", "ls") + images := helpers.Capture("images") + containers := helpers.Capture("ps", "-a") + assert.Assert(t, strings.Contains(volumes, data.Identifier()), volumes) + assert.Assert(t, !strings.Contains(volumes, data.Get("anonIdentifier")), volumes) + assert.Assert(t, !strings.Contains(containers, data.Identifier()), containers) + assert.Assert(t, !strings.Contains(networks, data.Identifier()), networks) + assert.Assert(t, !strings.Contains(images, testutil.CommonImage), images) + }, + } + }, }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("network", "rm", data.Identifier()) - helpers.Anyhow("volume", "rm", data.Identifier()) - helpers.Anyhow("volume", "rm", data.Get("anonIdentifier")) - helpers.Anyhow("rm", "-f", data.Identifier()) - }, - Command: test.RunCommand("system", "prune", "-f", "--volumes", "--all"), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - ExitCode: 0, - Output: func(stdout string, info string, t *testing.T) { - volumes := helpers.Capture("volume", "ls") - networks := helpers.Capture("network", "ls") - images := helpers.Capture("images") - containers := helpers.Capture("ps", "-a") - assert.Assert(t, strings.Contains(volumes, data.Identifier()), volumes) - assert.Assert(t, !strings.Contains(volumes, data.Get("anonIdentifier")), volumes) - assert.Assert(t, !strings.Contains(containers, data.Identifier()), containers) - assert.Assert(t, !strings.Contains(networks, data.Identifier()), networks) - assert.Assert(t, !strings.Contains(images, testutil.CommonImage), images) - }, - } - }, - }, - { - Description: "buildkit", - // FIXME: using a dedicated namespace does not work with rootful (because of buildkitd) - NoParallel: true, - // buildkitd is not available with docker - Require: test.Require(nerdtest.Build, test.Not(nerdtest.Docker)), - // FIXME: this test will happily say "green" even if the command actually fails to do its duty - // if there is nothing in the build cache. - // Ensure with setup here that we DO build something first - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("system", "prune", "-f", "--volumes", "--all") - }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - buildctlBinary, err := buildkitutil.BuildctlBinary() - if err != nil { - t.Fatal(err) - } + { + Description: "buildkit", + // FIXME: using a dedicated namespace does not work with rootful (because of buildkitd) + NoParallel: true, + // buildkitd is not available with docker + Require: test.Require(nerdtest.Build, test.Not(nerdtest.Docker)), + // FIXME: this test will happily say "green" even if the command actually fails to do its duty + // if there is nothing in the build cache. + // Ensure with setup here that we DO build something first + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("system", "prune", "-f", "--volumes", "--all") + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + buildctlBinary, err := buildkitutil.BuildctlBinary() + if err != nil { + t.Fatal(err) + } - host, err := buildkitutil.GetBuildkitHost(testutil.Namespace) - if err != nil { - t.Fatal(err) - } + host, err := buildkitutil.GetBuildkitHost(testutil.Namespace) + if err != nil { + t.Fatal(err) + } - buildctlArgs := buildkitutil.BuildctlBaseArgs(host) - buildctlArgs = append(buildctlArgs, "du") + buildctlArgs := buildkitutil.BuildctlBaseArgs(host) + buildctlArgs = append(buildctlArgs, "du") - return helpers.CustomCommand(buildctlBinary, buildctlArgs...) + return helpers.CustomCommand(buildctlBinary, buildctlArgs...) + }, + Expected: test.Expects(0, nil, test.Contains("Total:\t\t0B")), }, - Expected: test.Expects(0, nil, test.Contains("Total:\t\t0B")), }, } - testGroup.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/volume/volume_prune_linux_test.go b/cmd/nerdctl/volume/volume_prune_linux_test.go index 8898ad30ab4..da859b1af43 100644 --- a/cmd/nerdctl/volume/volume_prune_linux_test.go +++ b/cmd/nerdctl/volume/volume_prune_linux_test.go @@ -56,54 +56,58 @@ func TestVolumePrune(t *testing.T) { } // This set must be marked as private, since we cannot prune without interacting with other tests. - testGroup := &test.Group{ - { - Description: "prune anonymous only", - Require: nerdtest.Private, - Command: test.RunCommand("volume", "prune", "-f"), - Setup: setup, - Cleanup: cleanup, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.DoesNotContain(data.Get("anonIDBusy")), - test.Contains(data.Get("anonIDDangling")), - test.DoesNotContain(data.Get("namedBusy")), - test.DoesNotContain(data.Get("namedDangling")), - func(stdout string, info string, t *testing.T) { - helpers.Ensure("volume", "inspect", data.Get("anonIDBusy")) - helpers.Fail("volume", "inspect", data.Get("anonIDDangling")) - helpers.Ensure("volume", "inspect", data.Get("namedBusy")) - helpers.Ensure("volume", "inspect", data.Get("namedDangling")) - }, - ), - } + testCase := &test.Case{ + Description: "Prune", + Require: nerdtest.Private, + SubTests: []*test.Case{ + { + Description: "prune anonymous only", + NoParallel: true, + Command: test.RunCommand("volume", "prune", "-f"), + Setup: setup, + Cleanup: cleanup, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain(data.Get("anonIDBusy")), + test.Contains(data.Get("anonIDDangling")), + test.DoesNotContain(data.Get("namedBusy")), + test.DoesNotContain(data.Get("namedDangling")), + func(stdout string, info string, t *testing.T) { + helpers.Ensure("volume", "inspect", data.Get("anonIDBusy")) + helpers.Fail("volume", "inspect", data.Get("anonIDDangling")) + helpers.Ensure("volume", "inspect", data.Get("namedBusy")) + helpers.Ensure("volume", "inspect", data.Get("namedDangling")) + }, + ), + } + }, }, - }, - { - Description: "prune all", - Require: nerdtest.Private, - Command: test.RunCommand("volume", "prune", "-f", "--all"), - Setup: setup, - Cleanup: cleanup, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.DoesNotContain(data.Get("anonIDBusy")), - test.Contains(data.Get("anonIDDangling")), - test.DoesNotContain(data.Get("namedBusy")), - test.Contains(data.Get("namedDangling")), - func(stdout string, info string, t *testing.T) { - helpers.Ensure("volume", "inspect", data.Get("anonIDBusy")) - helpers.Fail("volume", "inspect", data.Get("anonIDDangling")) - helpers.Ensure("volume", "inspect", data.Get("namedBusy")) - helpers.Fail("volume", "inspect", data.Get("namedDangling")) - }, - ), - } + { + Description: "prune all", + NoParallel: true, + Command: test.RunCommand("volume", "prune", "-f", "--all"), + Setup: setup, + Cleanup: cleanup, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain(data.Get("anonIDBusy")), + test.Contains(data.Get("anonIDDangling")), + test.DoesNotContain(data.Get("namedBusy")), + test.Contains(data.Get("namedDangling")), + func(stdout string, info string, t *testing.T) { + helpers.Ensure("volume", "inspect", data.Get("anonIDBusy")) + helpers.Fail("volume", "inspect", data.Get("anonIDDangling")) + helpers.Ensure("volume", "inspect", data.Get("namedBusy")) + helpers.Fail("volume", "inspect", data.Get("namedDangling")) + }, + ), + } + }, }, }, } - testGroup.Run(t) + testCase.Run(t) } From 2c1a5b8721f901933d9d752f301e3f70a04f6c05 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 2 Oct 2024 01:00:10 -0700 Subject: [PATCH 0797/1066] Fix tests broken by tooling update Signed-off-by: apostasie --- .../container/container_create_linux_test.go | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/cmd/nerdctl/container/container_create_linux_test.go b/cmd/nerdctl/container/container_create_linux_test.go index 234b2170db1..ff5e076d241 100644 --- a/cmd/nerdctl/container/container_create_linux_test.go +++ b/cmd/nerdctl/container/container_create_linux_test.go @@ -206,14 +206,16 @@ func TestIssue2993(t *testing.T) { testCase := &test.Group{ { Description: "Issue #2993 - nerdctl no longer leaks containers and etchosts directories and files when container creation fails.", - Require: nerdtest.Private, Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") + dataRoot := data.TempDir() + + helpers.Ensure("run", "--data-root", dataRoot, "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") - dataRoot := string(data.ReadConfig(nerdtest.DataRoot)) h := getAddrHash(defaults.DefaultAddress) dataStore := filepath.Join(dataRoot, h) - namespace := data.Identifier() + + // FIXME: update with next tooling iteration to retrieve from the command + namespace := "nerdctl-test" containersPath := filepath.Join(dataStore, "containers", namespace) containersDirs, err := os.ReadDir(containersPath) @@ -229,10 +231,10 @@ func TestIssue2993(t *testing.T) { data.Set(etchostsPathKey, etchostsPath) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("rm", "--data-root", data.TempDir(), "-f", data.Identifier()) }, Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("run", "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") + return helpers.Command("run", "--data-root", data.TempDir(), "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ @@ -252,14 +254,16 @@ func TestIssue2993(t *testing.T) { }, { Description: "Issue #2993 - nerdctl no longer leaks containers and etchosts directories and files when containers are removed.", - Require: nerdtest.Private, Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") + dataRoot := data.TempDir() + + helpers.Ensure("run", "--data-root", dataRoot, "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") - dataRoot := string(data.ReadConfig(nerdtest.DataRoot)) h := getAddrHash(defaults.DefaultAddress) dataStore := filepath.Join(dataRoot, h) - namespace := data.Identifier() + + // FIXME: update with next tooling iteration to retrieve from the command + namespace := "nerdctl-test" containersPath := filepath.Join(dataStore, "containers", namespace) containersDirs, err := os.ReadDir(containersPath) @@ -275,10 +279,10 @@ func TestIssue2993(t *testing.T) { data.Set(etchostsPathKey, etchostsPath) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("--data-root", data.TempDir(), "rm", "-f", data.Identifier()) }, Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("rm", "-f", data.Identifier()) + return helpers.Command("--data-root", data.TempDir(), "rm", "-f", data.Identifier()) }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ From e6c47ef328aa1e7eea3273311fdc4e5800c541e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 05:00:54 +0000 Subject: [PATCH 0798/1066] build(deps): bump golangci/golangci-lint-action from 6.1.0 to 6.1.1 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.1.0 to 6.1.1. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v6.1.0...v6.1.1) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/test-canary.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 37dfd898fd7..90f5d5248dd 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -32,7 +32,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v6.1.0 + uses: golangci/golangci-lint-action@v6.1.1 with: args: --verbose diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 06c04a9685d..bb9a66ce3a3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v6.1.0 + uses: golangci/golangci-lint-action@v6.1.1 with: version: v1.60.1 args: --verbose From 1ff8d48ba78423535b4447b86c04d5540bce8c11 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Fri, 4 Oct 2024 22:02:27 +0000 Subject: [PATCH 0799/1066] Update to containerd 1.7.22, 1.6.36 in CI Signed-off-by: Austin Vazquez --- .github/workflows/test-canary.yml | 2 +- .github/workflows/test.yml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 90f5d5248dd..90c96b71988 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -100,7 +100,7 @@ jobs: - uses: actions/checkout@v4.2.0 with: repository: containerd/containerd - ref: "v1.7.19" + ref: "v1.7.22" path: containerd fetch-depth: 1 - name: "Set up CNI" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bb9a66ce3a3..1bd3c674777 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -63,10 +63,10 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04 and later: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.33 + containerd: v1.6.36 runner: "ubuntu-20.04" - ubuntu: 22.04 - containerd: v1.7.19 + containerd: v1.7.22 runner: "ubuntu-22.04" - ubuntu: 24.04 containerd: v2.0.0-rc.5 @@ -115,7 +115,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04 and later: cgroup v2 include: - ubuntu: 24.04 - containerd: v1.7.19 + containerd: v1.7.22 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -171,11 +171,11 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04 and later: cgroup v2 include: - ubuntu: 20.04 - containerd: v1.6.33 + containerd: v1.6.36 rootlesskit: v1.1.1 # Deprecated target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.19 + containerd: v1.7.22 rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 24.04 @@ -183,7 +183,7 @@ jobs: rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 24.04 - containerd: v1.7.19 + containerd: v1.7.22 rootlesskit: v2.3.1 target: test-integration-rootless-port-slirp4netns env: @@ -320,7 +320,7 @@ jobs: - uses: actions/checkout@v4.2.0 with: repository: containerd/containerd - ref: v1.7.19 + ref: v1.7.22 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -328,7 +328,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.19 + ctrdVersion: 1.7.22 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" From 9755f22f9af43bf385b990b76ff560768248dce2 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Fri, 4 Oct 2024 22:17:45 +0000 Subject: [PATCH 0800/1066] Update BuildKit (0.16.0) Signed-off-by: Austin Vazquez --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.2 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.16.0 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.2 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.16.0 diff --git a/Dockerfile b/Dockerfile index dcd8e5995ba..5f95798d18b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.1.14 ARG CNI_PLUGINS_VERSION=v1.5.1 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.15.2 +ARG BUILDKIT_VERSION=v0.16.0 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.2 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.2 deleted file mode 100644 index a662a4e6cd1..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.15.2 +++ /dev/null @@ -1,2 +0,0 @@ -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/buildkit-v0.16.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.16.0 new file mode 100644 index 00000000000..d150cc6c876 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.16.0 @@ -0,0 +1,2 @@ +a07a01da821d39bdb6e03a2f98ee407bb861cc61ece2e69e2ea4d61b3a4ab7f1 buildkit-v0.16.0.linux-amd64.tar.gz +1b70bb7955ddda66537d4bf9aa540e79e79e19aa989901613da58f5f133a53ef buildkit-v0.16.0.linux-arm64.tar.gz From 92c3297f159b9982209f63b41fc226825c43ba84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Oct 2024 22:57:24 +0000 Subject: [PATCH 0801/1066] build(deps): bump the golang-x group with 5 updates Bumps the golang-x group with 5 updates: | Package | From | To | | --- | --- | --- | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.27.0` | `0.28.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.29.0` | `0.30.0` | | [golang.org/x/sys](https://github.com/golang/sys) | `0.25.0` | `0.26.0` | | [golang.org/x/term](https://github.com/golang/term) | `0.24.0` | `0.25.0` | | [golang.org/x/text](https://github.com/golang/text) | `0.18.0` | `0.19.0` | Updates `golang.org/x/crypto` from 0.27.0 to 0.28.0 - [Commits](https://github.com/golang/crypto/compare/v0.27.0...v0.28.0) Updates `golang.org/x/net` from 0.29.0 to 0.30.0 - [Commits](https://github.com/golang/net/compare/v0.29.0...v0.30.0) Updates `golang.org/x/sys` from 0.25.0 to 0.26.0 - [Commits](https://github.com/golang/sys/compare/v0.25.0...v0.26.0) Updates `golang.org/x/term` from 0.24.0 to 0.25.0 - [Commits](https://github.com/golang/term/compare/v0.24.0...v0.25.0) Updates `golang.org/x/text` from 0.18.0 to 0.19.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.18.0...v0.19.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 0638c63fe97..f59fac3953e 100644 --- a/go.mod +++ b/go.mod @@ -65,12 +65,12 @@ require ( github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.27.0 - golang.org/x/net v0.29.0 + golang.org/x/crypto v0.28.0 + golang.org/x/net v0.30.0 golang.org/x/sync v0.8.0 - golang.org/x/sys v0.25.0 - golang.org/x/term v0.24.0 - golang.org/x/text v0.18.0 + golang.org/x/sys v0.26.0 + golang.org/x/term v0.25.0 + golang.org/x/text v0.19.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) diff --git a/go.sum b/go.sum index 5888b21f15a..dc101766143 100644 --- a/go.sum +++ b/go.sum @@ -336,8 +336,8 @@ go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= @@ -357,8 +357,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -382,14 +382,14 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From c075a5769a07c6824d2ddfe1f37fe8ce8c14fc9d Mon Sep 17 00:00:00 2001 From: Bob Callaway Date: Sun, 6 Oct 2024 08:53:23 -0400 Subject: [PATCH 0802/1066] switch cosign registry from GCR to GHCR Signed-off-by: Bob Callaway --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5f95798d18b..f825b4bc837 100644 --- a/Dockerfile +++ b/Dockerfile @@ -293,7 +293,7 @@ WORKDIR /go/src/github.com/containerd/nerdctl VOLUME /tmp ENV CGO_ENABLED=0 # copy cosign binary for integration test -COPY --from=gcr.io/projectsigstore/cosign:v2.2.3@sha256:8fc9cad121611e8479f65f79f2e5bea58949e8a87ffac2a42cb99cf0ff079ba7 /ko-app/cosign /usr/local/bin/cosign +COPY --from=ghcr.io/sigstore/cosign/cosign:v2.2.3@sha256:8fc9cad121611e8479f65f79f2e5bea58949e8a87ffac2a42cb99cf0ff079ba7 /ko-app/cosign /usr/local/bin/cosign # installing soci for integration test ARG SOCI_SNAPSHOTTER_VERSION RUN fname="soci-snapshotter-${SOCI_SNAPSHOTTER_VERSION}-${TARGETOS:-linux}-${TARGETARCH:-amd64}.tar.gz" && \ From 2e3b6365cff2851b9c05b59d0ce11ff463f3357f Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 6 Oct 2024 18:01:29 -0700 Subject: [PATCH 0803/1066] Fix netwalker issues Current implementation of netwalker (henceforth network inspect and remove) suffers from many issues, rooting from mixing names and identifiers in the same namespace, faulty erroring logic, and overly complicated design making debugging and reasonning harder. This commit removes the walker and replaces it with a simpler approach. Next commit will add tests. Signed-off-by: apostasie --- cmd/nerdctl/completion/completion.go | 6 +- pkg/cmd/container/kill.go | 12 +- pkg/cmd/network/inspect.go | 71 ++++++----- pkg/cmd/network/remove.go | 73 +++++++---- .../container_network_manager.go | 13 +- pkg/idutil/netwalker/netwalker.go | 119 ------------------ pkg/netutil/netutil.go | 92 +++++++++++--- pkg/netutil/netutil_unix.go | 4 +- pkg/ocihook/ocihook.go | 12 +- 9 files changed, 181 insertions(+), 221 deletions(-) delete mode 100644 pkg/idutil/netwalker/netwalker.go diff --git a/cmd/nerdctl/completion/completion.go b/cmd/nerdctl/completion/completion.go index ea7352d8561..7718c1bb063 100644 --- a/cmd/nerdctl/completion/completion.go +++ b/cmd/nerdctl/completion/completion.go @@ -124,9 +124,13 @@ func NetworkNames(cmd *cobra.Command, exclude []string) ([]string, cobra.ShellCo if err != nil { return nil, cobra.ShellCompDirectiveError } - for netName := range netConfigs { + for netName, network := range netConfigs { if _, ok := excludeMap[netName]; !ok { candidates = append(candidates, netName) + if network.NerdctlID != nil { + candidates = append(candidates, *network.NerdctlID) + candidates = append(candidates, (*network.NerdctlID)[0:12]) + } } } for _, s := range []string{"host", "none"} { diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index 50c2900bfbd..4e53b4f9e3b 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -161,16 +161,12 @@ func cleanupNetwork(ctx context.Context, container containerd.Container, globalO cniOpts := []gocni.Opt{ gocni.WithPluginDir([]string{globalOpts.CNIPath}), } - netMap, err := e.NetworkMap() - if err != nil { - return err - } + var netw *netutil.NetworkConfig for _, netstr := range networks { - net, ok := netMap[netstr] - if !ok { - return fmt.Errorf("no such network: %q", netstr) + if netw, err = e.NetworkByNameOrID(netstr); err != nil { + return err } - cniOpts = append(cniOpts, gocni.WithConfListBytes(net.Bytes)) + cniOpts = append(cniOpts, gocni.WithConfListBytes(netw.Bytes)) } cni, err := gocni.New(cniOpts...) if err != nil { diff --git a/pkg/cmd/network/inspect.go b/pkg/cmd/network/inspect.go index 6389be63755..5fae28028f3 100644 --- a/pkg/cmd/network/inspect.go +++ b/pkg/cmd/network/inspect.go @@ -19,62 +19,71 @@ package network import ( "context" "encoding/json" + "errors" "fmt" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/formatter" - "github.com/containerd/nerdctl/v2/pkg/idutil/netwalker" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/netutil" ) func Inspect(ctx context.Context, options types.NetworkInspectOptions) error { - globalOptions := options.GOptions - e, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace)) + if options.Mode != "native" && options.Mode != "dockercompat" { + return fmt.Errorf("unknown mode %q", options.Mode) + } + cniEnv, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace)) if err != nil { return err } - if options.Mode != "native" && options.Mode != "dockercompat" { - return fmt.Errorf("unknown mode %q", options.Mode) - } var result []interface{} - walker := netwalker.NetworkWalker{ - Client: e, - OnFound: func(ctx context.Context, found netwalker.Found) error { - if found.MatchCount > 1 { - return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) - } - r := &native.Network{ - CNI: json.RawMessage(found.Network.Bytes), - NerdctlID: found.Network.NerdctlID, - NerdctlLabels: found.Network.NerdctlLabels, - File: found.Network.File, - } - switch options.Mode { - case "native": - result = append(result, r) - case "dockercompat": - compat, err := dockercompat.NetworkFromNative(r) - if err != nil { - return err - } - result = append(result, compat) + netLists, errs := cniEnv.ListNetworksMatch(options.Networks, true) + + for req, netList := range netLists { + if len(netList) > 1 { + errs = append(errs, fmt.Errorf("multiple IDs found with provided prefix: %s", req)) + continue + } + if len(netList) == 0 { + errs = append(errs, fmt.Errorf("no network found matching: %s", req)) + continue + } + network := netList[0] + r := &native.Network{ + CNI: json.RawMessage(network.Bytes), + NerdctlID: network.NerdctlID, + NerdctlLabels: network.NerdctlLabels, + File: network.File, + } + switch options.Mode { + case "native": + result = append(result, r) + case "dockercompat": + compat, err := dockercompat.NetworkFromNative(r) + if err != nil { + return err } - return nil - }, + result = append(result, compat) + } } - // `network inspect` doesn't support pseudo network. - err = walker.WalkAll(ctx, options.Networks, true, false) if len(result) > 0 { if formatErr := formatter.FormatSlice(options.Format, options.Stdout, result); formatErr != nil { log.G(ctx).Error(formatErr) } + err = nil + } else { + err = errors.New("unable to find any network matching the provided request") + } + + for _, unErr := range errs { + log.G(ctx).Error(unErr) } + return err } diff --git a/pkg/cmd/network/remove.go b/pkg/cmd/network/remove.go index 66ad7ca1f33..41731d3f40c 100644 --- a/pkg/cmd/network/remove.go +++ b/pkg/cmd/network/remove.go @@ -18,17 +18,18 @@ package network import ( "context" + "errors" "fmt" containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" - "github.com/containerd/nerdctl/v2/pkg/idutil/netwalker" "github.com/containerd/nerdctl/v2/pkg/netutil" ) func Remove(ctx context.Context, client *containerd.Client, options types.NetworkRemoveOptions) error { - e, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace)) + cniEnv, err := netutil.NewCNIEnv(options.GOptions.CNIPath, options.GOptions.CNINetConfPath, netutil.WithNamespace(options.GOptions.Namespace)) if err != nil { return err } @@ -38,28 +39,52 @@ func Remove(ctx context.Context, client *containerd.Client, options types.Networ return err } - walker := netwalker.NetworkWalker{ - Client: e, - OnFound: func(ctx context.Context, found netwalker.Found) error { - if found.MatchCount > 1 { - return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) - } - if value, ok := usedNetworkInfo[found.Network.Name]; ok { - return fmt.Errorf("network %q is in use by container %q", found.Req, value) - } - if found.Network.NerdctlID == nil { - return fmt.Errorf("%s is managed outside nerdctl and cannot be removed", found.Req) - } - if found.Network.File == "" { - return fmt.Errorf("%s is a pre-defined network and cannot be removed", found.Req) - } - if err := e.RemoveNetwork(found.Network); err != nil { - return err - } - fmt.Fprintln(options.Stdout, found.Req) - return nil - }, + var result []string + netLists, errs := cniEnv.ListNetworksMatch(options.Networks, false) + + for req, netList := range netLists { + if len(netList) > 1 { + errs = append(errs, fmt.Errorf("multiple IDs found with provided prefix: %s", req)) + continue + } + if len(netList) == 0 { + errs = append(errs, fmt.Errorf("no network found matching: %s", req)) + continue + } + network := netList[0] + if value, ok := usedNetworkInfo[network.Name]; ok { + errs = append(errs, fmt.Errorf("network %q is in use by container %q", req, value)) + continue + } + if network.Name == "bridge" { + errs = append(errs, errors.New("cannot remove pre-defined network bridge")) + continue + } + if network.File == "" { + errs = append(errs, fmt.Errorf("%s is a pre-defined network and cannot be removed", req)) + continue + } + if network.NerdctlID == nil { + errs = append(errs, fmt.Errorf("%s is managed outside nerdctl and cannot be removed", req)) + continue + } + if err := cniEnv.RemoveNetwork(network); err != nil { + errs = append(errs, err) + } else { + result = append(result, req) + } + } + for _, unErr := range errs { + log.G(ctx).Error(unErr) + } + if len(result) > 0 { + for _, id := range result { + fmt.Fprintln(options.Stdout, id) + } + err = nil + } else { + err = errors.New("no network could be removed") } - return walker.WalkAll(ctx, options.Networks, true, false) + return err } diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 6a97adc47ef..7f7b97b13e4 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -667,17 +667,14 @@ func writeEtcHostnameForContainer(globalOptions types.GlobalCommandOptions, host // from the networkSlice is of a type within supportedTypes. // nolint:unused func verifyNetworkTypes(env *netutil.CNIEnv, networkSlice []string, supportedTypes []string) (map[string]*netutil.NetworkConfig, error) { - netMap, err := env.NetworkMap() - if err != nil { - return nil, err - } - res := make(map[string]*netutil.NetworkConfig, len(networkSlice)) + var netConfig *netutil.NetworkConfig + var err error for _, netstr := range networkSlice { - netConfig, ok := netMap[netstr] - if !ok { - return nil, fmt.Errorf("network %s not found", netstr) + if netConfig, err = env.NetworkByNameOrID(netstr); err != nil { + return nil, err } + netType := netConfig.Plugins[0].Network.Type if supportedTypes != nil && !strutil.InStringSlice(supportedTypes, netType) { return nil, fmt.Errorf("network type %q is not supported for network mapping %q, must be one of: %v", netType, netstr, supportedTypes) diff --git a/pkg/idutil/netwalker/netwalker.go b/pkg/idutil/netwalker/netwalker.go deleted file mode 100644 index 40debd9bfd2..00000000000 --- a/pkg/idutil/netwalker/netwalker.go +++ /dev/null @@ -1,119 +0,0 @@ -/* - 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 netwalker - -import ( - "context" - "fmt" - "regexp" - "strings" - - "github.com/containerd/nerdctl/v2/pkg/netutil" -) - -type Found struct { - Network *netutil.NetworkConfig - Req string // The raw request string. name, short ID, or long ID. - MatchIndex int // Begins with 0, up to MatchCount - 1. - MatchCount int // 1 on exact match. > 1 on ambiguous match. Never be <= 0. -} - -type OnFound func(ctx context.Context, found Found) error - -type NetworkWalker struct { - Client *netutil.CNIEnv - OnFound OnFound -} - -// Walk walks networks and calls w.OnFound . -// Req is name, short ID, or long ID. -// Returns the number of the found entries. -func (w *NetworkWalker) Walk(ctx context.Context, req string) (int, error) { - longIDExp, err := regexp.Compile(fmt.Sprintf("^sha256:%s.*", regexp.QuoteMeta(req))) - if err != nil { - return 0, err - } - - shortIDExp, err := regexp.Compile(fmt.Sprintf("^%s", regexp.QuoteMeta(req))) - if err != nil { - return 0, err - } - - idFilterF := func(n *netutil.NetworkConfig) bool { - if n.NerdctlID == nil { - // External network - return n.Name == req - } - return n.Name == req || longIDExp.Match([]byte(*n.NerdctlID)) || shortIDExp.Match([]byte(*n.NerdctlID)) - } - networks, err := w.Client.FilterNetworks(idFilterF) - if err != nil { - return 0, err - } - - matchCount := len(networks) - - for i, network := range networks { - f := Found{ - Network: network, - Req: req, - MatchIndex: i, - MatchCount: matchCount, - } - if e := w.OnFound(ctx, f); e != nil { - return -1, e - } - } - return matchCount, nil -} - -// WalkAll calls `Walk` for each req in `reqs`. -// -// It can be used when the matchCount is not important (e.g., only care if there -// is any error or if matchCount == 0 (not found error) when walking all reqs). -// If `forceAll`, it calls `Walk` on every req -// and return all errors joined by `\n`. If not `forceAll`, it returns the first error -// encountered while calling `Walk`. -// `allowSeudoNetwork` allows seudo network (host, none) to be passed to `Walk`, otherwise -// an error is recorded for it. -func (w *NetworkWalker) WalkAll(ctx context.Context, reqs []string, forceAll, allowSeudoNetwork bool) error { - var errs []string - for _, req := range reqs { - if !allowSeudoNetwork && (req == "host" || req == "none") { - err := fmt.Errorf("pseudo network not allowed: %s", req) - if !forceAll { - return err - } - errs = append(errs, err.Error()) - } else { - n, err := w.Walk(ctx, req) - if err == nil && n == 0 { - err = fmt.Errorf("no such network: %s", req) - } - if err != nil { - if !forceAll { - return err - } - errs = append(errs, err.Error()) - } - } - } - if len(errs) > 0 { - return fmt.Errorf("%d errors:\n%s", len(errs), strings.Join(errs, "\n")) - } - return nil -} diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index bafc1385c3e..81badc8edf1 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -53,6 +53,48 @@ type CNIEnv struct { type CNIEnvOpt func(e *CNIEnv) error +func (e *CNIEnv) ListNetworksMatch(reqs []string, allowPseudoNetwork bool) (list map[string][]*NetworkConfig, errs []error) { + var err error + + var networkConfigs []*NetworkConfig + err = lockutil.WithDirLock(e.NetconfPath, func() error { + networkConfigs, err = e.networkConfigList() + return err + }) + if err != nil { + return nil, []error{err} + } + + list = make(map[string][]*NetworkConfig) + for _, req := range reqs { + if !allowPseudoNetwork && (req == "host" || req == "none") { + errs = append(errs, fmt.Errorf("pseudo network not allowed: %s", req)) + continue + } + + result := []*NetworkConfig{} + // First match by name + for _, networkConfig := range networkConfigs { + if networkConfig.Name == req { + result = append(result, networkConfig) + } + } + // If nothing, try to match the id + if len(result) == 0 { + for _, networkConfig := range networkConfigs { + if networkConfig.NerdctlID != nil { + if len(req) <= len((*networkConfig.NerdctlID)) && (*networkConfig.NerdctlID)[0:len(req)] == req { + result = append(result, networkConfig) + } + } + } + } + list[req] = result + } + + return list, errs +} + func UsedNetworks(ctx context.Context, client *containerd.Client) (map[string][]string, error) { nsService := client.NamespaceService() nsList, err := nsService.List(ctx) @@ -188,19 +230,29 @@ func (e *CNIEnv) NetworkMap() (map[string]*NetworkConfig, error) { //nolint:revi log.L.Warnf("duplicate network name %q, %#v will get superseded by %#v", n.Name, original, n) } m[n.Name] = n - if n.NerdctlID != nil { - id := *n.NerdctlID - m[id] = n - if len(id) > 12 { - id = id[:12] - m[id] = n - } - } } return m, nil } -func (e *CNIEnv) FilterNetworks(filterf func(*NetworkConfig) bool) ([]*NetworkConfig, error) { +func (e *CNIEnv) NetworkByNameOrID(key string) (*NetworkConfig, error) { + networks, err := e.networkConfigList() + if err != nil { + return nil, err + } + + for _, n := range networks { + if n.Name == key { + return n, nil + } + if n.NerdctlID != nil && (*n.NerdctlID == key || (*n.NerdctlID)[0:12] == key) { + return n, nil + } + } + + return nil, fmt.Errorf("no such network: %q", key) +} + +func (e *CNIEnv) filterNetworks(filterf func(*NetworkConfig) bool) ([]*NetworkConfig, error) { networkConfigs, err := e.networkConfigList() if err != nil { return nil, err @@ -230,8 +282,8 @@ func (e *CNIEnv) usedSubnets() ([]*net.IPNet, error) { if err != nil { return nil, err } - for _, net := range networkConfigs { - usedSubnets = append(usedSubnets, net.subnets()...) + for _, netConf := range networkConfigs { + usedSubnets = append(usedSubnets, netConf.subnets()...) } return usedSubnets, nil } @@ -252,7 +304,7 @@ type cniNetworkConfig struct { } func (e *CNIEnv) CreateNetwork(opts types.NetworkCreateOptions) (*NetworkConfig, error) { //nolint:revive - var net *NetworkConfig + var netConf *NetworkConfig fn := func() error { netMap, err := e.NetworkMap() @@ -272,17 +324,17 @@ func (e *CNIEnv) CreateNetwork(opts types.NetworkCreateOptions) (*NetworkConfig, if err != nil { return err } - net, err = e.generateNetworkConfig(opts.Name, opts.Labels, plugins) + netConf, err = e.generateNetworkConfig(opts.Name, opts.Labels, plugins) if err != nil { return err } - return e.writeNetworkConfig(net) + return e.writeNetworkConfig(netConf) } err := lockutil.WithDirLock(e.NetconfPath, fn) if err != nil { return nil, err } - return net, nil + return netConf, nil } func (e *CNIEnv) RemoveNetwork(net *NetworkConfig) error { @@ -309,7 +361,7 @@ func (e *CNIEnv) GetDefaultNetworkConfig() (*NetworkConfig, error) { } return false } - labelMatches, err := e.FilterNetworks(defaultLabelFilterF) + labelMatches, err := e.filterNetworks(defaultLabelFilterF) if err != nil { return nil, err } @@ -324,7 +376,7 @@ func (e *CNIEnv) GetDefaultNetworkConfig() (*NetworkConfig, error) { defaultNameFilterF := func(nc *NetworkConfig) bool { return nc.Name == DefaultNetworkName } - nameMatches, err := e.FilterNetworks(defaultNameFilterF) + nameMatches, err := e.filterNetworks(defaultNameFilterF) if err != nil { return nil, err } @@ -460,11 +512,11 @@ func (e *CNIEnv) networkConfigList() ([]*NetworkConfig, error) { return nil, err } } - id, labels := nerdctlIDLabels(lcl.Bytes) + id, lbls := nerdctlIDLabels(lcl.Bytes) l = append(l, &NetworkConfig{ NetworkConfigList: lcl, NerdctlID: id, - NerdctlLabels: labels, + NerdctlLabels: lbls, File: fileName, }) } @@ -567,7 +619,7 @@ func structToMap(in interface{}) (map[string]interface{}, error) { } // ParseMTU parses the mtu option -func ParseMTU(mtu string) (int, error) { +func parseMTU(mtu string) (int, error) { if mtu == "" { return 0, nil // default } diff --git a/pkg/netutil/netutil_unix.go b/pkg/netutil/netutil_unix.go index df62145f632..eba2a5e3b8b 100644 --- a/pkg/netutil/netutil_unix.go +++ b/pkg/netutil/netutil_unix.go @@ -102,7 +102,7 @@ func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string] for opt, v := range opts { switch opt { case "mtu", "com.docker.network.driver.mtu": - mtu, err = ParseMTU(v) + mtu, err = parseMTU(v) if err != nil { return nil, err } @@ -148,7 +148,7 @@ func (e *CNIEnv) generateCNIPlugins(driver string, name string, ipam map[string] for opt, v := range opts { switch opt { case "mtu", "com.docker.network.driver.mtu": - mtu, err = ParseMTU(v) + mtu, err = parseMTU(v) if err != nil { return nil, err } diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index e67ec17c677..ffa98041611 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -159,16 +159,12 @@ func newHandlerOpts(state *specs.State, dataStore, cniPath, cniNetconfPath strin cniOpts := []gocni.Opt{ gocni.WithPluginDir([]string{cniPath}), } - netMap, err := e.NetworkMap() - if err != nil { - return nil, err - } + var netw *netutil.NetworkConfig for _, netstr := range networks { - net, ok := netMap[netstr] - if !ok { - return nil, fmt.Errorf("no such network: %q", netstr) + if netw, err = e.NetworkByNameOrID(netstr); err != nil { + return nil, err } - cniOpts = append(cniOpts, gocni.WithConfListBytes(net.Bytes)) + cniOpts = append(cniOpts, gocni.WithConfListBytes(netw.Bytes)) o.cniNames = append(o.cniNames, netstr) } o.cni, err = gocni.New(cniOpts...) From 1fe34f86cfb6be5f178eaf474dbb907aa178d0f3 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 6 Oct 2024 18:03:36 -0700 Subject: [PATCH 0804/1066] Tests for net inspect Signed-off-by: apostasie --- cmd/nerdctl/network/network_inspect_test.go | 129 +++++++++++++++++++- 1 file changed, 126 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/network/network_inspect_test.go b/cmd/nerdctl/network/network_inspect_test.go index 4aa6147d063..5dfe9b88612 100644 --- a/cmd/nerdctl/network/network_inspect_test.go +++ b/cmd/nerdctl/network/network_inspect_test.go @@ -19,6 +19,7 @@ package network import ( "encoding/json" "errors" + "strings" "testing" "gotest.tools/v3/assert" @@ -38,6 +39,128 @@ func TestNetworkInspect(t *testing.T) { ) testGroup := &test.Group{ + { + Description: "non existent network", + Command: test.RunCommand("network", "inspect", "nonexistent"), + // FIXME: where is this error even comin from? + Expected: test.Expects(1, []error{errors.New("no network found matching")}, nil), + }, + { + Description: "invalid name network", + Command: test.RunCommand("network", "inspect", "∞"), + // FIXME: this is not even a valid identifier + Expected: test.Expects(1, []error{errors.New("no network found matching")}, nil), + }, + { + Description: "none", + Require: nerdtest.NerdctlNeedsFixing, + Command: test.RunCommand("network", "inspect", "none"), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Equal(t, dc[0].Name, "none") + }), + }, + { + Description: "host", + Require: nerdtest.NerdctlNeedsFixing, + Command: test.RunCommand("network", "inspect", "host"), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Equal(t, dc[0].Name, "host") + }), + }, + { + Description: "bridge", + Require: test.Not(test.Windows), + Command: test.RunCommand("network", "inspect", "bridge"), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Equal(t, dc[0].Name, "bridge") + }), + }, + { + Description: "custom", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", "custom") + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "remove", "custom") + }, + Command: test.RunCommand("network", "inspect", "custom"), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Equal(t, dc[0].Name, "custom") + }), + }, + { + Description: "match exact id", + Require: test.Not(test.Windows), + Command: func(data test.Data, helpers test.Helpers) test.Command { + id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) + return helpers.Command("network", "inspect", id) + }, + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Equal(t, dc[0].Name, "bridge") + }), + }, + { + Description: "match part of id", + Require: test.Not(test.Windows), + Command: func(data test.Data, helpers test.Helpers) test.Command { + id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) + return helpers.Command("network", "inspect", id[0:25]) + }, + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Equal(t, dc[0].Name, "bridge") + }), + }, + { + Description: "using another net short id", + Require: test.Not(test.Windows), + Setup: func(data test.Data, helpers test.Helpers) { + id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) + helpers.Ensure("network", "create", id[0:12]) + data.Set("netname", id[0:12]) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) + helpers.Anyhow("network", "remove", id[0:12]) + }, + Command: func(data test.Data, helpers test.Helpers) test.Command { + return helpers.Command("network", "inspect", data.Get("netname")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Equal(t, dc[0].Name, data.Get("netname")) + }, + } + }, + }, { Description: "Test network inspect", // IPAMConfig is not implemented on Windows yet @@ -88,16 +211,16 @@ func TestNetworkInspect(t *testing.T) { return &test.Expected{ ExitCode: 0, Output: func(stdout string, info string, t *testing.T) { - cmd := helpers.Command().Clear().WithBinary("nerdctl").WithArgs("--namespace", data.Identifier()) + cmd := helpers.CustomCommand("nerdctl", "--namespace", data.Identifier()) cmd.Clone().WithArgs("network", "inspect", data.Identifier()).Run(&test.Expected{ ExitCode: 1, - Errors: []error{errors.New("no such network")}, + Errors: []error{errors.New("no network found")}, }) cmd.Clone().WithArgs("network", "remove", data.Identifier()).Run(&test.Expected{ ExitCode: 1, - Errors: []error{errors.New("no such network")}, + Errors: []error{errors.New("no network found")}, }) cmd.Clone().WithArgs("network", "ls").Run(&test.Expected{ From 3e3517c22b8ae5c9cf7787bb5aa6a3a05f1f71af Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 4 Oct 2024 17:27:15 -0700 Subject: [PATCH 0805/1066] Remove images from Docker Hub from tests, fix #3498 Signed-off-by: apostasie --- cmd/nerdctl/container/container_run_test.go | 4 ++-- cmd/nerdctl/image/image_list_test.go | 16 ++++++++-------- pkg/testutil/testutil_linux.go | 1 + pkg/testutil/testutil_windows.go | 2 ++ 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/cmd/nerdctl/container/container_run_test.go b/cmd/nerdctl/container/container_run_test.go index d6d7f4a576f..d2e7ef79011 100644 --- a/cmd/nerdctl/container/container_run_test.go +++ b/cmd/nerdctl/container/container_run_test.go @@ -383,8 +383,8 @@ func TestRunWithLogBinary(t *testing.T) { imageName := testutil.Identifier(t) + "-image" containerName := testutil.Identifier(t) - const dockerfile = ` -FROM golang:latest as builder + var dockerfile = ` +FROM ` + testutil.GolangImage + ` as builder WORKDIR /go/src/ RUN mkdir -p logger WORKDIR /go/src/logger diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index fceb83a0426..3b3772fe292 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -95,12 +95,12 @@ LABEL version=0.1`, testutil.CommonImage) base.Cmd("build", "-t", tempName, "-f", buildCtx+"/Dockerfile", buildCtx).AssertOK() defer base.Cmd("rmi", tempName).AssertOK() - busyboxGlibc, busyboxUclibc := "busybox:glibc", "busybox:uclibc" - base.Cmd("pull", busyboxGlibc).AssertOK() - defer base.Cmd("rmi", busyboxGlibc).AssertOK() - - base.Cmd("pull", busyboxUclibc).AssertOK() - defer base.Cmd("rmi", busyboxUclibc).AssertOK() + // This test is about testing local filtering of image names - as such, we do not need remote images at all + taggedOne, taggedTwo := "taggedimage:xfoox", "taggedimage:yzfooyz" + base.Cmd("tag", testutil.CommonImage, taggedOne).Run() + base.Cmd("tag", testutil.CommonImage, taggedTwo).Run() + defer base.Cmd("rmi", taggedOne).AssertOK() + defer base.Cmd("rmi", taggedTwo).AssertOK() // before/since filters are not compatible with DOCKER_BUILDKIT=1? (but still compatible with DOCKER_BUILDKIT=0) if base.Target == testutil.Nerdctl { @@ -119,8 +119,8 @@ LABEL version=0.1`, testutil.CommonImage) base.Cmd("images", "--filter", "label=foo=bar", "--filter", "label=version=0.2").AssertOutNotContains(tempName) base.Cmd("images", "--filter", "label=version").AssertOutContains(tempName) base.Cmd("images", "--filter", fmt.Sprintf("reference=%s*", tempName)).AssertOutContains(tempName) - base.Cmd("images", "--filter", "reference=busy*:*libc*").AssertOutContains("glibc") - base.Cmd("images", "--filter", "reference=busy*:*libc*").AssertOutContains("uclibc") + base.Cmd("images", "--filter", "reference=tag*:*foo*").AssertOutContains("xfoox") + base.Cmd("images", "--filter", "reference=tag*:*foo*").AssertOutContains("yzfooyz") } func TestImagesFilterDangling(t *testing.T) { diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index dce9431e021..8c0cca4fdc8 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -43,6 +43,7 @@ var ( FluentdImage = "fluent/fluentd:v1.17.0-debian-1.0" KuboImage = mirrorOf("ipfs/kubo:v0.16.0") SystemdImage = "ghcr.io/containerd/stargz-snapshotter:0.15.1-kind" + GolangImage = mirrorOf("golang:1.18") // Source: https://gist.github.com/cpuguy83/fcf3041e5d8fb1bb5c340915aabeebe0 NonDistBlobImage = "ghcr.io/cpuguy83/non-dist-blob:latest" diff --git a/pkg/testutil/testutil_windows.go b/pkg/testutil/testutil_windows.go index 54bf1e05b25..edf86ba9143 100644 --- a/pkg/testutil/testutil_windows.go +++ b/pkg/testutil/testutil_windows.go @@ -43,6 +43,8 @@ const ( NginxAlpineImage = "registry.k8s.io/e2e-test-images/nginx:1.14-2" NginxAlpineIndexHTMLSnippet = "Welcome to nginx!" + GolangImage = "fixme-test-using-this-image-is-disabled-on-windows" + // This error string is expected when attempting to connect to a TCP socket // for a service which actively refuses the connection. // (e.g. attempting to connect using http to an https endpoint). From 7ff3c68aaf8a80dc599e589fd5c4e1778552384b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 22:53:29 +0000 Subject: [PATCH 0806/1066] build(deps): bump actions/checkout from 4.2.0 to 4.2.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.0 to 4.2.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.0...v4.2.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/project.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test-canary.yml | 8 ++++---- .github/workflows/test-kube.yml | 2 +- .github/workflows/test.yml | 20 +++++++++---------- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index dca7c9d1c0f..ebb35de53cb 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.2.0 + uses: actions/checkout@v4.2.1 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml index d9de8b3114e..a03da712e02 100644 --- a/.github/workflows/project.yml +++ b/.github/workflows/project.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 71c30eb3b9f..60117672325 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 - uses: actions/setup-go@v5 with: go-version: 1.23.x diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 90c96b71988..91b4cc06af4 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -19,7 +19,7 @@ jobs: runs-on: "ubuntu-24.04" timeout-minutes: 20 steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - name: Set GO env @@ -40,7 +40,7 @@ jobs: runs-on: "ubuntu-24.04" timeout-minutes: 40 steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -74,7 +74,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - name: Set GO env @@ -97,7 +97,7 @@ jobs: - run: go install ./cmd/nerdctl # This here is solely to get the cni install script, which has not been modified in 3+ years. # There is little to no reason to update this to latest containerd - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: repository: containerd/containerd ref: "v1.7.22" diff --git a/.github/workflows/test-kube.yml b/.github/workflows/test-kube.yml index d76ea903ca0..c8e2ccda405 100644 --- a/.github/workflows/test-kube.yml +++ b/.github/workflows/test-kube.yml @@ -18,7 +18,7 @@ jobs: runs-on: "ubuntu-24.04" timeout-minutes: 40 steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - name: "Run Kubernetes integration tests" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1bd3c674777..2fae92dcbfa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -78,7 +78,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -120,7 +120,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - name: Enable ipv4 and ipv6 forwarding @@ -207,7 +207,7 @@ jobs: } EOT sudo systemctl restart apparmor.service - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -244,7 +244,7 @@ jobs: matrix: go-version: ["1.22.x", "1.23.x"] steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -259,7 +259,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 45 steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -308,7 +308,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -317,7 +317,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 with: repository: containerd/containerd ref: v1.7.22 @@ -342,7 +342,7 @@ jobs: timeout-minutes: 20 steps: - - uses: actions/checkout@v4.2.0 + - uses: actions/checkout@v4.2.1 - uses: actions/cache@v4 with: path: /root/.vagrant.d From 456337f97fe1667c7a26c71582be97ce0d4f0f66 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Mon, 7 Oct 2024 23:38:33 +0000 Subject: [PATCH 0807/1066] Update runc (1.1.15) Signed-off-by: Austin Vazquez --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f825b4bc837..7e7d8b8554c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v2.0.0-rc.5 -ARG RUNC_VERSION=v1.1.14 +ARG RUNC_VERSION=v1.1.15 ARG CNI_PLUGINS_VERSION=v1.5.1 # Extra deps: Build From 93152fa8bb67963f659e2d7a4d8d0ad09587383b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Oct 2024 22:42:05 +0000 Subject: [PATCH 0808/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.2.0 to 2.3.0. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.2.0...v2.3.0) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f59fac3953e..c38990b8623 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.7 - github.com/compose-spec/compose-go/v2 v2.2.0 + github.com/compose-spec/compose-go/v2 v2.3.0 github.com/containerd/accelerated-container-image v1.2.2 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index dc101766143..ff24d78e156 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.2.0 h1:VsQosGhuO+H9wh5laiIiAe4TVd73kQ5NWwmNrdm0HRA= -github.com/compose-spec/compose-go/v2 v2.2.0/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.3.0 h1:5eomqgNcs/GqVknPtXF68V3muc67cOdXD35zCXn1aes= +github.com/compose-spec/compose-go/v2 v2.3.0/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.2 h1:GzBaFYyA3JFJGor9de1tX2aLSIG1vIewdNzJrcP3dco= github.com/containerd/accelerated-container-image v1.2.2/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= From 65363a664f20d631370e0c57ea359f28d9117821 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Oct 2024 22:42:11 +0000 Subject: [PATCH 0809/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.3.3 to 0.3.4. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Changelog](https://github.com/cyphar/filepath-securejoin/blob/main/CHANGELOG.md) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.3.3...v0.3.4) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f59fac3953e..57b77252226 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.8.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.3.3 + github.com/cyphar/filepath-securejoin v0.3.4 github.com/distribution/reference v0.6.0 github.com/docker/cli v27.3.1+incompatible github.com/docker/docker v27.3.1+incompatible diff --git a/go.sum b/go.sum index dc101766143..66823852f9f 100644 --- a/go.sum +++ b/go.sum @@ -78,8 +78,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.3.3 h1:lofZkCEVFIBe0KcdQOzFs8Soy9oaHOWl4gGtPI+gCFc= -github.com/cyphar/filepath-securejoin v0.3.3/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= +github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8= +github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= From 93fb53b0b4e9dfa80fae45bb1ffc583eecbd2469 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 8 Oct 2024 15:40:06 -0700 Subject: [PATCH 0810/1066] Enforce global lock in oci hooks Signed-off-by: apostasie --- pkg/ocihook/ocihook.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index ffa98041611..a98c84d1d37 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -39,6 +39,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/bypass4netnsutil" "github.com/containerd/nerdctl/v2/pkg/dnsutil/hostsstore" "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/lockutil" "github.com/containerd/nerdctl/v2/pkg/namestore" "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/containerd/nerdctl/v2/pkg/netutil/nettype" @@ -92,6 +93,26 @@ func Run(stdin io.Reader, stderr io.Writer, event, dataStore, cniPath, cniNetcon } }() + // FIXME: CNI plugins are not safe to use concurrently + // See + // https://github.com/containerd/nerdctl/issues/3518 + // https://github.com/containerd/nerdctl/issues/2908 + // and likely others + // Fixing these issues would require a lot of work, possibly even stopping using individual cni binaries altogether + // or at least being very mindful in what operation we call inside CNIEnv at what point, with filesystem locking. + // This below is a stopgap solution that just enforces a global lock + // Note this here is probably not enough, as concurrent CNI operations may happen outside of the scope of ocihooks + // through explicit calls to Remove, etc. + err = os.MkdirAll(cniNetconfPath, 0o700) + if err != nil { + return err + } + lock, err := lockutil.Lock(cniNetconfPath) + if err != nil { + return err + } + defer lockutil.Unlock(lock) + opts, err := newHandlerOpts(&state, dataStore, cniPath, cniNetconfPath) if err != nil { return err From 0e35a5356efb915ecdc4d2be5a7d8c30da1a24a3 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 6 Oct 2024 23:57:03 -0700 Subject: [PATCH 0811/1066] Test tooling iteration Simplifications: - no longer requires spurious Description for top-level tests - renamed test.RunCommand to test.Command - removed test.Group: inability to make the test not parallel, or specify requirements makes the abstraction too problematic, with not enough value - moved from interface test.Command (renamed to test.CustomizableCommand) to test.TestableCommand with a smaller footprint - specifically removing access to Clear and other methods - data.Identifier(id ...string) now allow optional string arguments, to generate multiple unique identifiers related to the test - data.System has been removed - no value - command customization hook and lifecycle is better - minor cleanups in testutil Enhancements: - overhauled Requirement API which now supports optional Setup/Cleanup routines - Config has been split out from Data, and is now available to Commands, and also on helpers - improved debugging output - a lot more Requirements implemented (stargz, ipfs, etc) - adopted + revamped and improved registry / kubo / cesanta code New: - new helpers to capture logs (eg: stderr) - hosts.toml testing code landed - introduction of more ambient requirements IsFlaky (+ flag -test.only-flaky), along with BrokenTest and NerdctlNeedsFixing markers, allowing to decorate tests with indications of what the problem is - platform stubs to help bridge away from platform specific test files (eg: *_linux_test) in favor of t.Skip - moved around some code in ./cmd/nerdctl/helpers for the same reasons Signed-off-by: apostasie --- cmd/nerdctl/helpers/testing.go | 105 +++++ cmd/nerdctl/helpers/testing_linux.go | 101 ----- docs/testing/tools.md | 153 +++++--- pkg/testutil/nerdtest/ambient.go | 31 ++ pkg/testutil/nerdtest/ca/ca.go | 162 ++++++++ pkg/testutil/nerdtest/command.go | 200 ++++++++++ pkg/testutil/nerdtest/hoststoml/hoststoml.go | 67 ++++ .../nerdtest/platform/platform_freebsd.go | 29 ++ .../nerdtest/platform/platform_linux.go | 33 ++ .../nerdtest/platform/platform_windows.go | 37 ++ pkg/testutil/nerdtest/registry/cesanta.go | 233 +++++++++++ pkg/testutil/nerdtest/registry/common.go | 108 +++++ pkg/testutil/nerdtest/registry/docker.go | 154 ++++++++ pkg/testutil/nerdtest/registry/kubo.go | 90 +++++ pkg/testutil/nerdtest/requirements.go | 368 +++++++++++++----- pkg/testutil/nerdtest/test.go | 149 ++----- pkg/testutil/nerdtest/third-party.go | 63 +++ .../nerdtest/{helpers.go => utilities.go} | 35 +- pkg/testutil/test/case.go | 228 ++++++----- pkg/testutil/test/command.go | 224 +++++++---- pkg/testutil/test/config.go | 71 ++++ pkg/testutil/test/data.go | 108 ++--- pkg/testutil/test/expected.go | 35 +- pkg/testutil/test/helpers.go | 84 +++- pkg/testutil/test/requirement.go | 125 +++--- pkg/testutil/test/test.go | 161 +++++--- pkg/testutil/test/utilities.go | 42 ++ pkg/testutil/testregistry/certsd_linux.go | 28 +- .../testregistry/testregistry_linux.go | 11 +- pkg/testutil/testutil.go | 12 + 30 files changed, 2393 insertions(+), 854 deletions(-) create mode 100644 pkg/testutil/nerdtest/ambient.go create mode 100644 pkg/testutil/nerdtest/ca/ca.go create mode 100644 pkg/testutil/nerdtest/command.go create mode 100644 pkg/testutil/nerdtest/hoststoml/hoststoml.go create mode 100644 pkg/testutil/nerdtest/platform/platform_freebsd.go create mode 100644 pkg/testutil/nerdtest/platform/platform_linux.go create mode 100644 pkg/testutil/nerdtest/platform/platform_windows.go create mode 100644 pkg/testutil/nerdtest/registry/cesanta.go create mode 100644 pkg/testutil/nerdtest/registry/common.go create mode 100644 pkg/testutil/nerdtest/registry/docker.go create mode 100644 pkg/testutil/nerdtest/registry/kubo.go create mode 100644 pkg/testutil/nerdtest/third-party.go rename pkg/testutil/nerdtest/{helpers.go => utilities.go} (83%) create mode 100644 pkg/testutil/test/config.go create mode 100644 pkg/testutil/test/utilities.go diff --git a/cmd/nerdctl/helpers/testing.go b/cmd/nerdctl/helpers/testing.go index a9c633faa13..c7f460b19a0 100644 --- a/cmd/nerdctl/helpers/testing.go +++ b/cmd/nerdctl/helpers/testing.go @@ -17,11 +17,22 @@ package helpers import ( + "context" + "encoding/json" + "errors" + "fmt" "os" + "os/exec" "path/filepath" "testing" "gotest.tools/v3/assert" + + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + + "github.com/containerd/nerdctl/v2/pkg/buildkitutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" ) func CreateBuildContext(t *testing.T, dockerfile string) string { @@ -30,3 +41,97 @@ func CreateBuildContext(t *testing.T, dockerfile string) string { assert.NilError(t, err) return tmpDir } + +func RmiAll(base *testutil.Base) { + base.T.Logf("Pruning images") + imageIDs := base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() + // remove empty output line at the end + imageIDs = imageIDs[:len(imageIDs)-1] + // use `Run` on purpose (same below) because `rmi all` may fail on individual + // image id that has an expected running container (e.g. a registry) + base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() + + base.T.Logf("Pruning build caches") + if _, err := buildkitutil.GetBuildkitHost(testutil.Namespace); err == nil { + base.Cmd("builder", "prune", "--force").AssertOK() + } + + // For BuildKit >= 0.11, pruning cache isn't enough to remove manifest blobs that are referred by build history blobs + // https://github.com/containerd/nerdctl/pull/1833 + if base.Target == testutil.Nerdctl { + base.T.Logf("Pruning all content blobs") + addr := base.ContainerdAddress() + client, err := containerd.New(addr, containerd.WithDefaultNamespace(testutil.Namespace)) + assert.NilError(base.T, err) + cs := client.ContentStore() + ctx := context.TODO() + wf := func(info content.Info) error { + base.T.Logf("Pruning blob %+v", info) + if err := cs.Delete(ctx, info.Digest); err != nil { + base.T.Log(err) + } + return nil + } + if err := cs.Walk(ctx, wf); err != nil { + base.T.Log(err) + } + + base.T.Logf("Pruning all images (again?)") + imageIDs = base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() + base.T.Logf("pruning following images: %+v", imageIDs) + base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() + } +} + +func ExtractDockerArchive(archiveTarPath, rootfsPath string) error { + if err := os.MkdirAll(rootfsPath, 0755); err != nil { + return err + } + workDir, err := os.MkdirTemp("", "extract-docker-archive") + if err != nil { + return err + } + defer os.RemoveAll(workDir) + if err := ExtractTarFile(workDir, archiveTarPath); err != nil { + return err + } + manifestJSONPath := filepath.Join(workDir, "manifest.json") + manifestJSONBytes, err := os.ReadFile(manifestJSONPath) + if err != nil { + return err + } + var mani DockerArchiveManifestJSON + if err := json.Unmarshal(manifestJSONBytes, &mani); err != nil { + return err + } + if len(mani) > 1 { + return fmt.Errorf("multi-image archive cannot be extracted: contains %d images", len(mani)) + } + if len(mani) < 1 { + return errors.New("invalid archive") + } + ent := mani[0] + for _, l := range ent.Layers { + layerTarPath := filepath.Join(workDir, l) + if err := ExtractTarFile(rootfsPath, layerTarPath); err != nil { + return err + } + } + return nil +} + +type DockerArchiveManifestJSON []DockerArchiveManifestJSONEntry + +type DockerArchiveManifestJSONEntry struct { + Config string + RepoTags []string + Layers []string +} + +func ExtractTarFile(dirPath, tarFilePath string) error { + cmd := exec.Command("tar", "Cxf", dirPath, tarFilePath) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to run %v: %q: %w", cmd.Args, string(out), err) + } + return nil +} diff --git a/cmd/nerdctl/helpers/testing_linux.go b/cmd/nerdctl/helpers/testing_linux.go index ec638021b11..c50e16ae06c 100644 --- a/cmd/nerdctl/helpers/testing_linux.go +++ b/cmd/nerdctl/helpers/testing_linux.go @@ -17,9 +17,6 @@ package helpers import ( - "context" - "encoding/json" - "errors" "fmt" "io" "net" @@ -32,10 +29,6 @@ import ( "gotest.tools/v3/assert" - containerd "github.com/containerd/containerd/v2/client" - "github.com/containerd/containerd/v2/core/content" - - "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" ) @@ -137,47 +130,6 @@ func NewCosignKeyPair(t testing.TB, path string, password string) *CosignKeyPair } } -func RmiAll(base *testutil.Base) { - base.T.Logf("Pruning images") - imageIDs := base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() - // remove empty output line at the end - imageIDs = imageIDs[:len(imageIDs)-1] - // use `Run` on purpose (same below) because `rmi all` may fail on individual - // image id that has an expected running container (e.g. a registry) - base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() - - base.T.Logf("Pruning build caches") - if _, err := buildkitutil.GetBuildkitHost(testutil.Namespace); err == nil { - base.Cmd("builder", "prune", "--force").AssertOK() - } - - // For BuildKit >= 0.11, pruning cache isn't enough to remove manifest blobs that are referred by build history blobs - // https://github.com/containerd/nerdctl/pull/1833 - if base.Target == testutil.Nerdctl { - base.T.Logf("Pruning all content blobs") - addr := base.ContainerdAddress() - client, err := containerd.New(addr, containerd.WithDefaultNamespace(testutil.Namespace)) - assert.NilError(base.T, err) - cs := client.ContentStore() - ctx := context.TODO() - wf := func(info content.Info) error { - base.T.Logf("Pruning blob %+v", info) - if err := cs.Delete(ctx, info.Digest); err != nil { - base.T.Log(err) - } - return nil - } - if err := cs.Walk(ctx, wf); err != nil { - base.T.Log(err) - } - - base.T.Logf("Pruning all images (again?)") - imageIDs = base.Cmd("images", "--no-trunc", "-a", "-q").OutLines() - base.T.Logf("pruning following images: %+v", imageIDs) - base.Cmd(append([]string{"rmi", "-f"}, imageIDs...)...).Run() - } -} - func ComposeUp(t *testing.T, base *testutil.Base, dockerComposeYAML string, opts ...string) { comp := testutil.NewComposeDir(t, dockerComposeYAML) defer comp.CleanUp() @@ -228,56 +180,3 @@ func ComposeUp(t *testing.T, base *testutil.Base, dockerComposeYAML string, opts base.Cmd("volume", "inspect", fmt.Sprintf("%s_db", projectName)).AssertFail() base.Cmd("network", "inspect", fmt.Sprintf("%s_default", projectName)).AssertFail() } - -func ExtractDockerArchive(archiveTarPath, rootfsPath string) error { - if err := os.MkdirAll(rootfsPath, 0755); err != nil { - return err - } - workDir, err := os.MkdirTemp("", "extract-docker-archive") - if err != nil { - return err - } - defer os.RemoveAll(workDir) - if err := ExtractTarFile(workDir, archiveTarPath); err != nil { - return err - } - manifestJSONPath := filepath.Join(workDir, "manifest.json") - manifestJSONBytes, err := os.ReadFile(manifestJSONPath) - if err != nil { - return err - } - var mani DockerArchiveManifestJSON - if err := json.Unmarshal(manifestJSONBytes, &mani); err != nil { - return err - } - if len(mani) > 1 { - return fmt.Errorf("multi-image archive cannot be extracted: contains %d images", len(mani)) - } - if len(mani) < 1 { - return errors.New("invalid archive") - } - ent := mani[0] - for _, l := range ent.Layers { - layerTarPath := filepath.Join(workDir, l) - if err := ExtractTarFile(rootfsPath, layerTarPath); err != nil { - return err - } - } - return nil -} - -type DockerArchiveManifestJSON []DockerArchiveManifestJSONEntry - -type DockerArchiveManifestJSONEntry struct { - Config string - RepoTags []string - Layers []string -} - -func ExtractTarFile(dirPath, tarFilePath string) error { - cmd := exec.Command("tar", "Cxf", dirPath, tarFilePath) - if out, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("failed to run %v: %q: %w", cmd.Args, string(out), err) - } - return nil -} diff --git a/docs/testing/tools.md b/docs/testing/tools.md index 36cee3c0510..66d416d25d6 100644 --- a/docs/testing/tools.md +++ b/docs/testing/tools.md @@ -28,17 +28,12 @@ import ( ) func TestMyThing(t *testing.T) { - nerdtest.Setup() - // Declare your test - myTest := &test.Case{ - Description: "A first test", - // This is going to run `nerdctl info` (or `docker info`) - Command: test.RunCommand("info"), - // Verify the command exits with 0, and stdout contains the word `Kernel` - Expected: test.Expects(0, nil, test.Contains("Kernel")), - } - + myTest := nerdtest.Setup() + // This is going to run `nerdctl info` (or `docker info`) + mytest.Command = test.Command("info") + // Verify the command exits with 0, and stdout contains the word `Kernel` + myTest.Expected = test.Expects(0, nil, test.Contains("Kernel")) // Run it myTest.Run(t) } @@ -53,7 +48,7 @@ You already saw two (`test.Expects` and `test.Contains`): First, `test.Expects(exitCode int, errors []error, outputCompare Comparator)`, which is convenient to quickly describe what you expect overall. -`exitCode` is obvious. +`exitCode` is obvious (note that passing -1 as an exit code will just verify the commands does fail without comparing the code). `errors` is a slice of go `error`, that allows you to compare what is seen on stderr with existing errors (for example: `errdefs.ErrNotFound`), or more generally @@ -62,13 +57,14 @@ any string you want to match. `outputCompare` can be either your own comparison function, or one of the comparison helper. -Secondly, `test.Contains`, is a `Comparator`. +Secondly, `test.Contains` - which is a `Comparator`. ### Comparators Besides `test.Contains(string)`, there are a few more: - `test.DoesNotContain(string)` - `test.Equals(string)` +- `test.Match(*regexp.Regexp)` - `test.All(comparators ...Comparator)`, which allows you to bundle together a bunch of other comparators The following example shows how to implement your own custom `Comparator` @@ -105,7 +101,7 @@ that is being used in the command or at other stages of your test (Setup). For example, creating a container with a certain name, you might want to verify that this name is then visible in the list of containers. -To achieve that, you should write your own `Expecter`, leveraging test `Data`. +To achieve that, you should write your own `Manager`, leveraging test `Data`. Here is an example, where we are using `data.Get("sometestdata")`. @@ -129,9 +125,8 @@ func TestMyThing(t *testing.T) { // Declare your test myTest := &test.Case{ - Description: "A subtest with custom data, manager, and comparator", Data: test.WithData("sometestdata", "blah"), - Command: test.RunCommand("info"), + Command: test.Command("info"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ ExitCode: 1, @@ -152,28 +147,41 @@ func TestMyThing(t *testing.T) { ## On `Data` -`Data` is provided to first allow storing mutable key-value information that pertain to the test. +`Data` is provided to allow storing mutable key-value information that pertain to the test. -While it can be provided through `WithData(key string, value string)` (or `WithConfig`, see below), +While it can be provided through `test.WithData(key string, value string)`, inside the testcase definition, it can also be dynamically manipulated inside `Setup`, or `Command`. Note that `Data` additionally exposes the following functions: -- `Identifier()` which returns the unique id associated with the _current_ test (or subtest) +- `Identifier(words ...string)` which returns a unique identifier associated with the _current_ test (or subtest) - `TempDir()` which returns the private, temporary directory associated with the test ... along with the `Get(key)` and `Set(key, value)` methods. -Secondly, `Data` allows defining and manipulating "configuration" data. +Note that Data is copied down to subtests, which is convenient to pass "down" +information relevant to a bunch of subtests (eg: like a registry IP). + +## On Config + +`Config` is similar to `Data`, although it is meant specifically for predefined +keys that impact the base behavior of the binary you are testing. -In the case of nerdctl here, the following configuration options are defined: -- `WithConfig(NerdctlToml, "foo")` which allows specifying a custom config -- `WithConfig(DataRoot, "foo")` allowing to point to a custom data-root -- `WithConfig(HostsDir, "foo")` to point to a specific hosts directory -- `WithConfig(Namespace, "foo")` allows passing a specific namespace (otherwise defaults to `nerdctl-test`) +You can initiate your config using `test.WithConfig(key, value)`, and you can +manipulate it further using `helpers.Read` and`helpers.Write`. + +Currently, the following keys are defined: +- `DockerConfig` allowing to set custom content for the `$DOCKER_CONFIG/config.json` file +- `Namespace` (default to `nerdctl-test` if unspecified, but see "mode private") +- `NerdctlToml` to set custom content for the `$NERDCTL_TOML` file +- `HostsDir` to specify the value of the arg `--hosts-dir` +- `DataRoot` to specify the value of the arg `--data-root` +- `Debug` to enable debug (works for both nerdctl and docker) + +Note that config defined on the test case is copied over for subtests. ## Commands -For simple cases, `test.RunCommand(args ...string)` is the way to go. +For simple cases, `test.Command(args ...string)` is the way to go. It will execute the binary to test (nerdctl or docker), with the provided arguments, and will by default get cwd inside the temporary directory associated with the test. @@ -189,8 +197,7 @@ your setup and cleanup routines (see below). If you would like to override the environment specifically for a command, but not for others (eg: in `Setup` or `Cleanup`), you can do so with custom commands (see below). -Note that environment as defined statically in the test will be inherited by subtests, -unless explicitly overridden. +Note that environment as defined statically in the test will be copied over for subtests. ### Working directory @@ -199,9 +206,9 @@ of the test. This behavior can be overridden using custom commands. -### Custom commands +### Custom Executor -Custom commands allow you to manipulate test `Data`, override important aspects +Custom `Executor`s allow you to manipulate test `Data`, override important aspects of the command to execute (`Env`, `WorkingDir`), or otherwise give you full control on what the command does. @@ -227,10 +234,9 @@ func TestMyThing(t *testing.T) { // Declare your test myTest := &test.Case{ - Description: "A subtest with custom data, manager, and comparator", Data: test.WithData("sometestdata", "blah"), - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("run", "--name", data.Identifier()+data.Get("sometestdata")) + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--name", data.Get("sometestdata")) }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ @@ -250,24 +256,35 @@ func TestMyThing(t *testing.T) { } ``` +Note that inside your `Executor` you do have access to the full palette of command options, +including: +- `Background(timeout time.Duration)` which allows you to background a command execution +- `WithWrapper(binary string, args ...string)` which allows you to "wrap" your command with another binary +- `WithStdin(io.Reader)` which allows you to pass a reader to the command stdin +- `WithCwd(string)` which allows you to specify the working directory (default to the test temp directory) +- `Clone()` which returns a copy of the command, with env, cwd, etc + +and also `WithBinary` and `WithArgs`. + ### On `helpers` Inside a custom `Executor`, `Manager`, or `Butler`, you have access to a collection of `helpers` to simplify command execution: -- `helpers.Ensure(args ...string)` will run a command and ensure it exits succesfully +- `helpers.Ensure(args ...string)` will run a command and ensure it exits successfully - `helpers.Fail(args ...string)` will run a command and ensure it fails - `helpers.Anyhow(args ...string)` will run a command but does not care if it succeeds or fails - `helpers.Capture(args ...string)` will run a command, ensure it is successful, and return the output - `helpers.Command(args ...string)` will return a command that can then be tested against expectations -- `helpers.CustomCommand(binary string, args ...string)` will do the same for any arbitrary command (not limited to nerdctl) +- `helpers.Custom(binary string, args ...string)` will do the same for any arbitrary command (not limited to nerdctl) +- `helpers.T()` which returns the appropriate `*testing.T` for your context ## Setup and Cleanup Tests routinely require a set of actions to be performed _before_ you can run the command you want to test. A setup routine will get executed before your `Command`, and have access to and can -manipulate your test `Data`. +manipulate your test `Data` and `Config`. Conversely, you very likely want to clean things up once your test is done. While temporary directories are cleaned for you with no action needed on your part, @@ -296,7 +313,6 @@ func TestMyThing(t *testing.T) { // Declare your test myTest := &test.Case{ - Description: "A subtest with custom data, manager, and comparator", Data: test.WithData("sometestdata", "blah"), Setup: func(data *test.Data, helpers test.Helpers){ helpers.Ensure("volume", "create", "foo") @@ -306,7 +322,7 @@ func TestMyThing(t *testing.T) { helpers.Anyhow("volume", "rm", "foo") helpers.Anyhow("volume", "rm", "bar") }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("run", "--name", data.Identifier()+data.Get("sometestdata")) }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { @@ -331,23 +347,13 @@ func TestMyThing(t *testing.T) { Subtests are just regular tests, attached to the `SubTests` slice of a test. -Note that a subtest will inherit its parent `Data` and `Env`, in the state they are at +Note that a subtest will inherit its parent `Data`, `Config` and `Env`, in the state they are at after the parent test has run its `Setup` and `Command` routines (but before `Cleanup`). -This does _not_ apply to `Identifier()` and `TempDir()`, which are unique to the sub-test. +This does _not_ apply to `Identifier()` and `TempDir()`, which are unique to the subtest. Also note that a test does not have to have a `Command`. This is a convenient pattern if you just need a common `Setup` for a bunch of subtests. -## Groups - -A `test.Group` is just a convenient way to represent a slice of tests. - -Note that unlike a `test.Case`, a group cannot define properties inherited by -subtests, nor `Setup` or `Cleanup` routines. - -- if you just have a bunch of subtests you want to run, put them in a `test.Group` -- if you want to have a global setup, or otherwise set a common property first for your subtests, use a `test.Case` with `SubTests` - ## Parallelism All tests (and subtests) are assumed to be parallelizable. @@ -362,6 +368,9 @@ Note that if you want better isolation, it is usually better to use the requirem `test.Case` has a `Require` property that allow enforcing specific, per-test requirements. +A `Requirement` is expected to make you `Skip` tests when the environment does not match +expectations. + Here are a few: ```go test.Windows // a test runs only on Windows (or Not(Windows)) @@ -374,31 +383,53 @@ test.Require(req ...Requirement) // a test runs only if all requirements are ful nerdtest.Docker // a test only run on Docker - normally used with test.Not(nerdtest.Docker) nerdtest.Soci // a test requires the soci snapshotter -nerdtest.Rootless // a test requires Rootless (or Not(Rootless), indicating it requires Rootful) +nerdtest.Stargz // a test requires the stargz snapshotter +nerdtest.Rootless // a test requires Rootless +nerdtest.RootFul // a test requires Rootful nerdtest.Build // a test requires buildkit nerdtest.CGroup // a test requires cgroup -nerdtest.OnlyIPv6 // a test is meant to run solely in the ipv6 environment nerdtest.NerdctlNeedsFixing // indicates that a test cannot be run on nerdctl yet as a fix is required +nerdtest.BrokenTest // indicates that a test needs to be fixed and has been restricted to run only in certain cases +nerdtest.OnlyIPv6 // a test is meant to run solely in the ipv6 environment +nerdtest.OnlyKubernetes // a test is meant to run solely in the Kubernetes environment +nerdtest.IsFlaky // indicates that a test will fail in a flaky way - this may be the test fault, or more likely something racy in nerdctl nerdtest.Private // see below ``` ### About `nerdtest.Private` -While all requirements above are self-descriptive or obvious, and are going to skip -tests for environments that do not match the requirements, `nerdtest.Private` is a +While all requirements above are self-descriptive or obvious, `nerdtest.Private` is a special case. -What it does when required is: create a private namespace, data-root, hosts-dir, nerdctl.toml and -DOCKER_CONFIG that is private to the test. - -Note that subtests are going to inherit that environment as well. +If set, it will run tests inside a dedicated namespace that is private to the test. +Note that subtests by default are going to be set in that same namespace, unless they +ask for private as well, or they reset the `Namespace` config key. -If the target is Docker - which does not support namespaces for eg - asking for `private` -will merely disable parallelization. +If the target is Docker - which does not support namespaces - asking for `Private` +will disable parallelization. The purpose of private is to provide a truly clean-room environment for tests -that are guaranteed to have side effects on others, or that do require an exclusive, pristine +that are going to have side effects on others, or that do require an exclusive, pristine environment. Using private is generally preferable to disabling parallelization, as doing the latter -would slow down the run and won't have the same guarantees about the environment. +would slow down the run and won't have the same isolation guarantees about the environment. + +## Advanced command customization + +Testing any non-trivial binary likely assume a good amount of custom code +to set up the right default behavior wrt environment, flags, etc. + +To do that, you can pass a `test.Testable` implementation to the `test.Customize` method. + +It basically lets you define your own `CustomizableCommand`, along with a hook to deal with +ambient requirements that is run after `test.Require` and before `test.Setup`. + +`CustomizableCommand` are typically embedding a `test.GenericCommand` and overriding both the +`Run` and `Clone` methods. + +Check the `nerdtest` implementation for details. + +## Utilities + +TBD \ No newline at end of file diff --git a/pkg/testutil/nerdtest/ambient.go b/pkg/testutil/nerdtest/ambient.go new file mode 100644 index 00000000000..d59ebc6a18e --- /dev/null +++ b/pkg/testutil/nerdtest/ambient.go @@ -0,0 +1,31 @@ +/* + 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 nerdtest + +import "github.com/containerd/nerdctl/v2/pkg/testutil" + +func environmentHasIPv6() bool { + return testutil.GetEnableIPv6() +} + +func environmentHasKubernetes() bool { + return testutil.GetEnableKubernetes() +} + +func environmentIsForFlaky() bool { + return testutil.GetFlakyEnvironment() +} diff --git a/pkg/testutil/nerdtest/ca/ca.go b/pkg/testutil/nerdtest/ca/ca.go new file mode 100644 index 00000000000..da367d464e1 --- /dev/null +++ b/pkg/testutil/nerdtest/ca/ca.go @@ -0,0 +1,162 @@ +/* + 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 ca + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "net" + "os" + "path/filepath" + "testing" + "time" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +type CA struct { + KeyPath string + CertPath string + + t *testing.T + key *rsa.PrivateKey + cert *x509.Certificate + closeF func() error +} + +func (ca *CA) Close() error { + return ca.closeF() +} + +const keyLength = 4096 + +func New(data test.Data, t *testing.T) *CA { + key, err := rsa.GenerateKey(rand.Reader, keyLength) + assert.NilError(t, err) + + cert := &x509.Certificate{ + SerialNumber: serialNumber(t), + Subject: pkix.Name{ + Organization: []string{"nerdctl test organization"}, + CommonName: fmt.Sprintf("nerdctl CA (%s)", t.Name()), + }, + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + IsCA: true, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + BasicConstraintsValid: true, + } + + dir, err := os.MkdirTemp(data.TempDir(), "ca") + assert.NilError(t, err) + keyPath := filepath.Join(dir, "ca.key") + certPath := filepath.Join(dir, "ca.cert") + writePair(t, keyPath, certPath, cert, cert, key, key) + + return &CA{ + KeyPath: keyPath, + CertPath: certPath, + t: t, + key: key, + cert: cert, + closeF: func() error { + return os.RemoveAll(dir) + }, + } +} + +type Cert struct { + KeyPath string + CertPath string + closeF func() error +} + +func (c *Cert) Close() error { + return c.closeF() +} + +func (ca *CA) NewCert(host string, additional ...string) *Cert { + t := ca.t + + key, err := rsa.GenerateKey(rand.Reader, keyLength) + assert.NilError(t, err) + + additional = append([]string{host}, additional...) + + cert := &x509.Certificate{ + SerialNumber: serialNumber(t), + Subject: pkix.Name{ + Organization: []string{"nerdctl test organization"}, + CommonName: fmt.Sprintf("nerdctl %s (%s)", host, t.Name()), + }, + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + KeyUsage: x509.KeyUsageCRLSign, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + DNSNames: additional, + } + for _, h := range additional { + if ip := net.ParseIP(h); ip != nil { + cert.IPAddresses = append(cert.IPAddresses, ip) + } + } + + dir, err := os.MkdirTemp(t.TempDir(), "cert") + assert.NilError(t, err) + certPath := filepath.Join(dir, "a.cert") + keyPath := filepath.Join(dir, "a.key") + writePair(t, keyPath, certPath, cert, ca.cert, key, ca.key) + + return &Cert{ + CertPath: certPath, + KeyPath: keyPath, + closeF: func() error { + return os.RemoveAll(dir) + }, + } +} + +func writePair(t *testing.T, keyPath, certPath string, cert, caCert *x509.Certificate, key, caKey *rsa.PrivateKey) { + keyF, err := os.Create(keyPath) + assert.NilError(t, err) + defer keyF.Close() + assert.NilError(t, pem.Encode(keyF, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})) + assert.NilError(t, keyF.Close()) + + certB, err := x509.CreateCertificate(rand.Reader, cert, caCert, &key.PublicKey, caKey) + assert.NilError(t, err) + certF, err := os.Create(certPath) + assert.NilError(t, err) + defer certF.Close() + assert.NilError(t, pem.Encode(certF, &pem.Block{Type: "CERTIFICATE", Bytes: certB})) + assert.NilError(t, certF.Close()) +} + +func serialNumber(t *testing.T) *big.Int { + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 60) + sn, err := rand.Int(rand.Reader, serialNumberLimit) + assert.NilError(t, err) + return sn +} diff --git a/pkg/testutil/nerdtest/command.go b/pkg/testutil/nerdtest/command.go new file mode 100644 index 00000000000..99fb0e3b0f5 --- /dev/null +++ b/pkg/testutil/nerdtest/command.go @@ -0,0 +1,200 @@ +/* + 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 nerdtest + +import ( + "os" + "os/exec" + "path/filepath" + "testing" + "time" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/platform" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +const defaultNamespace = testutil.Namespace + +// IMPORTANT note on file writing here: +// Inside the context of a single test, there is no concurrency, as setup, command and cleanup operate in sequence +// Furthermore, the tempdir is private by definition. +// Writing files here in a non-safe manner is thus OK. +type target = string + +const ( + targetNerdctl = target("nerdctl") + targetDocker = target("docker") +) + +func getTarget() string { + // Indirecting to testutil for now + return testutil.GetTarget() +} + +func newNerdCommand(conf test.Config, t *testing.T) *nerdCommand { + // Decide what binary we are running + var err error + var binary string + trgt := getTarget() + switch trgt { + case targetNerdctl: + binary, err = exec.LookPath(trgt) + if err != nil { + t.Fatalf("unable to find binary %q: %v", trgt, err) + } + // Set the default namespace if we do not have something already + if conf.Read(Namespace) == "" { + conf.Write(Namespace, defaultNamespace) + } + case targetDocker: + binary, err = exec.LookPath(trgt) + if err != nil { + t.Fatalf("unable to find binary %q: %v", trgt, err) + } + if err = exec.Command("docker", "compose", "version").Run(); err != nil { + t.Fatalf("docker does not support compose: %v", err) + } + default: + t.Fatalf("unknown target %q", getTarget()) + } + + // Create the base command, with the right binary, t + ret := &nerdCommand{} + ret.WithBinary(binary) + // Not interested in these - and insulate us from parent environment side effects + ret.WithBlacklist([]string{ + "LS_COLORS", + "DOCKER_CONFIG", + "CONTAINERD_SNAPSHOTTER", + "NERDCTL_TOML", + "CONTAINERD_ADDRESS", + "CNI_PATH", + "NETCONFPATH", + "NERDCTL_EXPERIMENTAL", + "NERDCTL_HOST_GATEWAY_IP", + }) + return ret +} + +type nerdCommand struct { + test.GenericCommand + + hasWrittenToml bool + hasWrittenDockerConfig bool +} + +func (nc *nerdCommand) Run(expect *test.Expected) { + nc.prep() + if getTarget() == targetDocker { + // We are not in the business of testing docker *error* output, so, spay expectation here + if expect != nil { + expect.Errors = nil + } + } + nc.GenericCommand.Run(expect) +} + +func (nc *nerdCommand) Background(timeout time.Duration) { + nc.prep() + nc.GenericCommand.Background(timeout) +} + +// Run does override the generic command run, as we are testing both docker and nerdctl +func (nc *nerdCommand) prep() { + nc.T().Helper() + + // If no DOCKER_CONFIG was explicitly provided, set ourselves inside the current working directory + if nc.Env["DOCKER_CONFIG"] == "" { + nc.Env["DOCKER_CONFIG"] = nc.GenericCommand.TempDir + } + + if customDCConfig := nc.GenericCommand.Config.Read(DockerConfig); customDCConfig != "" { + if !nc.hasWrittenDockerConfig { + dest := filepath.Join(nc.Env["DOCKER_CONFIG"], "config.json") + err := os.WriteFile(dest, []byte(customDCConfig), 0400) + assert.NilError(nc.T(), err, "failed to write custom docker config json file for test") + nc.hasWrittenDockerConfig = true + } + } + + if getTarget() == targetDocker { + // Allow debugging with docker syntax + if nc.Config.Read(Debug) != "" { + nc.PrependArgs("--log-level=debug") + } + } else if getTarget() == targetNerdctl { + // Set the namespace + if nc.Config.Read(Namespace) != "" { + nc.PrependArgs("--namespace=" + string(nc.Config.Read(Namespace))) + } + + if nc.Config.Read(stargz) == enabled { + nc.Env["CONTAINERD_SNAPSHOTTER"] = "stargz" + } + + if nc.Config.Read(ipfs) == enabled { + var ipfsPath string + if rootlessutil.IsRootless() { + var err error + ipfsPath, err = platform.DataHome() + ipfsPath = filepath.Join(ipfsPath, "ipfs") + assert.NilError(nc.T(), err) + } else { + ipfsPath = filepath.Join(os.Getenv("HOME"), ".ipfs") + } + + nc.Env["IPFS_PATH"] = ipfsPath + } + + // If no NERDCTL_TOML was explicitly provided, set it to the private dir + if nc.Env["NERDCTL_TOML"] == "" { + nc.Env["NERDCTL_TOML"] = filepath.Join(nc.GenericCommand.TempDir, "nerdctl.toml") + } + + // If we have custom toml content, write it if it does not exist already + if nc.Config.Read(NerdctlToml) != "" { + if !nc.hasWrittenToml { + dest := nc.Env["NERDCTL_TOML"] + err := os.WriteFile(dest, []byte(nc.Config.Read(NerdctlToml)), 0400) + assert.NilError(nc.T(), err, "failed to write NerdctlToml") + nc.hasWrittenToml = true + } + } + + if nc.Config.Read(HostsDir) != "" { + nc.PrependArgs("--hosts-dir=" + string(nc.Config.Read(HostsDir))) + } + if nc.Config.Read(DataRoot) != "" { + nc.PrependArgs("--data-root=" + string(nc.Config.Read(DataRoot))) + } + if nc.Config.Read(Debug) != "" { + nc.PrependArgs("--debug-full") + } + } +} + +func (nc *nerdCommand) Clone() test.TestableCommand { + return &nerdCommand{ + GenericCommand: *(nc.GenericCommand.Clone().(*test.GenericCommand)), + hasWrittenToml: nc.hasWrittenToml, + hasWrittenDockerConfig: nc.hasWrittenDockerConfig, + } +} diff --git a/pkg/testutil/nerdtest/hoststoml/hoststoml.go b/pkg/testutil/nerdtest/hoststoml/hoststoml.go new file mode 100644 index 00000000000..f6ae48b1247 --- /dev/null +++ b/pkg/testutil/nerdtest/hoststoml/hoststoml.go @@ -0,0 +1,67 @@ +/* + 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 hoststoml + +import ( + "net" + "os" + "path/filepath" + "strconv" + + "github.com/pelletier/go-toml/v2" +) + +type hostsTomlHost struct { + CA string `toml:"ca,omitempty"` + SkipVerify bool `toml:"skip_verify,omitempty"` + Client [][]string `toml:"client,omitempty"` +} + +// See https://github.com/containerd/containerd/blob/main/docs/hosts.md +type HostsToml struct { + CA string `toml:"ca,omitempty"` + SkipVerify bool `toml:"skip_verify,omitempty"` + Client [][]string `toml:"client,omitempty"` + Headers map[string]string `toml:"header,omitempty"` + Server string `toml:"server,omitempty"` + Endpoints map[string]*hostsTomlHost `toml:"host,omitempty"` +} + +func (ht *HostsToml) Save(dir string, hostIP string, port int) error { + var err error + var r *os.File + + hostSubDir := hostIP + if port != 0 { + hostSubDir = net.JoinHostPort(hostIP, strconv.Itoa(port)) + } + + hostsSubDir := filepath.Join(dir, hostSubDir) + err = os.MkdirAll(hostsSubDir, 0700) + if err != nil { + return err + } + + if r, err = os.Create(filepath.Join(dir, hostSubDir, "hosts.toml")); err == nil { + defer r.Close() + enc := toml.NewEncoder(r) + enc.SetIndentTables(true) + err = enc.Encode(ht) + } + + return err +} diff --git a/pkg/testutil/nerdtest/platform/platform_freebsd.go b/pkg/testutil/nerdtest/platform/platform_freebsd.go new file mode 100644 index 00000000000..8128c930167 --- /dev/null +++ b/pkg/testutil/nerdtest/platform/platform_freebsd.go @@ -0,0 +1,29 @@ +/* + 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 platform + +func DataHome() (string, error) { + panic("not supported") +} + +var ( + // The following are here solely for freebsd to compile / lint. They are not used, as the corresponding tests are running only on linux. + RegistryImageStable = "registry:2" + RegistryImageNext = "ghcr.io/distribution/distribution:" + KuboImage = "ipfs/kubo:v0.16.0" + DockerAuthImage = "cesanta/docker_auth:1.7" +) diff --git a/pkg/testutil/nerdtest/platform/platform_linux.go b/pkg/testutil/nerdtest/platform/platform_linux.go new file mode 100644 index 00000000000..3aeeb0f03c8 --- /dev/null +++ b/pkg/testutil/nerdtest/platform/platform_linux.go @@ -0,0 +1,33 @@ +/* + 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 platform + +import ( + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func DataHome() (string, error) { + return rootlessutil.XDGDataHome() +} + +var ( + RegistryImageStable = testutil.RegistryImageStable + RegistryImageNext = testutil.RegistryImageNext + KuboImage = testutil.KuboImage + DockerAuthImage = testutil.DockerAuthImage +) diff --git a/pkg/testutil/nerdtest/platform/platform_windows.go b/pkg/testutil/nerdtest/platform/platform_windows.go new file mode 100644 index 00000000000..56be8501931 --- /dev/null +++ b/pkg/testutil/nerdtest/platform/platform_windows.go @@ -0,0 +1,37 @@ +/* + 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 platform + +import ( + "fmt" +) + +func DataHome() (string, error) { + panic("not supported") +} + +// The following are here solely for windows to compile. They are not used, as the corresponding tests are running only on linux. +func mirrorOf(s string) string { + return fmt.Sprintf("ghcr.io/stargz-containers/%s-org", s) +} + +var ( + RegistryImageStable = mirrorOf("registry:2") + RegistryImageNext = "ghcr.io/distribution/distribution:" + KuboImage = mirrorOf("ipfs/kubo:v0.16.0") + DockerAuthImage = mirrorOf("cesanta/docker_auth:1.7") +) diff --git a/pkg/testutil/nerdtest/registry/cesanta.go b/pkg/testutil/nerdtest/registry/cesanta.go new file mode 100644 index 00000000000..b8924e8c369 --- /dev/null +++ b/pkg/testutil/nerdtest/registry/cesanta.go @@ -0,0 +1,233 @@ +/* + 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 registry + +import ( + "encoding/json" + "fmt" + "net" + "os" + "strconv" + "testing" + "time" + + "golang.org/x/crypto/bcrypt" + "gopkg.in/yaml.v3" + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/ca" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/platform" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/portlock" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +type CesantaConfigServer struct { + Addr string `yaml:"addr,omitempty"` + Certificate string + Key string +} + +type CesantaConfigToken struct { + Issuer string `yaml:"issuer,omitempty"` + Certificate string `yaml:"certificate,omitempty"` + Key string `yaml:"key,omitempty"` + Expiration int `yaml:"expiration,omitempty"` +} + +type CesantaConfigUser struct { + Password string `yaml:"password,omitempty"` +} + +type CesantaMatchConditions struct { + Account string `yaml:"account,omitempty"` +} + +type CesantaConfigACLEntry struct { + Match CesantaMatchConditions `yaml:"match"` + Actions []string `yaml:"actions,flow"` +} + +type CesantaConfigACL []CesantaConfigACLEntry + +type CesantaConfig struct { + Server CesantaConfigServer `yaml:"server"` + Token CesantaConfigToken `yaml:"token"` + Users map[string]CesantaConfigUser `yaml:"users,omitempty"` + ACL CesantaConfigACL `yaml:"acl,omitempty"` +} + +func (cc *CesantaConfig) Save(path string) error { + var err error + var r *os.File + if r, err = os.Create(path); err == nil { + defer r.Close() + err = yaml.NewEncoder(r).Encode(cc) + } + return err +} + +func ensureContainerStarted(helpers test.Helpers, con string) { + const maxRetry = 5 + const sleep = time.Second + success := false + for i := 0; i < maxRetry && !success; i++ { + time.Sleep(sleep) + count := i + cmd := helpers.Command("container", "inspect", con) + cmd.Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Container + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + if dc[0].State.Running { + success = true + return + } + if count == maxRetry-1 { + // FIXME: there is currently no simple way to capture stderr + // Sometimes, it is convenient for debugging, like here + // Here we cheat with unbuffer which will bundle stderr and stdout together + // This is just bad + t.Error(helpers.Err("logs", con)) + t.Fatalf("container %s still not running after %d retries", con, count) + } + }, + }) + } +} + +func NewCesantaAuthServer(data test.Data, helpers test.Helpers, ca *ca.CA, port int, user, pass string, tls bool) *TokenAuthServer { + // listen on 0.0.0.0 to enable 127.0.0.1 + listenIP := net.ParseIP("0.0.0.0") + hostIP, err := nettestutil.NonLoopbackIPv4() + assert.NilError(helpers.T(), err, fmt.Errorf("failed finding ipv4 non loopback interface: %w", err)) + bpass, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) + assert.NilError(helpers.T(), err, fmt.Errorf("failed bcrypt encrypting password: %w", err)) + // Prepare configuration file for authentication server + // Details: https://github.com/cesanta/docker_auth/blob/1.7.1/examples/simple.yml + configFile, err := os.CreateTemp(data.TempDir(), "authconfig") + assert.NilError(helpers.T(), err, fmt.Errorf("failed creating temporary directory for config file: %w", err)) + configFileName := configFile.Name() + + cc := &CesantaConfig{ + Server: CesantaConfigServer{ + Addr: ":5100", + }, + Token: CesantaConfigToken{ + Issuer: "Cesanta auth server", + Expiration: 900, + }, + Users: map[string]CesantaConfigUser{ + user: { + Password: string(bpass), + }, + }, + ACL: CesantaConfigACL{ + { + Match: CesantaMatchConditions{ + Account: user, + }, + Actions: []string{"*"}, + }, + }, + } + + scheme := "http" + if tls { + scheme = "https" + cc.Server.Certificate = "/auth/domain.crt" + cc.Server.Key = "/auth/domain.key" + } else { + cc.Token.Certificate = "/auth/domain.crt" + cc.Token.Key = "/auth/domain.key" + } + + err = cc.Save(configFileName) + assert.NilError(helpers.T(), err, fmt.Errorf("failed writing configuration: %w", err)) + + cert := ca.NewCert(hostIP.String()) + // FIXME: this will fail in many circumstances. Review strategy on how to acquire a free port. + // We probably have better code for that already somewhere. + port, err = portlock.Acquire(port) + assert.NilError(helpers.T(), err, fmt.Errorf("failed acquiring port: %w", err)) + containerName := data.Identifier(fmt.Sprintf("cesanta-auth-server-%d-%t", port, tls)) + // Cleanup possible leftovers first + helpers.Ensure("rm", "-f", containerName) + + cleanup := func(data test.Data, helpers test.Helpers) { + helpers.Ensure("rm", "-f", containerName) + errPortRelease := portlock.Release(port) + errCertClose := cert.Close() + errConfigClose := configFile.Close() + errConfigRemove := os.Remove(configFileName) + if errPortRelease != nil { + helpers.T().Error(errPortRelease.Error()) + } + if errCertClose != nil { + helpers.T().Error(errCertClose.Error()) + } + if errConfigClose != nil { + helpers.T().Error(errConfigClose.Error()) + } + if errConfigRemove != nil { + helpers.T().Error(errConfigRemove.Error()) + } + } + + setup := func(data test.Data, helpers test.Helpers) { + helpers.Ensure( + "run", + "--pull=never", + "-d", + "-p", fmt.Sprintf("%s:%d:5100", listenIP, port), + "--name", containerName, + "-v", cert.CertPath+":/auth/domain.crt", + "-v", cert.KeyPath+":/auth/domain.key", + "-v", configFileName+":/config/auth_config.yml", + platform.DockerAuthImage, + "/config/auth_config.yml", + ) + ensureContainerStarted(helpers, containerName) + _, err = nettestutil.HTTPGet(fmt.Sprintf("%s://%s/auth", + scheme, + net.JoinHostPort(hostIP.String(), strconv.Itoa(port)), + ), + 10, + true) + assert.NilError(helpers.T(), err, fmt.Errorf("failed starting auth container in a timely manner: %w", err)) + + } + + return &TokenAuthServer{ + IP: hostIP, + Port: port, + Scheme: scheme, + CertPath: cert.CertPath, + Auth: &TokenAuth{ + Address: scheme + "://" + net.JoinHostPort(hostIP.String(), strconv.Itoa(port)), + CertPath: cert.CertPath, + }, + Setup: setup, + Cleanup: cleanup, + Logs: func(data test.Data, helpers test.Helpers) { + helpers.T().Error(helpers.Err("logs", containerName)) + }, + } +} diff --git a/pkg/testutil/nerdtest/registry/common.go b/pkg/testutil/nerdtest/registry/common.go new file mode 100644 index 00000000000..0f7496b049a --- /dev/null +++ b/pkg/testutil/nerdtest/registry/common.go @@ -0,0 +1,108 @@ +/* + 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 registry + +import ( + "fmt" + "net" + "os" + "path/filepath" + + "golang.org/x/crypto/bcrypt" + + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +// Auth describes a struct able to serialize authenticator information into arguments to be fed to a registry container run +type Auth interface { + Params(data test.Data) []string +} + +type NoAuth struct { +} + +func (na *NoAuth) Params(data test.Data) []string { + return []string{} +} + +type TokenAuth struct { + Address string + CertPath string +} + +// FIXME: this is specific to Docker Registry +// Like need something else for Harbor and Gitlab +func (ta *TokenAuth) Params(data test.Data) []string { + return []string{ + "--env", "REGISTRY_AUTH=token", + "--env", "REGISTRY_AUTH_TOKEN_REALM=" + ta.Address + "/auth", + "--env", "REGISTRY_AUTH_TOKEN_SERVICE=Docker registry", + "--env", "REGISTRY_AUTH_TOKEN_ISSUER=Cesanta auth server", + "--env", "REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE=/auth/domain.crt", + "-v", ta.CertPath + ":/auth/domain.crt", + } +} + +type BasicAuth struct { + Realm string + HtFile string + Username string + Password string +} + +func (ba *BasicAuth) Params(data test.Data) []string { + if ba.Realm == "" { + ba.Realm = "Basic Realm" + } + if ba.HtFile == "" && ba.Username != "" && ba.Password != "" { + pass := ba.Password + encryptedPass, _ := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) + tmpDir, _ := os.MkdirTemp(data.TempDir(), "htpasswd") + ba.HtFile = filepath.Join(tmpDir, "htpasswd") + _ = os.WriteFile(ba.HtFile, []byte(fmt.Sprintf(`%s:%s`, ba.Username, string(encryptedPass[:]))), 0600) + } + ret := []string{ + "--env", "REGISTRY_AUTH=htpasswd", + "--env", "REGISTRY_AUTH_HTPASSWD_REALM=" + ba.Realm, + "--env", "REGISTRY_AUTH_HTPASSWD_PATH=/htpasswd", + } + if ba.HtFile != "" { + ret = append(ret, "-v", ba.HtFile+":/htpasswd") + } + return ret +} + +type TokenAuthServer struct { + Scheme string + IP net.IP + Port int + CertPath string + Cleanup func(data test.Data, helpers test.Helpers) + Setup func(data test.Data, helpers test.Helpers) + Logs func(data test.Data, helpers test.Helpers) + Auth Auth +} + +type Server struct { + Scheme string + IP net.IP + Port int + Cleanup func(data test.Data, helpers test.Helpers) + Setup func(data test.Data, helpers test.Helpers) + Logs func(data test.Data, helpers test.Helpers) + HostsDir string // contains ":/hosts.toml" +} diff --git a/pkg/testutil/nerdtest/registry/docker.go b/pkg/testutil/nerdtest/registry/docker.go new file mode 100644 index 00000000000..9248dc56652 --- /dev/null +++ b/pkg/testutil/nerdtest/registry/docker.go @@ -0,0 +1,154 @@ +/* + 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 registry + +import ( + "fmt" + "net" + "os" + "strconv" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/ca" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/hoststoml" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/platform" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/portlock" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func NewDockerRegistry(data test.Data, helpers test.Helpers, currentCA *ca.CA, port int, auth Auth) *Server { + // listen on 0.0.0.0 to enable 127.0.0.1 + listenIP := net.ParseIP("0.0.0.0") + hostIP, err := nettestutil.NonLoopbackIPv4() + assert.NilError(helpers.T(), err, fmt.Errorf("failed finding ipv4 non loopback interface: %w", err)) + // XXX RELEASE PORT IN CLEANUP HERE + // FIXME: this will fail in many circumstances. Review strategy on how to acquire a free port. + // We probably have better code for that already somewhere. + port, err = portlock.Acquire(port) + assert.NilError(helpers.T(), err, fmt.Errorf("failed acquiring port: %w", err)) + + containerName := data.Identifier(fmt.Sprintf("docker-registry-server-%d-%t", port, currentCA != nil)) + // Cleanup possible leftovers first + helpers.Ensure("rm", "-f", containerName) + + args := []string{ + "run", + "--pull=never", + "-d", + "-p", fmt.Sprintf("%s:%d:5000", listenIP, port), + "--name", containerName, + } + scheme := "http" + var cert *ca.Cert + if currentCA != nil { + scheme = "https" + cert = currentCA.NewCert(hostIP.String(), "127.0.0.1", "localhost", "::1") + args = append(args, + "--env", "REGISTRY_HTTP_TLS_CERTIFICATE=/registry/domain.crt", + "--env", "REGISTRY_HTTP_TLS_KEY=/registry/domain.key", + "-v", cert.CertPath+":/registry/domain.crt", + "-v", cert.KeyPath+":/registry/domain.key", + ) + } + + // Attach authentication params returns by authenticator + args = append(args, auth.Params(data)...) + + // Get the right registry version + registryImage := platform.RegistryImageStable + up := os.Getenv("DISTRIBUTION_VERSION") + if up != "" { + if up[0:1] != "v" { + up = "v" + up + } + registryImage = platform.RegistryImageNext + up + } + args = append(args, registryImage) + + cleanup := func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", containerName) + errPortRelease := portlock.Release(port) + + if cert != nil { + assert.NilError(helpers.T(), cert.Close(), fmt.Errorf("failed cleaning certificates: %w", err)) + } + + assert.NilError(helpers.T(), errPortRelease, fmt.Errorf("failed releasing port: %w", err)) + } + + // FIXME: in the future, we will want to further manipulate hosts toml file from the test + // This should then return the struct, instead of saving it on its own + hostsDir, err := func() (string, error) { + hDir, err := os.MkdirTemp(data.TempDir(), "certs.d") + assert.NilError(helpers.T(), err, fmt.Errorf("failed creating directory certs.d: %w", err)) + + if currentCA != nil { + hostTomlContent := &hoststoml.HostsToml{ + CA: currentCA.CertPath, + } + + err = hostTomlContent.Save(hDir, hostIP.String(), port) + assert.NilError(helpers.T(), err, fmt.Errorf("failed creating hosts.toml file: %w", err)) + + err = hostTomlContent.Save(hDir, "127.0.0.1", port) + assert.NilError(helpers.T(), err, fmt.Errorf("failed creating hosts.toml file: %w", err)) + + err = hostTomlContent.Save(hDir, "localhost", port) + assert.NilError(helpers.T(), err, fmt.Errorf("failed creating hosts.toml file: %w", err)) + + if port == 443 { + err = hostTomlContent.Save(hDir, hostIP.String(), 0) + assert.NilError(helpers.T(), err, fmt.Errorf("failed creating hosts.toml file: %w", err)) + + err = hostTomlContent.Save(hDir, "127.0.0.1", 0) + assert.NilError(helpers.T(), err, fmt.Errorf("failed creating hosts.toml file: %w", err)) + + err = hostTomlContent.Save(hDir, "localhost", 0) + assert.NilError(helpers.T(), err, fmt.Errorf("failed creating hosts.toml file: %w", err)) + + } + } + + return hDir, nil + }() + + setup := func(data test.Data, helpers test.Helpers) { + helpers.Ensure(args...) + ensureContainerStarted(helpers, containerName) + _, err = nettestutil.HTTPGet(fmt.Sprintf("%s://%s/v2/", + scheme, + net.JoinHostPort(hostIP.String(), strconv.Itoa(port)), + ), + 10, + true) + assert.NilError(helpers.T(), err, fmt.Errorf("failed starting docker registry in a timely manner: %w", err)) + } + + return &Server{ + Scheme: scheme, + IP: hostIP, + Port: port, + Cleanup: cleanup, + Setup: setup, + Logs: func(data test.Data, helpers test.Helpers) { + helpers.T().Error(helpers.Err("logs", containerName)) + }, + HostsDir: hostsDir, + } +} diff --git a/pkg/testutil/nerdtest/registry/kubo.go b/pkg/testutil/nerdtest/registry/kubo.go new file mode 100644 index 00000000000..8cb350a65b0 --- /dev/null +++ b/pkg/testutil/nerdtest/registry/kubo.go @@ -0,0 +1,90 @@ +/* + 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 registry + +import ( + "fmt" + "net" + "strconv" + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/ca" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/platform" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/portlock" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func NewKuboRegistry(data test.Data, helpers test.Helpers, t *testing.T, currentCA *ca.CA, port int, auth Auth) *Server { + // listen on 0.0.0.0 to enable 127.0.0.1 + listenIP := net.ParseIP("0.0.0.0") + hostIP, err := nettestutil.NonLoopbackIPv4() + assert.NilError(t, err, fmt.Errorf("failed finding ipv4 non loopback interface: %w", err)) + port, err = portlock.Acquire(port) + assert.NilError(t, err, fmt.Errorf("failed acquiring port: %w", err)) + + containerName := data.Identifier(fmt.Sprintf("kubo-registry-server-%d-%t", port, currentCA != nil)) + // Cleanup possible leftovers first + helpers.Ensure("rm", "-f", containerName) + + args := []string{ + "run", + "--pull=never", + "-d", + "-p", fmt.Sprintf("%s:%d:%d", listenIP, port, port), + "--name", containerName, + "--entrypoint=/bin/sh", + platform.KuboImage, + "-c", "--", + fmt.Sprintf("ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/%d && ipfs daemon --offline", port), + } + + scheme := "http" + + cleanup := func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", containerName) + errPortRelease := portlock.Release(port) + + assert.NilError(t, errPortRelease, fmt.Errorf("failed releasing port: %w", err)) + } + + setup := func(data test.Data, helpers test.Helpers) { + helpers.Ensure(args...) + ensureContainerStarted(helpers, containerName) + _, err = nettestutil.HTTPGet(fmt.Sprintf("%s://%s/api/v0", + scheme, + net.JoinHostPort(hostIP.String(), strconv.Itoa(port)), + ), + 30, + true) + logs := helpers.Capture("logs", containerName) + assert.NilError(t, err, fmt.Errorf("failed starting kubo registry in a timely manner: %w - logs: %s", err, logs)) + } + + return &Server{ + IP: hostIP, + Port: port, + Scheme: scheme, + Cleanup: cleanup, + Setup: setup, + Logs: func(data test.Data, helpers test.Helpers) { + helpers.T().Error(helpers.Err("logs", containerName)) + }, + } +} diff --git a/pkg/testutil/nerdtest/requirements.go b/pkg/testutil/nerdtest/requirements.go index f75f3e8b7f7..32878ce1cda 100644 --- a/pkg/testutil/nerdtest/requirements.go +++ b/pkg/testutil/nerdtest/requirements.go @@ -19,125 +19,293 @@ package nerdtest import ( "encoding/json" "fmt" - "testing" + "os" + "os/exec" + "strings" "gotest.tools/v3/assert" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/platform" "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) +var BuildkitHost test.ConfigKey = "bkHost" + +// These are used for ambient requirements var ipv6 test.ConfigKey = "IPv6Test" +var kubernetes test.ConfigKey = "KubeTest" +var flaky test.ConfigKey = "FlakyTest" var only test.ConfigValue = "Only" -var mode test.ConfigKey = "Mode" -var modePrivate test.ConfigValue = "Private" -var OnlyIPv6 = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { - ret = testutil.GetEnableIPv6() - if !ret { - mess = "runner skips IPv6 compatible tests in the non-IPv6 environment" - } - data.WithConfig(ipv6, only) - return ret, mess -}) - -var Private = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { - data.WithConfig(mode, modePrivate) - return true, "private mode" -}) - -var Soci = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { - ret = false - mess = "soci is not enabled" - (&test.GenericCommand{}). - WithT(t). - WithBinary(testutil.GetTarget()). - WithArgs("info", "--format", "{{ json . }}"). - Run(&test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var dinf dockercompat.Info - err := json.Unmarshal([]byte(stdout), &dinf) - assert.NilError(t, err, "failed to parse docker info") - for _, p := range dinf.Plugins.Storage { - if p == "soci" { - ret = true - mess = "soci is enabled" - } - } - }, - }) +// These are used for down the road configuration and custom behavior inside command +var modePrivate test.ConfigKey = "PrivateMode" +var stargz test.ConfigKey = "Stargz" +var ipfs test.ConfigKey = "IPFS" +var enabled test.ConfigValue = "Enabled" - return ret, mess -}) +// OnlyIPv6 marks a test as suitable to be run exclusively inside an ipv6 environment +// This is an ambient requirement +var OnlyIPv6 = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + helpers.Write(ipv6, only) + ret = environmentHasIPv6() + if !ret { + mess = "runner skips IPv6 compatible tests in the non-IPv6 environment" + } + return ret, mess + }, +} + +// OnlyKubernetes marks a test as meant to be tested on Kubernetes +// This is an ambient requirement +var OnlyKubernetes = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + helpers.Write(kubernetes, only) + ret = environmentHasKubernetes() + if !ret { + mess = "runner skips Kubernetes compatible tests in the non-Kubernetes environment" + } + return ret, mess + }, +} -var Docker = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { - ret = testutil.GetTarget() == testutil.Docker - if ret { - mess = "current target is docker" - } else { - mess = "current target is not docker" +// IsFlaky marks a test as randomly failing. +// This is an ambient requirement +var IsFlaky = func(issueLink string) *test.Requirement { + return &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + // We do not even want to get to the setup phase here + helpers.Write(flaky, only) + ret = environmentIsForFlaky() + if !ret { + mess = "runner skips flaky compatible tests in the non-flaky environment" + } + return ret, mess + }, } - return ret, mess -}) - -var NerdctlNeedsFixing = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { - ret = testutil.GetTarget() == testutil.Docker - if ret { - mess = "current target is docker" - } else { - mess = "current target is nerdctl, but it is currently broken and not working for this" +} + +// Docker marks a test as suitable solely for Docker and not Nerdctl +// Generally used as test.Not(nerdtest.Docker), which of course it the opposite +var Docker = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + ret = getTarget() == targetDocker + if ret { + mess = "current target is docker" + } else { + mess = "current target is not docker" + } + return ret, mess + }, +} + +// NerdctlNeedsFixing marks a test as unsuitable to be run for Nerdctl, because of a specific known issue which +// url must be passed as an argument +var NerdctlNeedsFixing = func(issueLink string) *test.Requirement { + return &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + ret = getTarget() == targetDocker + if ret { + mess = "current target is docker" + } else { + mess = "current target is nerdctl, but we will skip as nerdctl currently has issue: " + issueLink + } + return ret, mess + }, } - return ret, mess -}) - -var Rootless = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { - // Make sure we DO not return "IsRootless true" for docker - ret = testutil.GetTarget() != testutil.Docker && rootlessutil.IsRootless() - if ret { - mess = "environment is rootless" - } else { - mess = "environment is rootful" +} + +// BrokenTest marks a test as currently broken, with explanation provided in message, along with +// additional requirements / restrictions describing what it can run on. +var BrokenTest = func(message string, req *test.Requirement) *test.Requirement { + return &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (bool, string) { + ret, mess := req.Check(data, helpers) + return ret, message + "\n" + mess + }, + Setup: req.Setup, + Cleanup: req.Cleanup, } - return ret, mess -}) - -var Build = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { - // FIXME: shouldn't we run buildkitd in a container? At least for testing, that would be so much easier than - // against the host install - ret = true - mess = "buildkitd is enabled" - if testutil.GetTarget() == testutil.Nerdctl { - _, err := buildkitutil.GetBuildkitHost(testutil.Namespace) - if err != nil { +} + +// RootLess marks a test as suitable only for the rootless environment +var RootLess = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + // Make sure we DO not return "IsRootless true" for docker + ret = getTarget() == targetNerdctl && rootlessutil.IsRootless() + if ret { + mess = "environment is root-less" + } else { + mess = "environment is root-ful" + } + return ret, mess + }, +} + +// RootFul marks a test as suitable only for rootful env +var RootFul = test.Not(RootLess) + +// CGroup requires that cgroup is enabled +var CGroup = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + ret = true + mess = "cgroup is enabled" + stdout := helpers.Capture("info", "--format", "{{ json . }}") + var dinf dockercompat.Info + err := json.Unmarshal([]byte(stdout), &dinf) + assert.NilError(helpers.T(), err, "failed to parse docker info") + switch dinf.CgroupDriver { + case "none", "": ret = false - mess = fmt.Sprintf("buildkitd is not enabled: %+v", err) + mess = "cgroup is none" } - } - return ret, mess -}) - -var CGroup = test.MakeRequirement(func(data test.Data, t *testing.T) (ret bool, mess string) { - ret = true - mess = "cgroup is enabled" - (&test.GenericCommand{}). - WithT(t). - WithBinary(testutil.GetTarget()). - WithArgs("info", "--format", "{{ json . }}"). - Run(&test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var dinf dockercompat.Info - err := json.Unmarshal([]byte(stdout), &dinf) - assert.NilError(t, err, "failed to parse docker info") - switch dinf.CgroupDriver { - case "none", "": - ret = false - mess = "cgroup is none" + return ret, mess + }, +} + +// Soci requires that the soci snapshotter is enabled +var Soci = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + ret = false + mess = "soci is not enabled" + stdout := helpers.Capture("info", "--format", "{{ json . }}") + var dinf dockercompat.Info + err := json.Unmarshal([]byte(stdout), &dinf) + assert.NilError(helpers.T(), err, "failed to parse docker info") + for _, p := range dinf.Plugins.Storage { + if p == "soci" { + ret = true + mess = "soci is enabled" + } + } + return ret, mess + }, +} + +var Stargz = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + ret = false + mess = "stargz is not enabled" + stdout := helpers.Capture("info", "--format", "{{ json . }}") + var dinf dockercompat.Info + err := json.Unmarshal([]byte(stdout), &dinf) + assert.NilError(helpers.T(), err, "failed to parse docker info") + for _, p := range dinf.Plugins.Storage { + if p == "stargz" { + ret = true + mess = "stargz is enabled" + } + } + // Need this to happen now for Cleanups to work + // FIXME: we should be able to access the env (at least through helpers.Command().) instead of this gym + helpers.Write(stargz, enabled) + return ret, mess + }, +} + +// Registry marks a test as requiring a registry to be deployed +var Registry = test.Require( + // Registry requires Linux currently + test.Linux, + (func() *test.Requirement { + // Provisional: see note in cleanup + // var reg *registry.Server + + return &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (bool, string) { + return true, "" + }, + Setup: func(data test.Data, helpers test.Helpers) { + // Ensure we have registry images now, so that we can run --pull=never + // This is useful for two reasons: + // - if ghcr.io is out, we want to fail early + // - when we start a large number of registries in subtests, no need to round-trip to ghcr everytime + // This of course assumes that the subtests are NOT going to prune / rmi images + registryImage := platform.RegistryImageStable + up := os.Getenv("DISTRIBUTION_VERSION") + if up != "" { + if up[0:1] != "v" { + up = "v" + up + } + registryImage = platform.RegistryImageNext + up } + helpers.Ensure("pull", "--quiet", registryImage) + helpers.Ensure("pull", "--quiet", platform.DockerAuthImage) + helpers.Ensure("pull", "--quiet", platform.KuboImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + // FIXME: figure out what to do with reg setup/cleanup routines + // Provisionally, reg is available here in the closure }, - }) + } + })(), +) + +// Build marks a test as suitable only if buildkitd is enabled (only tested for nerdctl obviously) +var Build = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (bool, string) { + // FIXME: shouldn't we run buildkitd in a container? At least for testing, that would be so much easier than + // against the host install + ret := true + mess := "buildkitd is enabled" + + if getTarget() == targetNerdctl { + bkHostAddr, err := buildkitutil.GetBuildkitHost(defaultNamespace) + if err != nil { + ret = false + mess = fmt.Sprintf("buildkitd is not enabled: %+v", err) + return ret, mess + } + // We also require the buildctl binary in the path + _, err = exec.LookPath("buildctl") + if err != nil { + ret = false + mess = fmt.Sprintf("buildctl is not in the path: %+v", err) + return ret, mess + } + helpers.Write(BuildkitHost, test.ConfigValue(bkHostAddr)) + } + return ret, mess + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("builder", "prune", "--all", "--force") + }, +} + +var IPFS = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + // FIXME: we should be able to access the env (at least through helpers.Command().) instead of this gym + helpers.Write(ipfs, enabled) + // FIXME: this is incomplete. We obviously need a daemon running, properly configured + return test.Binary("ipfs").Check(data, helpers) + }, +} - return ret, mess -}) +// Private makes a test run inside a dedicated namespace, with a private config.toml, hosts directory, and DOCKER_CONFIG path +// If the target is docker, parallelism is forcefully disabled +var Private = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + // We need this to happen NOW and not in setup, as otherwise cleanup with operate on the default namespace + namespace := data.Identifier("private") + helpers.Write(Namespace, test.ConfigValue(namespace)) + data.Set("_deletenamespace", namespace) + // FIXME: is this necessary? Should NoParallel be subsumed into config? + helpers.Write(modePrivate, enabled) + return true, "private mode creates a dedicated namespace for nerdctl, and disable parallelism for docker" + }, + + Cleanup: func(data test.Data, helpers test.Helpers) { + if getTarget() == targetNerdctl { + // FIXME: there are conditions where we still have some stuff in there and this fails... + containerList := strings.TrimSpace(helpers.Capture("ps", "-aq")) + if containerList != "" { + helpers.Ensure(append([]string{"rm", "-f"}, strings.Split(containerList, "\n")...)...) + } + helpers.Ensure("system", "prune", "-f", "--all", "--volumes") + helpers.Anyhow("namespace", "remove", data.Get("_deletenamespace")) + } + }, +} diff --git a/pkg/testutil/nerdtest/test.go b/pkg/testutil/nerdtest/test.go index 78046cb9cca..7bfd485cdf2 100644 --- a/pkg/testutil/nerdtest/test.go +++ b/pkg/testutil/nerdtest/test.go @@ -17,154 +17,51 @@ package nerdtest import ( - "os" - "path/filepath" "testing" - "gotest.tools/v3/assert" - - "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func Setup() { - test.CustomCommand(nerdctlSetup) -} - -// Nerdctl specific config key and values -var NerdctlToml test.ConfigKey = "NerdctlToml" var DockerConfig test.ConfigKey = "DockerConfig" +var Namespace test.ConfigKey = "Namespace" +var NerdctlToml test.ConfigKey = "NerdctlToml" var HostsDir test.ConfigKey = "HostsDir" var DataRoot test.ConfigKey = "DataRoot" -var Namespace test.ConfigKey = "Namespace" +var Debug test.ConfigKey = "Debug" -type NerdCommand struct { - test.GenericCommand - // FIXME: annoying - forces custom Clone, etc - Target string -} - -// Run does override the generic command run, as we are testing both docker and nerdctl -func (nc *NerdCommand) Run(expect *test.Expected) { - // We are not in the business of testing docker error output, so, spay expect for errors testing, if any - if expect != nil && nc.Target != testutil.Nerdctl { - expect.Errors = nil +func Setup() *test.Case { + test.Customize(&nerdctlSetup{}) + return &test.Case{ + Env: map[string]string{}, } - - nc.GenericCommand.Run(expect) } -// Clone is overridden as well, as we need to pass along the target -func (nc *NerdCommand) Clone() test.Command { - return &NerdCommand{ - GenericCommand: *((nc.GenericCommand.Clone()).(*test.GenericCommand)), - Target: nc.Target, - } +type nerdctlSetup struct { } -func nerdctlSetup(testCase *test.Case, t *testing.T) test.Command { - t.Helper() - - var testUtilBase *testutil.Base - dt := testCase.Data - var pvNamespace string - inherited := false +func (ns *nerdctlSetup) CustomCommand(testCase *test.Case, t *testing.T) test.CustomizableCommand { + return newNerdCommand(testCase.Config, t) +} - if dt.ReadConfig(ipv6) != only && testutil.GetEnableIPv6() { +func (ns *nerdctlSetup) AmbientRequirements(testCase *test.Case, t *testing.T) { + // Ambient requirements, bail out now if these do not match + if environmentHasIPv6() && testCase.Config.Read(ipv6) != only { t.Skip("runner skips non-IPv6 compatible tests in the IPv6 environment") } - if dt.ReadConfig(mode) == modePrivate { - // If private was inherited, we already got a configured namespace - if dt.ReadConfig(Namespace) != "" { - pvNamespace = string(dt.ReadConfig(Namespace)) - inherited = true - } else { - // Otherwise, we need to set everything up - pvNamespace = testCase.Data.Identifier() - dt.WithConfig(Namespace, test.ConfigValue(pvNamespace)) - testCase.Env["DOCKER_CONFIG"] = testCase.Data.TempDir() - testCase.Env["NERDCTL_TOML"] = filepath.Join(testCase.Data.TempDir(), "nerdctl.toml") - dt.WithConfig(HostsDir, test.ConfigValue(testCase.Data.TempDir())) - // Setting data root is more trouble than anything and does not significantly increase isolation - // dt.WithConfig(DataRoot, test.ConfigValue(testCase.Data.TempDir())) - } - testUtilBase = testutil.NewBaseWithNamespace(t, pvNamespace) - if testUtilBase.Target == testutil.Docker { - // For docker, just disable parallel - testCase.NoParallel = true - } - } else if dt.ReadConfig(Namespace) != "" { - pvNamespace = string(dt.ReadConfig(Namespace)) - testUtilBase = testutil.NewBaseWithNamespace(t, pvNamespace) - } else { - testUtilBase = testutil.NewBase(t) + if environmentHasKubernetes() && testCase.Config.Read(kubernetes) != only { + t.Skip("runner skips non-Kubernetes compatible tests in the Kubernetes environment") } - // If we were passed custom content for NerdctlToml, save it - // Not happening if this is not nerdctl of course - if testUtilBase.Target == testutil.Nerdctl { - if dt.ReadConfig(NerdctlToml) != "" { - dest := filepath.Join(testCase.Data.TempDir(), "nerdctl.toml") - testCase.Env["NERDCTL_TOML"] = dest - err := os.WriteFile(dest, []byte(dt.ReadConfig(NerdctlToml)), 0400) - assert.NilError(t, err, "failed to write custom nerdctl toml file for test") - } - if dt.ReadConfig(DockerConfig) != "" { - dest := filepath.Join(testCase.Data.TempDir(), "config.json") - testCase.Env["DOCKER_CONFIG"] = filepath.Dir(dest) - err := os.WriteFile(dest, []byte(dt.ReadConfig(DockerConfig)), 0400) - assert.NilError(t, err, "failed to write custom docker config json file for test") - } + if environmentIsForFlaky() && testCase.Config.Read(flaky) != only { + t.Skip("runner skips non-flaky tests in the flaky environment") } - // Build the base - baseCommand := &NerdCommand{} - baseCommand.WithBinary(testUtilBase.Binary) - baseCommand.WithArgs(testUtilBase.Args...) - baseCommand.WithEnv(testCase.Env) - baseCommand.WithT(t) - baseCommand.WithTempDir(testCase.Data.TempDir()) - baseCommand.Target = testUtilBase.Target - - if testUtilBase.Target == testutil.Nerdctl { - if dt.ReadConfig(HostsDir) != "" { - baseCommand.WithArgs("--hosts-dir=" + string(dt.ReadConfig(HostsDir))) - } - - if dt.ReadConfig(DataRoot) != "" { - baseCommand.WithArgs("--data-root=" + string(dt.ReadConfig(DataRoot))) - } - } - - // If we were in a custom namespace, not inherited - make sure we clean up the namespace - if testUtilBase.Target == testutil.Nerdctl && pvNamespace != "" && !inherited { - cleanup := func() { - // Stop all containers, then prune everything - containerList := baseCommand.Clone() - containerList.WithArgs("ps", "-q") - containerList.Run(&test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - if stdout != "" { - containerRm := baseCommand.Clone() - containerRm.WithArgs("rm", "-f", stdout) - containerRm.Run(&test.Expected{}) - } - }, - }) - - systemPrune := baseCommand.Clone() - systemPrune.WithArgs("system", "prune", "-f", "--all", "--volumes") - systemPrune.Run(&test.Expected{}) - - cleanNamespace := baseCommand.Clone() - cleanNamespace.WithArgs("namespace", "remove", pvNamespace) - cleanNamespace.Run(nil) - } - cleanup() - t.Cleanup(cleanup) + if getTarget() == targetDocker && testCase.Config.Read(modePrivate) == enabled { + // For docker, we do disable parallel since there is no namespace where we can isolate + testCase.NoParallel = true } - // Attach the base command - return baseCommand + // We do not want private to get inherited by subtests, as we want them to be in the same namespace set here + testCase.Config.Write(modePrivate, "") } diff --git a/pkg/testutil/nerdtest/third-party.go b/pkg/testutil/nerdtest/third-party.go new file mode 100644 index 00000000000..21199f3a815 --- /dev/null +++ b/pkg/testutil/nerdtest/third-party.go @@ -0,0 +1,63 @@ +/* + 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 nerdtest + +import ( + "os/exec" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/ca" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/registry" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func BuildCtlCommand(helpers test.Helpers, args ...string) test.TestableCommand { + assert.Assert(helpers.T(), string(helpers.Read(BuildkitHost)) != "", "You first need to Require Build to use buildctl") + buildctl, _ := exec.LookPath("buildctl") + cmd := helpers.Custom(buildctl) + cmd.WithArgs("--addr=" + string(helpers.Read(BuildkitHost))) + cmd.WithArgs(args...) + return cmd +} + +func RegistryWithTokenAuth(data test.Data, helpers test.Helpers, user, pass string, port int, tls bool) (*registry.Server, *registry.TokenAuthServer) { + rca := ca.New(data, helpers.T()) + as := registry.NewCesantaAuthServer(data, helpers, rca, 0, user, pass, tls) + re := registry.NewDockerRegistry(data, helpers, rca, port, as.Auth) + return re, as +} + +func RegistryWithNoAuth(data test.Data, helpers test.Helpers, port int, tls bool) *registry.Server { + var rca *ca.CA + if tls { + rca = ca.New(data, helpers.T()) + } + return registry.NewDockerRegistry(data, helpers, rca, port, ®istry.NoAuth{}) +} + +func RegistryWithBasicAuth(data test.Data, helpers test.Helpers, user, pass string, port int, tls bool) *registry.Server { + auth := ®istry.BasicAuth{ + Username: user, + Password: pass, + } + var rca *ca.CA + if tls { + rca = ca.New(data, helpers.T()) + } + return registry.NewDockerRegistry(data, helpers, rca, port, auth) +} diff --git a/pkg/testutil/nerdtest/helpers.go b/pkg/testutil/nerdtest/utilities.go similarity index 83% rename from pkg/testutil/nerdtest/helpers.go rename to pkg/testutil/nerdtest/utilities.go index 346a6c9122a..384f5132110 100644 --- a/pkg/testutil/nerdtest/helpers.go +++ b/pkg/testutil/nerdtest/utilities.go @@ -25,15 +25,19 @@ import ( "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) +func IsDocker() bool { + return testutil.GetTarget() == "docker" +} + // InspectContainer is a helper that can be used inside custom commands or Setup func InspectContainer(helpers test.Helpers, name string) dockercompat.Container { var dc []dockercompat.Container cmd := helpers.Command("container", "inspect", name) cmd.Run(&test.Expected{ - ExitCode: 0, Output: func(stdout string, info string, t *testing.T) { err := json.Unmarshal([]byte(stdout), &dc) assert.NilError(t, err, "Unable to unmarshal output\n"+info) @@ -43,14 +47,10 @@ func InspectContainer(helpers test.Helpers, name string) dockercompat.Container return dc[0] } -func InspectVolume(helpers test.Helpers, name string, args ...string) native.Volume { +func InspectVolume(helpers test.Helpers, name string) native.Volume { var dc []native.Volume - cmdArgs := append([]string{"volume", "inspect"}, args...) - cmdArgs = append(cmdArgs, name) - - cmd := helpers.Command(cmdArgs...) + cmd := helpers.Command("volume", "inspect", name) cmd.Run(&test.Expected{ - ExitCode: 0, Output: func(stdout string, info string, t *testing.T) { err := json.Unmarshal([]byte(stdout), &dc) assert.NilError(t, err, "Unable to unmarshal output\n"+info) @@ -60,14 +60,10 @@ func InspectVolume(helpers test.Helpers, name string, args ...string) native.Vol return dc[0] } -func InspectNetwork(helpers test.Helpers, name string, args ...string) dockercompat.Network { +func InspectNetwork(helpers test.Helpers, name string) dockercompat.Network { var dc []dockercompat.Network - cmdArgs := append([]string{"network", "inspect"}, args...) - cmdArgs = append(cmdArgs, name) - - cmd := helpers.Command(cmdArgs...) + cmd := helpers.Command("network", "inspect", name) cmd.Run(&test.Expected{ - ExitCode: 0, Output: func(stdout string, info string, t *testing.T) { err := json.Unmarshal([]byte(stdout), &dc) assert.NilError(t, err, "Unable to unmarshal output\n"+info) @@ -81,7 +77,6 @@ func InspectImage(helpers test.Helpers, name string) dockercompat.Image { var dc []dockercompat.Image cmd := helpers.Command("image", "inspect", name) cmd.Run(&test.Expected{ - ExitCode: 0, Output: func(stdout string, info string, t *testing.T) { err := json.Unmarshal([]byte(stdout), &dc) assert.NilError(t, err, "Unable to unmarshal output\n"+info) @@ -91,16 +86,16 @@ func InspectImage(helpers test.Helpers, name string) dockercompat.Image { return dc[0] } +const ( + maxRetry = 5 + sleep = time.Second +) + func EnsureContainerStarted(helpers test.Helpers, con string) { - const ( - maxRetry = 5 - sleep = time.Second - ) for i := 0; i < maxRetry; i++ { count := i cmd := helpers.Command("container", "inspect", con) cmd.Run(&test.Expected{ - ExitCode: 0, Output: func(stdout string, info string, t *testing.T) { var dc []dockercompat.Container err := json.Unmarshal([]byte(stdout), &dc) @@ -110,7 +105,7 @@ func EnsureContainerStarted(helpers test.Helpers, con string) { return } if count == maxRetry-1 { - t.Fatalf("conainer %s not running", con) + t.Fatalf("container %s still not running after %d retries", con, count) } time.Sleep(sleep) }, diff --git a/pkg/testutil/test/case.go b/pkg/testutil/test/case.go index 36384c6962b..58f9f573757 100644 --- a/pkg/testutil/test/case.go +++ b/pkg/testutil/test/case.go @@ -17,159 +17,181 @@ package test import ( + "slices" "testing" "gotest.tools/v3/assert" ) -// Group informally describes a slice of tests -type Group []*Case - -func (tg *Group) Run(t *testing.T) { - t.Helper() - // If the group contains only one test, no need to create a subtest - sub := len(*tg) > 1 - if sub { - t.Parallel() - } - // Run each subtest - for _, tc := range *tg { - tc.subIt = sub - tc.Run(t) - } -} - // Case describes an entire test-case, including data, setup and cleanup routines, command and expectations type Case struct { // Description contains a human-readable short desc, used as a seed for the identifier and as a title for the test Description string // NoParallel disables parallel execution if set to true + // This obviously implies that all tests run in parallel, by default. This is a design choice. NoParallel bool - // Env contains a map of environment variables to use for commands run in Setup, Command and Cleanup + // Env contains a map of environment variables to use as a base for all commands run in Setup, Command and Cleanup // Note that the environment is inherited by subtests Env map[string]string // Data contains test specific data, accessible to all operations, also inherited by subtests Data Data + // Config contains specific information meaningful to the binary being tested. + // It is also inherited by subtests + Config Config + // Requirement + Require *Requirement // Setup Setup Butler - // Expected - Expected Manager // Command Command Executor + // Expected + Expected Manager // Cleanup Cleanup Butler - // Requirement - Require Requirement // SubTests SubTests []*Case // Private - helpers Helpers - t *testing.T - parent *Case - baseCommand Command - - subIt bool + helpers Helpers + t *testing.T + parent *Case } // Run prepares and executes the test, and any possible subtests func (test *Case) Run(t *testing.T) { t.Helper() // Run the test - testRun := func(tt *testing.T) { - tt.Helper() - test.seal(tt) - - if registeredInit == nil { - bc := &GenericCommand{} - bc.WithEnv(test.Env) - bc.WithT(tt) - bc.WithTempDir(test.Data.TempDir()) - test.baseCommand = bc + testRun := func(subT *testing.T) { + subT.Helper() + + assert.Assert(subT, test.t == nil, "You cannot run a test multiple times") + + // Attach testing.T + test.t = subT + assert.Assert(test.t, test.Description != "" || test.parent == nil, "A test description cannot be empty") + assert.Assert(test.t, test.Command == nil || test.Expected != nil, + "Expectations for a test command cannot be nil. You may want to use Setup instead.") + + // Ensure we have env + if test.Env == nil { + test.Env = map[string]string{} + } + + // If we have a parent, get parent env, data and config + var parentData Data + var parentConfig Config + if test.parent != nil { + parentData = test.parent.Data + parentConfig = test.parent.Config + for k, v := range test.parent.Env { + if _, ok := test.Env[k]; !ok { + test.Env[k] = v + } + } + } + + // Inherit and attach Data and Config + test.Data = configureData(test.t, test.Data, parentData) + test.Config = configureConfig(test.Config, parentConfig) + + var b CustomizableCommand + if registeredTestable == nil { + b = &GenericCommand{} } else { - test.baseCommand = registeredInit(test, test.t) + b = registeredTestable.CustomCommand(test, test.t) } - test.exec(tt) - } + b.WithCwd(test.Data.TempDir()) - if test.subIt { - t.Run(test.Description, testRun) - } else { - testRun(t) - } -} + b.withT(test.t) + b.withTempDir(test.Data.TempDir()) + b.withEnv(test.Env) + b.withConfig(test.Config) -// seal is a private method to prepare the test -func (test *Case) seal(t *testing.T) { - t.Helper() - assert.Assert(t, test.t == nil, "You cannot run a test multiple times") - assert.Assert(t, test.Description != "", "A test description cannot be empty") - assert.Assert(t, test.Command == nil || test.Expected != nil, - "Expectations for a test command cannot be nil. You may want to use Setup instead.") - - // Ensure we have env - if test.Env == nil { - test.Env = map[string]string{} - } + // Attach the base command, and t + test.helpers = &helpersInternal{ + cmdInternal: b, + t: test.t, + } - // If we have a parent, get parent env and data - var parentData Data - if test.parent != nil { - parentData = test.parent.Data - for k, v := range test.parent.Env { - if _, ok := test.Env[k]; !ok { - test.Env[k] = v + setups := []func(data Data, helpers Helpers){} + cleanups := []func(data Data, helpers Helpers){} + + // Check the requirements before going any further + if test.Require != nil { + shouldRun, message := test.Require.Check(test.Data, test.helpers) + if !shouldRun { + test.t.Skipf("test skipped as: %s", message) + } + if test.Require.Setup != nil { + setups = append(setups, test.Require.Setup) + } + if test.Require.Cleanup != nil { + cleanups = append(cleanups, test.Require.Cleanup) } } - } - // Attach testing.T - test.t = t - // Inherit and attach Data - test.Data = configureData(t, test.Data, parentData) + // Register setup if any + if test.Setup != nil { + setups = append(setups, test.Setup) + } - // Check the requirements - if test.Require != nil { - test.Require(test.Data, true, t) - } -} + // Register cleanup if any + if test.Cleanup != nil { + cleanups = append(cleanups, test.Cleanup) + } -// exec is a private method that will take care of the test setup, command and cleanup execution -func (test *Case) exec(t *testing.T) { - t.Helper() - test.helpers = &helpers{ - test.baseCommand, - } + // Run optional post requirement hook + if registeredTestable != nil { + registeredTestable.AmbientRequirements(test, test.t) + } - // Set parallel unless asked not to - if !test.NoParallel { - t.Parallel() - } + // Set parallel unless asked not to + if !test.NoParallel { + test.t.Parallel() + } + + // Execute cleanups now + test.t.Log("======================== Pre-test cleanup ========================") + for _, cleanup := range cleanups { + cleanup(test.Data, test.helpers) + } - // Register cleanup if there is any, and run it to collect any leftovers from previous runs - if test.Cleanup != nil { - test.Cleanup(test.Data, test.helpers) - t.Cleanup(func() { - test.Cleanup(test.Data, test.helpers) + // Register the cleanups, in reverse + test.t.Cleanup(func() { + test.t.Log("======================== Post-test cleanup ========================") + slices.Reverse(cleanups) + for _, cleanup := range cleanups { + cleanup(test.Data, test.helpers) + } }) - } - // Run setup - if test.Setup != nil { - test.Setup(test.Data, test.helpers) - } + // Run the setups + test.t.Log("======================== Test setup ========================") + for _, setup := range setups { + setup(test.Data, test.helpers) + } - // Run the command if any, with expectations - if test.Command != nil { - test.Command(test.Data, test.helpers).Run(test.Expected(test.Data, test.helpers)) + // Run the command if any, with expectations + // Note: if we have a command, we already know we DO have Expected + test.t.Log("======================== Test Run ========================") + if test.Command != nil { + test.Command(test.Data, test.helpers).Run(test.Expected(test.Data, test.helpers)) + } + + // Now go for the subtests + test.t.Log("======================== Processing subtests ========================") + for _, subTest := range test.SubTests { + subTest.parent = test + subTest.Run(test.t) + } } - for _, subTest := range test.SubTests { - subTest.parent = test - subTest.subIt = true - subTest.Run(t) + if test.parent != nil { + t.Run(test.Description, testRun) + } else { + testRun(t) } } diff --git a/pkg/testutil/test/command.go b/pkg/testutil/test/command.go index 3e1b840db6e..fd7c4fa3b6a 100644 --- a/pkg/testutil/test/command.go +++ b/pkg/testutil/test/command.go @@ -30,94 +30,88 @@ import ( // GenericCommand is a concrete Command implementation type GenericCommand struct { - WorkingDir string - Env map[string]string + Config Config + TempDir string + Env map[string]string + + t *testing.T - t *testing.T - tempDir string helperBinary string helperArgs []string + prependArgs []string mainBinary string mainArgs []string - result *icmd.Result + + envBlackList []string stdin io.Reader async bool timeout time.Duration + workingDir string + + result *icmd.Result + rawStdErr string } -func (gc *GenericCommand) WithBinary(binary string) Command { +func (gc *GenericCommand) WithBinary(binary string) { gc.mainBinary = binary - return gc } -func (gc *GenericCommand) WithArgs(args ...string) Command { +func (gc *GenericCommand) WithArgs(args ...string) { gc.mainArgs = append(gc.mainArgs, args...) - return gc -} - -// WithEnv will overload the command env with values from the passed map -func (gc *GenericCommand) WithEnv(env map[string]string) Command { - if gc.Env == nil { - gc.Env = map[string]string{} - } - for k, v := range env { - gc.Env[k] = v - } - return gc } -func (gc *GenericCommand) WithWrapper(binary string, args ...string) Command { +func (gc *GenericCommand) WithWrapper(binary string, args ...string) { gc.helperBinary = binary gc.helperArgs = args - return gc } -// WithStdin sets the standard input of Cmd to the specified reader -func (gc *GenericCommand) WithStdin(r io.Reader) Command { +func (gc *GenericCommand) WithStdin(r io.Reader) { gc.stdin = r - return gc } -func (gc *GenericCommand) Background(timeout time.Duration) Command { - // Run it - gc.async = true - i := gc.boot() - gc.result = icmd.StartCmd(i) - gc.timeout = timeout - return gc +func (gc *GenericCommand) WithCwd(path string) { + gc.workingDir = path } -// TODO: it should be possible to: -// - timeout execution +// TODO: it should be possible to timeout execution +// Primitives (gc.timeout) is here, it is just a matter of exposing a WithTimeout method +// - UX to be decided +// - validate use case: would we ever need this? func (gc *GenericCommand) Run(expect *Expected) { + if gc.t != nil { + gc.t.Helper() + } + var result *icmd.Result var env []string if gc.async { result = icmd.WaitOnCmd(gc.timeout, gc.result) env = gc.result.Cmd.Env } else { - icmdCmd := gc.boot() - env = icmdCmd.Env + iCmdCmd := gc.boot() + env = iCmdCmd.Env // Run it - result = icmd.RunCmd(icmdCmd) + result = icmd.RunCmd(iCmdCmd) } + gc.rawStdErr = result.Stderr() + // Check our expectations, if any if expect != nil { - // Build the debug string - additionally attach the env (which icmd does not do) + // Build the debug string - additionally attach the env (which iCmd does not do) debug := result.String() + "Env:\n" + strings.Join(env, "\n") // ExitCode goes first if expect.ExitCode == -1 { assert.Assert(gc.t, result.ExitCode != 0, - "Expected exit code to be different than 0"+debug) + "Expected exit code to be different than 0\n"+debug) } else { assert.Assert(gc.t, expect.ExitCode == result.ExitCode, - fmt.Sprintf("Expected exit code: %d", expect.ExitCode)+debug) + fmt.Sprintf("Expected exit code: %d\n", expect.ExitCode)+debug) } // Range through the expected errors and confirm they are seen on stderr for _, expectErr := range expect.Errors { - assert.Assert(gc.t, strings.Contains(result.Stderr(), expectErr.Error()), - fmt.Sprintf("Expected error: %q to be found in stderr", expectErr.Error())+debug) + assert.Assert(gc.t, strings.Contains(gc.rawStdErr, expectErr.Error()), + fmt.Sprintf("Expected error: %q to be found in stderr\n", expectErr.Error())+debug) } // Finally, check the output if we are asked to if expect.Output != nil { @@ -126,6 +120,91 @@ func (gc *GenericCommand) Run(expect *Expected) { } } +func (gc *GenericCommand) Stderr() string { + return gc.rawStdErr +} + +func (gc *GenericCommand) Background(timeout time.Duration) { + // Run it + gc.async = true + i := gc.boot() + gc.timeout = timeout + gc.result = icmd.StartCmd(i) +} + +func (gc *GenericCommand) withEnv(env map[string]string) { + if gc.Env == nil { + gc.Env = map[string]string{} + } + for k, v := range env { + gc.Env[k] = v + } +} + +func (gc *GenericCommand) withTempDir(path string) { + gc.TempDir = path +} + +func (gc *GenericCommand) WithBlacklist(env []string) { + gc.envBlackList = env +} + +func (gc *GenericCommand) withConfig(config Config) { + gc.Config = config +} + +func (gc *GenericCommand) PrependArgs(args ...string) { + gc.prependArgs = append(gc.prependArgs, args...) +} + +func (gc *GenericCommand) Clone() TestableCommand { + // Copy the command and return a new one - with almost everything from the parent command + cc := *gc + cc.result = nil + cc.stdin = nil + cc.timeout = 0 + cc.rawStdErr = "" + // Clone Env + cc.Env = make(map[string]string, len(gc.Env)) + for k, v := range gc.Env { + cc.Env[k] = v + } + return &cc +} + +func (gc *GenericCommand) T() *testing.T { + return gc.t +} + +func (gc *GenericCommand) clear() TestableCommand { + cc := *gc + cc.mainBinary = "" + cc.helperBinary = "" + cc.mainArgs = []string{} + cc.prependArgs = []string{} + cc.helperArgs = []string{} + // Clone Env + cc.Env = make(map[string]string, len(gc.Env)) + // Reset configuration + cc.Config = &config{} + for k, v := range gc.Env { + cc.Env[k] = v + } + return &cc +} + +func (gc *GenericCommand) withT(t *testing.T) { + gc.t = t +} + +func (gc *GenericCommand) read(key ConfigKey) ConfigValue { + return gc.Config.Read(key) +} + +func (gc *GenericCommand) write(key ConfigKey, value ConfigValue) { + gc.Config.Write(key, value) +} + func (gc *GenericCommand) boot() icmd.Cmd { // This is a helper function, not to appear in the debugging output if gc.t != nil { @@ -133,7 +212,7 @@ func (gc *GenericCommand) boot() icmd.Cmd { } binary := gc.mainBinary - args := gc.mainArgs + args := append(gc.prependArgs, gc.mainArgs...) if gc.helperBinary != "" { args = append([]string{binary}, args...) args = append(gc.helperArgs, args...) @@ -141,58 +220,35 @@ func (gc *GenericCommand) boot() icmd.Cmd { } // Create the command and set the env - // TODO: do we really need icmd? - icmdCmd := icmd.Command(binary, args...) - icmdCmd.Env = []string{} + // TODO: do we really need iCmd? + gc.t.Log(binary, strings.Join(args, " ")) + + iCmdCmd := icmd.Command(binary, args...) + iCmdCmd.Env = []string{} for _, v := range os.Environ() { - // Ignore LS_COLORS from the env, just too much noise - if !strings.HasPrefix(v, "LS_COLORS") { - icmdCmd.Env = append(icmdCmd.Env, v) + add := true + for _, b := range gc.envBlackList { + if strings.HasPrefix(v, b+"=") { + add = false + break + } + } + if add { + iCmdCmd.Env = append(iCmdCmd.Env, v) } } // Ensure the subprocess gets executed in a temporary directory unless explicitly instructed otherwise - icmdCmd.Dir = gc.WorkingDir - if icmdCmd.Dir == "" { - icmdCmd.Dir = gc.tempDir - } + iCmdCmd.Dir = gc.workingDir if gc.stdin != nil { - icmdCmd.Stdin = gc.stdin + iCmdCmd.Stdin = gc.stdin } // Attach any extra env we have for k, v := range gc.Env { - icmdCmd.Env = append(icmdCmd.Env, fmt.Sprintf("%s=%s", k, v)) + iCmdCmd.Env = append(iCmdCmd.Env, fmt.Sprintf("%s=%s", k, v)) } - return icmdCmd -} - -func (gc *GenericCommand) Clone() Command { - // Copy the command and return a new one - with WorkingDir, binary, args, etc - cc := *gc - // Clone Env - cc.Env = make(map[string]string, len(gc.Env)) - for k, v := range gc.Env { - cc.Env[k] = v - } - return &cc -} - -func (gc *GenericCommand) Clear() Command { - gc.mainBinary = "" - gc.helperBinary = "" - gc.mainArgs = []string{} - gc.helperArgs = []string{} - return gc -} - -func (gc *GenericCommand) WithT(t *testing.T) Command { - gc.t = t - return gc -} - -func (gc *GenericCommand) WithTempDir(tempDir string) { - gc.tempDir = tempDir + return iCmdCmd } diff --git a/pkg/testutil/test/config.go b/pkg/testutil/test/config.go new file mode 100644 index 00000000000..6cf5ceb0c25 --- /dev/null +++ b/pkg/testutil/test/config.go @@ -0,0 +1,71 @@ +/* + 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 test + +// WithConfig returns a config object with a certain config property set +func WithConfig(key ConfigKey, value ConfigValue) Config { + cfg := &config{} + cfg.Write(key, value) + return cfg +} + +// Contains the implementation of the Config interface + +func configureConfig(cfg Config, parent Config) Config { + if cfg == nil { + cfg = &config{ + config: make(map[ConfigKey]ConfigValue), + } + } + if parent != nil { + // Note: implementation dependent + cfg.(*config).adopt(parent) + } + return cfg +} + +type config struct { + config map[ConfigKey]ConfigValue +} + +func (cfg *config) Write(key ConfigKey, value ConfigValue) Config { + if cfg.config == nil { + cfg.config = make(map[ConfigKey]ConfigValue) + } + cfg.config[key] = value + return cfg +} + +func (cfg *config) Read(key ConfigKey) ConfigValue { + if cfg.config == nil { + cfg.config = make(map[ConfigKey]ConfigValue) + } + if val, ok := cfg.config[key]; ok { + return val + } + return "" +} + +func (cfg *config) adopt(parent Config) { + // Note: implementation dependent + for k, v := range parent.(*config).config { + // Only copy keys that are not set already + if _, ok := cfg.config[k]; !ok { + cfg.Write(k, v) + } + } +} diff --git a/pkg/testutil/test/data.go b/pkg/testutil/test/data.go index a2cc2d58b87..97c7659c6d5 100644 --- a/pkg/testutil/test/data.go +++ b/pkg/testutil/test/data.go @@ -24,40 +24,41 @@ import ( "testing" ) -// Contains the implementation of the Data interface - -type data struct { - config map[ConfigKey]ConfigValue - - system map[SystemKey]SystemValue - - labels map[string]string - testID string - tempDir string +// WithData returns a data object with a certain key value set +func WithData(key string, value string) Data { + dat := &data{} + dat.Set(key, value) + return dat } -func (dt *data) WithConfig(key ConfigKey, value ConfigValue) Data { - if dt.config == nil { - dt.config = make(map[ConfigKey]ConfigValue) - } - dt.config[key] = value - return dt -} +// Contains the implementation of the Data interface -func (dt *data) ReadConfig(key ConfigKey) ConfigValue { - if dt.config == nil { - dt.config = make(map[ConfigKey]ConfigValue) +func configureData(t *testing.T, seedData Data, parent Data) Data { + if seedData == nil { + seedData = &data{} } - if val, ok := dt.config[key]; ok { - return val + dat := &data{ + // Note: implementation dependent + labels: seedData.(*data).labels, + tempDir: t.TempDir(), + testID: func(suffix ...string) string { + suffix = append([]string{t.Name()}, suffix...) + return defaultIdentifierHashing(suffix...) + }, } - return "" + if parent != nil { + dat.adopt(parent) + } + return dat +} + +type data struct { + labels map[string]string + testID func(suffix ...string) string + tempDir string } func (dt *data) Get(key string) string { - if dt.labels == nil { - dt.labels = map[string]string{} - } return dt.labels[key] } @@ -69,8 +70,8 @@ func (dt *data) Set(key string, value string) Data { return dt } -func (dt *data) Identifier() string { - return dt.testID +func (dt *data) Identifier(suffix ...string) string { + return dt.testID(suffix...) } func (dt *data) TempDir() string { @@ -78,43 +79,13 @@ func (dt *data) TempDir() string { } func (dt *data) adopt(parent Data) { - for k, v := range parent.getLabels() { + // Note: implementation dependent + for k, v := range parent.(*data).labels { // Only copy keys that are not set already if _, ok := dt.labels[k]; !ok { dt.Set(k, v) } } - for k, v := range parent.getConfig() { - // Only copy keys that are not set already - if _, ok := dt.config[k]; !ok { - dt.WithConfig(k, v) - } - } -} - -func (dt *data) Sink(key SystemKey, value SystemValue) { - if _, ok := dt.system[key]; !ok { - dt.system[key] = value - } else { - // XXX should we really panic? - panic(fmt.Sprintf("Unable to set system key %s multiple times", key)) - } -} - -func (dt *data) Surface(key SystemKey) SystemValue { - if v, ok := dt.system[key]; ok { - return v - } - // XXX should we really panic? - panic(fmt.Sprintf("Unable to retrieve system key %s", key)) -} - -func (dt *data) getLabels() map[string]string { - return dt.labels -} - -func (dt *data) getConfig() map[ConfigKey]ConfigValue { - return dt.config } func defaultIdentifierHashing(names ...string) string { @@ -138,20 +109,3 @@ func defaultIdentifierHashing(names ...string) string { } return name + "-" + signature } - -// TODO: allow to pass custom hashing methods? -func configureData(t *testing.T, seedData Data, parent Data) Data { - if seedData == nil { - seedData = &data{} - } - dat := &data{ - config: seedData.getConfig(), - labels: seedData.getLabels(), - tempDir: t.TempDir(), - testID: defaultIdentifierHashing(t.Name()), - } - if parent != nil { - dat.adopt(parent) - } - return dat -} diff --git a/pkg/testutil/test/expected.go b/pkg/testutil/test/expected.go index 81d617acfdf..9057974c909 100644 --- a/pkg/testutil/test/expected.go +++ b/pkg/testutil/test/expected.go @@ -18,32 +18,20 @@ package test import ( "fmt" + "regexp" "strings" "testing" "gotest.tools/v3/assert" ) -func RunCommand(args ...string) Executor { - return func(data Data, helpers Helpers) Command { +// RunCommand is the simplest way to express a test.TestableCommand for very basic cases when access to test data is not necessary +func Command(args ...string) Executor { + return func(data Data, helpers Helpers) TestableCommand { return helpers.Command(args...) } } -// WithData returns a data object with a certain key value set -func WithData(key string, value string) Data { - dat := &data{} - dat.Set(key, value) - return dat -} - -// WithConfig returns a data object with a certain config property set -func WithConfig(key ConfigKey, value ConfigValue) Data { - dat := &data{} - dat.WithConfig(key, value) - return dat -} - // Expects is provided as a simple helper covering "expectations" for simple use-cases where access to the test data is not necessary func Expects(exitCode int, errors []error, output Comparator) Manager { return func(_ Data, _ Helpers) *Expected { @@ -55,7 +43,7 @@ func Expects(exitCode int, errors []error, output Comparator) Manager { } } -// All can be used as a parameter for expected.Output and allow passing a collection of conditions to match +// All can be used as a parameter for expected.Output to group a set of comparators func All(comparators ...Comparator) Comparator { return func(stdout string, info string, t *testing.T) { t.Helper() @@ -69,7 +57,7 @@ func All(comparators ...Comparator) Comparator { func Contains(compare string) Comparator { return func(stdout string, info string, t *testing.T) { t.Helper() - assert.Assert(t, strings.Contains(stdout, compare), fmt.Sprintf("Expected output to contain: %q", compare)+info) + assert.Check(t, strings.Contains(stdout, compare), fmt.Sprintf("Output does not contain: %q", compare)+info) } } @@ -77,7 +65,7 @@ func Contains(compare string) Comparator { func DoesNotContain(compare string) Comparator { return func(stdout string, info string, t *testing.T) { t.Helper() - assert.Assert(t, !strings.Contains(stdout, compare), fmt.Sprintf("Expected output to not contain: %q", compare)+info) + assert.Check(t, !strings.Contains(stdout, compare), fmt.Sprintf("Output does contain: %q", compare)+info) } } @@ -88,3 +76,12 @@ func Equals(compare string) Comparator { assert.Equal(t, compare, stdout, info) } } + +// Provisional - expected use, but have not seen it so far +// Match is to be used for expected.Output to ensure we match a regexp +func Match(reg *regexp.Regexp) Comparator { + return func(stdout string, info string, t *testing.T) { + t.Helper() + assert.Check(t, reg.MatchString(stdout), fmt.Sprintf("Output does not match: %s", reg), info) + } +} diff --git a/pkg/testutil/test/helpers.go b/pkg/testutil/test/helpers.go index 64a734dd86c..99d769d7c3e 100644 --- a/pkg/testutil/test/helpers.go +++ b/pkg/testutil/test/helpers.go @@ -18,37 +18,66 @@ package test import "testing" +// Helpers provides a set of helpers to run commands with simple expectations, available at all stages of a test (Setup, Cleanup, etc...) type Helpers interface { + // Ensure runs a command and verifies it is succeeding Ensure(args ...string) + // Anyhow runs a command and ignores its result Anyhow(args ...string) + // Fail runs a command and verifies it failed Fail(args ...string) + // Capture runs a command, verifies it succeeded, and returns stdout Capture(args ...string) string + // Err runs a command, and returns stderr regardless of its outcome + // This is mostly useful for debugging + Err(args ...string) string - Command(args ...string) Command - CustomCommand(binary string, args ...string) Command + // Command will return a populated command from the default internal command, with the provided arguments, + // ready to be Run or further configured + Command(args ...string) TestableCommand + // Custom will return a bare command, without configuration nor defaults (still has the Env) + Custom(binary string, args ...string) TestableCommand + + // Read return the config value associated with a key + Read(key ConfigKey) ConfigValue + // Write saves a value in the config + Write(key ConfigKey, value ConfigValue) + + // T returns the current testing object + T() *testing.T } -type helpers struct { - cmd Command +// This is the implementation of Helpers + +type helpersInternal struct { + cmdInternal CustomizableCommand + + t *testing.T } -func (hel *helpers) Ensure(args ...string) { - hel.Command(args...).Run(&Expected{}) +// Ensure will run a command and make sure it is successful +func (help *helpersInternal) Ensure(args ...string) { + help.Command(args...).Run(&Expected{ + ExitCode: 0, + }) } -func (hel *helpers) Anyhow(args ...string) { - hel.Command(args...).Run(nil) +// Anyhow will run a command regardless of outcome (may or may not fail) +func (help *helpersInternal) Anyhow(args ...string) { + help.Command(args...).Run(nil) } -func (hel *helpers) Fail(args ...string) { - hel.Command(args...).Run(&Expected{ +// Fail will run a command and make sure it does fail +func (help *helpersInternal) Fail(args ...string) { + help.Command(args...).Run(&Expected{ ExitCode: 1, }) } -func (hel *helpers) Capture(args ...string) string { +// Capture will run a command, ensure it is successful and return stdout +func (help *helpersInternal) Capture(args ...string) string { var ret string - hel.Command(args...).Run(&Expected{ + help.Command(args...).Run(&Expected{ Output: func(stdout string, info string, t *testing.T) { ret = stdout }, @@ -56,16 +85,37 @@ func (hel *helpers) Capture(args ...string) string { return ret } -func (hel *helpers) Command(args ...string) Command { - cc := hel.cmd.Clone() +// Capture will run a command, ensure it is successful and return stdout +func (help *helpersInternal) Err(args ...string) string { + cmd := help.Command(args...) + cmd.Run(nil) + return cmd.Stderr() +} + +// Command will return a clone of your base command without running it +func (help *helpersInternal) Command(args ...string) TestableCommand { + cc := help.cmdInternal.Clone() cc.WithArgs(args...) return cc } -func (hel *helpers) CustomCommand(binary string, args ...string) Command { - cc := hel.cmd.Clone() - cc.Clear() +// Custom will return a command for the requested binary and args, with the environment of your test +// (eg: Env, Cwd, etc.) +func (help *helpersInternal) Custom(binary string, args ...string) TestableCommand { + cc := help.cmdInternal.clear() cc.WithBinary(binary) cc.WithArgs(args...) return cc } + +func (help *helpersInternal) Read(key ConfigKey) ConfigValue { + return help.cmdInternal.read(key) +} + +func (help *helpersInternal) Write(key ConfigKey, value ConfigValue) { + help.cmdInternal.write(key, value) +} + +func (help *helpersInternal) T() *testing.T { + return help.t +} diff --git a/pkg/testutil/test/requirement.go b/pkg/testutil/test/requirement.go index c148fef1914..9a7abe0ca16 100644 --- a/pkg/testutil/test/requirement.go +++ b/pkg/testutil/test/requirement.go @@ -20,57 +20,49 @@ import ( "fmt" "os/exec" "runtime" - "testing" ) -func MakeRequirement(fn func(data Data, t *testing.T) (bool, string)) Requirement { - return func(data Data, skip bool, t *testing.T) (bool, string) { - ret, mess := fn(data, t) - - if skip && !ret { - t.Helper() - t.Skipf("Test skipped as %s", mess) - } +func Binary(name string) *Requirement { + return &Requirement{ + Check: func(data Data, helpers Helpers) (bool, string) { + mess := fmt.Sprintf("executable %q has been found in PATH", name) + ret := true + if _, err := exec.LookPath(name); err != nil { + ret = false + mess = fmt.Sprintf("executable %q doesn't exist in PATH", name) + } - return ret, mess + return ret, mess + }, } } -func Binary(name string) Requirement { - return MakeRequirement(func(data Data, t *testing.T) (ret bool, mess string) { - mess = fmt.Sprintf("executable %q has been found in PATH", name) - ret = true - if _, err := exec.LookPath(name); err != nil { - ret = false - mess = fmt.Sprintf("executable %q doesn't exist in PATH", name) - } - - return ret, mess - }) -} - -func OS(os string) Requirement { - return MakeRequirement(func(data Data, t *testing.T) (ret bool, mess string) { - mess = fmt.Sprintf("current operating system is %q", runtime.GOOS) - ret = true - if runtime.GOOS != os { - ret = false - } +func OS(os string) *Requirement { + return &Requirement{ + Check: func(data Data, helpers Helpers) (bool, string) { + mess := fmt.Sprintf("current operating system is %q", runtime.GOOS) + ret := true + if runtime.GOOS != os { + ret = false + } - return ret, mess - }) + return ret, mess + }, + } } -func Arch(arch string) Requirement { - return MakeRequirement(func(data Data, t *testing.T) (ret bool, mess string) { - mess = fmt.Sprintf("current architecture is %q", runtime.GOARCH) - ret = true - if runtime.GOARCH != arch { - ret = false - } +func Arch(arch string) *Requirement { + return &Requirement{ + Check: func(data Data, helpers Helpers) (bool, string) { + mess := fmt.Sprintf("current architecture is %q", runtime.GOARCH) + ret := true + if runtime.GOARCH != arch { + ret = false + } - return ret, mess - }) + return ret, mess + }, + } } var Amd64 = Arch("amd64") @@ -79,26 +71,45 @@ var Windows = OS("windows") var Linux = OS("linux") var Darwin = OS("darwin") -func Not(requirement Requirement) Requirement { - return MakeRequirement(func(data Data, t *testing.T) (ret bool, mess string) { - b, mess := requirement(data, false, t) +// NOTE: Not will always lose setups and cleanups... - return !b, mess - }) +func Not(requirement *Requirement) *Requirement { + return &Requirement{ + Check: func(data Data, helpers Helpers) (bool, string) { + ret, mess := requirement.Check(data, helpers) + return !ret, mess + }, + } } -func Require(thing ...Requirement) Requirement { - return func(data Data, skip bool, t *testing.T) (ret bool, mess string) { - for _, th := range thing { - b, m := th(data, false, t) - if !b { - if skip { - t.Helper() - t.Skipf("Test skipped as %s", m) +func Require(requirements ...*Requirement) *Requirement { + return &Requirement{ + Check: func(data Data, helpers Helpers) (bool, string) { + ret := true + mess := "" + var subMess string + for _, requirement := range requirements { + ret, subMess = requirement.Check(data, helpers) + mess += "\n" + subMess + if !ret { + return ret, mess + } + } + return ret, mess + }, + Setup: func(data Data, helpers Helpers) { + for _, requirement := range requirements { + if requirement.Setup != nil { + requirement.Setup(data, helpers) + } + } + }, + Cleanup: func(data Data, helpers Helpers) { + for _, requirement := range requirements { + if requirement.Cleanup != nil { + requirement.Cleanup(data, helpers) } - return false, "" } - } - return true, "" + }, } } diff --git a/pkg/testutil/test/test.go b/pkg/testutil/test/test.go index 858563be789..e8f3a9dfe4f 100644 --- a/pkg/testutil/test/test.go +++ b/pkg/testutil/test/test.go @@ -22,53 +22,35 @@ import ( "time" ) -// A Requirement is a function that can evaluate random requirement and possibly skip a test -// See test.MakeRequirement to make your own -type Requirement func(data Data, skip bool, t *testing.T) (bool, string) +// A Requirement offers a way to verify random conditions to decide if a test should be skipped or run. +// It can furthermore (optionally) provide custom Setup and Cleanup routines. +type Requirement struct { + // Check is expected to perform random operations and return a boolean and an explanatory message + Check Evaluator + // Setup, if provided, will be run before any test-specific Setup routine, in the order that requirements have been declared + Setup Butler + // Cleanup, if provided, will be run after any test-specific Cleanup routine, in the revers order that requirements have been declared + Cleanup Butler +} + +// An Evaluator is a function that decides whether a test should run or not +type Evaluator func(data Data, helpers Helpers) (bool, string) -// A Butler is the function signature meant to be attached to a Setup or Cleanup routine for a test.Case +// A Butler is the function signature meant to be attached to a Setup or Cleanup routine for a Case or Requirement type Butler func(data Data, helpers Helpers) -// An Executor is the function signature meant to be attached to a test.Case Command -type Executor func(data Data, helpers Helpers) Command +// An Executor is the function signature meant to be attached to the Command property of a Case +type Executor func(data Data, helpers Helpers) TestableCommand // A Manager is the function signature to be run to produce expectations to be fed to a command type Manager func(data Data, helpers Helpers) *Expected -// The Command interface represents a low-level command to execute, typically to be compared with an Expected -// A Command can be used as a Case Command obviously, but also as part of a Setup or Cleanup routine, -// and as the basis of any type of helper. -// A Command can be cloned, in which case, the subcommand inherits a copy of all of its Env and parameters. -// Typically, a Case has a base-command, from which all commands involved in the test are derived. -type Command interface { - // WithBinary specifies what binary to execute - WithBinary(binary string) Command - // WithArgs specifies the args to pass to the binary. Note that WithArgs is additive. - WithArgs(args ...string) Command - // WithEnv adds the passed map to the environment of the command to be executed - WithEnv(env map[string]string) Command - // WithWrapper allows wrapping a command with another command (for example: `time`, `unbuffer`) - WithWrapper(binary string, args ...string) Command - // WithStdin allows passing a reader to be used for stdin for the command - WithStdin(r io.Reader) Command - // Run does execute the command, and compare the output with the provided expectation. - // Passing nil for `Expected` will just run the command regardless of outcome. - // An empty `&Expected{}` is (of course) equivalent to &Expected{Exit: 0}, meaning the command is verified to be - // successful - Run(expect *Expected) - // Clone returns a copy of the command - Clone() Command - // Clear will clear binary and arguments, but retain the env, or any other custom properties - Clear() Command - // Allow starting a command in the background - Background(timeout time.Duration) Command -} - +// A Comparator is the function signature to implement for the Output property of an Expected type Comparator func(stdout string, info string, t *testing.T) // Expected expresses the expected output of a command type Expected struct { - // ExitCode to expect + // ExitCode ExitCode int // Errors contains any error that (once serialized) should be seen in stderr Errors []error @@ -76,16 +58,11 @@ type Expected struct { Output Comparator } -type ConfigKey string -type ConfigValue string - -type SystemKey string -type SystemValue string - // Data is meant to hold information about a test: // - first, any random key value data that the test implementer wants to carry / modify - this is test data -// - second, configuration specific to the binary being tested - typically defined by the specialized command being tested -// - third, immutable "system" info (unique identifier, tempdir, or other SystemKey/Value pairs) +// - second, some commonly useful immutable test properties (a way to generate unique identifiers for that test, +// temporary directory, etc.) +// Note that Data is inherited, from parent test to subtest (except for Identifier and TempDir of course) type Data interface { // Get returns the value of a certain key for custom data Get(key string) string @@ -93,27 +70,91 @@ type Data interface { Set(key string, value string) Data // Identifier returns the test identifier that can be used to name resources - Identifier() string + Identifier(suffix ...string) string // TempDir returns the test temporary directory TempDir() string - // Sink allows to define ONCE a certain system property - Sink(key SystemKey, value SystemValue) - // Surface allows retrieving a certain system property - Surface(key SystemKey) SystemValue - - // WithConfig allows setting a declared ConfigKey to a ConfigValue - WithConfig(key ConfigKey, value ConfigValue) Data - ReadConfig(key ConfigKey) ConfigValue - - // Private methods - getLabels() map[string]string - getConfig() map[ConfigKey]ConfigValue +} + +type ConfigKey string +type ConfigValue string + +// Config is meant to hold information relevant to the binary (eg: flags defining certain behaviors, etc.) +type Config interface { + // Write + Write(key ConfigKey, value ConfigValue) Config + // Read + Read(key ConfigKey) ConfigValue +} + +// The TestableCommand interface represents a low-level command to execute, typically to be compared with an Expected +// A TestableCommand can be used as a Case Command obviously, but also as part of a Setup or Cleanup routine, +// and as the basis of any type of helper. +// For more powerful usecase outside of test cases, see below CustomizableCommand +type TestableCommand interface { + // WithBinary specifies what binary to execute + WithBinary(binary string) + // WithArgs specifies the args to pass to the binary. Note that WithArgs can be used multiple times and is additive. + WithArgs(args ...string) + // WithWrapper allows wrapping a command with another command (for example: `time`, `unbuffer`) + WithWrapper(binary string, args ...string) + // WithStdin allows passing a reader to be used for stdin for the command + WithStdin(r io.Reader) + // WithCwd allows specifying the working directory for the command + WithCwd(path string) + // Clone returns a copy of the command + Clone() TestableCommand + + // Run does execute the command, and compare the output with the provided expectation. + // Passing nil for `Expected` will just run the command regardless of outcome. + // An empty `&Expected{}` is (of course) equivalent to &Expected{Exit: 0}, meaning the command is verified to be + // successful + Run(expect *Expected) + // Background allows starting a command in the background + Background(timeout time.Duration) + // Stderr allows retrieving the raw stderr output of the command + Stderr() string +} + +// ///////////////////////////////////////////// +// CustomizableCommand is an interface meant for people who want to heavily customize the base command of their test case +// It is passed along +type CustomizableCommand interface { + TestableCommand + + PrependArgs(args ...string) + // WithBlacklist allows to filter out unwanted variables from the embedding environment - default it pass any that is + // defined by WithEnv + WithBlacklist(env []string) + + // withEnv *copies* the passed map to the environment of the command to be executed + // Note that this will override any variable defined in the embedding environment + withEnv(env map[string]string) + // withTempDir specifies a temporary directory to use + withTempDir(path string) + // WithConfig allows passing custom config properties from the test to the base command + withConfig(config Config) + withT(t *testing.T) + // Clear does a clone, but will clear binary and arguments, but retain the env, or any other custom properties + // Gotcha: if GenericCommand is embedded with a custom Run and an overridden clear to return the embedding type + // the result will be the embedding command, no longer the GenericCommand + clear() TestableCommand + + // Will manipulate specific configuration option on the command + // Note that config is a copy of the test config + // Any modification done here will not be passed along to subtests, although they are shared amongst all commands of the test. + write(key ConfigKey, value ConfigValue) + read(key ConfigKey) ConfigValue +} + +type Testable interface { + CustomCommand(testCase *Case, t *testing.T) CustomizableCommand + AmbientRequirements(testCase *Case, t *testing.T) } var ( - registeredInit func(test *Case, t *testing.T) Command + registeredTestable Testable ) -func CustomCommand(custom func(test *Case, t *testing.T) Command) { - registeredInit = custom +func Customize(testable Testable) { + registeredTestable = testable } diff --git a/pkg/testutil/test/utilities.go b/pkg/testutil/test/utilities.go new file mode 100644 index 00000000000..b12715d7b82 --- /dev/null +++ b/pkg/testutil/test/utilities.go @@ -0,0 +1,42 @@ +/* + 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 test + +import ( + "crypto/rand" + "encoding/base64" + "fmt" + "os" +) + +// IsRoot returns true if we are root... simple +func IsRoot() bool { + return os.Geteuid() == 0 +} + +// RandomStringBase64 generates a base64 encoded random string +func RandomStringBase64(n int) string { + b := make([]byte, n) + l, err := rand.Read(b) + if err != nil { + panic(err) + } + if l != n { + panic(fmt.Errorf("expected %d bytes, got %d bytes", n, l)) + } + return base64.URLEncoding.EncodeToString(b) +} diff --git a/pkg/testutil/testregistry/certsd_linux.go b/pkg/testutil/testregistry/certsd_linux.go index 955bc4ba12f..2a9587e08c4 100644 --- a/pkg/testutil/testregistry/certsd_linux.go +++ b/pkg/testutil/testregistry/certsd_linux.go @@ -17,31 +17,11 @@ package testregistry import ( - "fmt" - "net" - "os" - "path/filepath" - "strconv" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/hoststoml" ) func generateCertsd(dir string, certPath string, hostIP string, port int) error { - joined := hostIP - if port != 0 { - joined = net.JoinHostPort(hostIP, strconv.Itoa(port)) - } - - hostsSubDir := filepath.Join(dir, joined) - err := os.MkdirAll(hostsSubDir, 0700) - if err != nil { - return err - } - - hostsTOMLPath := filepath.Join(hostsSubDir, "hosts.toml") - // See https://github.com/containerd/containerd/blob/main/docs/hosts.md - hostsTOML := fmt.Sprintf(` -server = "https://%s" -[host."https://%s"] - ca = %q - `, joined, joined, certPath) - return os.WriteFile(hostsTOMLPath, []byte(hostsTOML), 0700) + return (&hoststoml.HostsToml{ + CA: certPath, + }).Save(dir, hostIP, port) } diff --git a/pkg/testutil/testregistry/testregistry_linux.go b/pkg/testutil/testregistry/testregistry_linux.go index 61342b1a28f..72701d5998d 100644 --- a/pkg/testutil/testregistry/testregistry_linux.go +++ b/pkg/testutil/testregistry/testregistry_linux.go @@ -29,6 +29,7 @@ import ( "gotest.tools/v3/assert" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/platform" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/v2/pkg/testutil/portlock" "github.com/containerd/nerdctl/v2/pkg/testutil/testca" @@ -56,17 +57,17 @@ type TokenAuthServer struct { } func EnsureImages(base *testutil.Base) { - registryImage := testutil.RegistryImageStable + registryImage := platform.RegistryImageStable up := os.Getenv("DISTRIBUTION_VERSION") if up != "" { if up[0:1] != "v" { up = "v" + up } - registryImage = testutil.RegistryImageNext + up + registryImage = platform.RegistryImageNext + up } - base.Cmd("pull", registryImage).AssertOK() - base.Cmd("pull", testutil.DockerAuthImage).AssertOK() - base.Cmd("pull", testutil.KuboImage).AssertOK() + base.Cmd("pull", "--quiet", registryImage).AssertOK() + base.Cmd("pull", "--quiet", platform.DockerAuthImage).AssertOK() + base.Cmd("pull", "--quiet", platform.KuboImage).AssertOK() } func NewAuthServer(base *testutil.Base, ca *testca.CA, port int, user, pass string, tls bool) *TokenAuthServer { diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index a7237ad6c82..4287db9b305 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -549,6 +549,8 @@ var ( flagTestKillDaemon bool flagTestIPv6 bool flagTestKube bool + flagVerbose bool + flagTestFlaky bool ) var ( @@ -560,6 +562,10 @@ func M(m *testing.M) { flag.BoolVar(&flagTestKillDaemon, "test.allow-kill-daemon", false, "enable tests that kill the daemon") flag.BoolVar(&flagTestIPv6, "test.only-ipv6", false, "enable tests on IPv6") flag.BoolVar(&flagTestKube, "test.only-kubernetes", false, "enable tests on Kubernetes") + flag.BoolVar(&flagTestFlaky, "test.only-flaky", false, "enable testing of flaky tests only") + if flag.Lookup("test.v") != nil { + flagVerbose = true + } flag.Parse() os.Exit(func() int { @@ -625,6 +631,10 @@ func GetEnableKubernetes() bool { return flagTestKube } +func GetFlakyEnvironment() bool { + return flagTestFlaky +} + func GetDaemonIsKillable() bool { return flagTestKillDaemon } @@ -633,6 +643,8 @@ func IsDocker() bool { return GetTarget() == Docker } +func GetVerbose() bool { return flagVerbose } + func DockerIncompatible(t testing.TB) { if IsDocker() { t.Skip("test is incompatible with Docker") From 2d2afe0860e3ae9daf7e808561140ab4510ed4ea Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 7 Oct 2024 00:13:55 -0700 Subject: [PATCH 0812/1066] ./cmd/nerdctl/volume touchups With the updated tooling, a few changes are required to existing (migrated) tests. Specifically: - removal of test.Group - renaming of test.RunCommand (test.Command) and test.Command (test.TestableCommand) Other trivial changes involves simplifying syntax. Signed-off-by: apostasie --- cmd/nerdctl/volume/volume_create_test.go | 34 +- cmd/nerdctl/volume/volume_inspect_test.go | 292 ++++----- cmd/nerdctl/volume/volume_list_test.go | 587 +++++++++--------- cmd/nerdctl/volume/volume_namespace_test.go | 126 ++-- cmd/nerdctl/volume/volume_prune_linux_test.go | 113 ++-- .../volume/volume_remove_linux_test.go | 99 +-- 6 files changed, 637 insertions(+), 614 deletions(-) diff --git a/cmd/nerdctl/volume/volume_create_test.go b/cmd/nerdctl/volume/volume_create_test.go index 767f7ac12be..1cde5336199 100644 --- a/cmd/nerdctl/volume/volume_create_test.go +++ b/cmd/nerdctl/volume/volume_create_test.go @@ -18,6 +18,7 @@ package volume import ( "errors" + "regexp" "testing" "github.com/containerd/errdefs" @@ -27,27 +28,27 @@ import ( ) func TestVolumeCreate(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - tg := &test.Group{ + testCase.SubTests = []*test.Case{ { Description: "arg missing should create anonymous volume", - Command: test.RunCommand("volume", "create"), - Expected: test.Expects(0, nil, nil), + Command: test.Command("volume", "create"), + Expected: test.Expects(0, nil, test.Match(regexp.MustCompile("^[a-f0-9]{64}\n$"))), }, { Description: "invalid identifier should fail", - Command: test.RunCommand("volume", "create", "∞"), + Command: test.Command("volume", "create", "∞"), Expected: test.Expects(1, []error{errdefs.ErrInvalidArgument}, nil), }, { Description: "too many args should fail", - Command: test.RunCommand("volume", "create", "too", "many"), + Command: test.Command("volume", "create", "too", "many"), Expected: test.Expects(1, []error{errors.New("at most 1 arg")}, nil), }, { Description: "success", - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("volume", "create", data.Identifier()) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -61,7 +62,7 @@ func TestVolumeCreate(t *testing.T) { }, { Description: "success with labels", - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("volume", "create", "--label", "foo1=baz1", "--label", "foo2=baz2", data.Identifier()) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -74,28 +75,23 @@ func TestVolumeCreate(t *testing.T) { }, }, { - Description: "invalid labels", - Command: func(data test.Data, helpers test.Helpers) test.Command { + Description: "invalid labels should fail", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { // See https://github.com/containerd/nerdctl/issues/3126 return helpers.Command("volume", "create", "--label", "a", "--label", "", data.Identifier()) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("volume", "rm", "-f", data.Identifier()) }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - // NOTE: docker returns 125 on this - ExitCode: -1, - Errors: []error{errdefs.ErrInvalidArgument}, - } - }, + // NOTE: docker returns 125 on this + Expected: test.Expects(-1, []error{errdefs.ErrInvalidArgument}, nil), }, { Description: "creating already existing volume should succeed", Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("volume", "create", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("volume", "create", data.Identifier()) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -109,5 +105,5 @@ func TestVolumeCreate(t *testing.T) { }, } - tg.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/volume/volume_inspect_test.go b/cmd/nerdctl/volume/volume_inspect_test.go index edee98be906..a1c729b5c52 100644 --- a/cmd/nerdctl/volume/volume_inspect_test.go +++ b/cmd/nerdctl/volume/volume_inspect_test.go @@ -42,162 +42,170 @@ func createFileWithSize(mountPoint string, size int64) error { } func TestVolumeInspect(t *testing.T) { - nerdtest.Setup() - var size int64 = 1028 - tc := &test.Case{ - Description: "Volume inspect", - Setup: func(data test.Data, helpers test.Helpers) { - data.Set("volprefix", data.Identifier()) - helpers.Ensure("volume", "create", data.Identifier()) - helpers.Ensure("volume", "create", "--label", "foo=fooval", "--label", "bar=barval", data.Identifier()+"-second") - // Obviously note here that if inspect code gets totally hosed, this entire suite will - // probably fail right here on the Setup instead of actually testing something - vol := nerdtest.InspectVolume(helpers, data.Identifier()) - err := createFileWithSize(vol.Mountpoint, size) - assert.NilError(t, err, "File creation failed") + testCase := nerdtest.Setup() + + testCase.Require = nerdtest.BrokenTest("This test assumes that the host-side of a volume can be written into, "+ + "which is not always true. To be replaced by cp into the container.", + &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (bool, string) { + isDocker, _ := nerdtest.Docker.Check(data, helpers) + return !isDocker || test.IsRoot(), "docker cli needs to be run as root" + }, + }) + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("volume", "create", data.Identifier("first")) + helpers.Ensure("volume", "create", "--label", "foo=fooval", "--label", "bar=barval", data.Identifier("second")) + // Obviously note here that if inspect code gets totally hosed, this entire suite will + // probably fail right here on the Setup instead of actually testing something + vol := nerdtest.InspectVolume(helpers, data.Identifier("first")) + err := createFileWithSize(vol.Mountpoint, size) + assert.NilError(t, err, "File creation failed") + data.Set("vol1", data.Identifier("first")) + data.Set("vol2", data.Identifier("second")) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Identifier("first")) + helpers.Anyhow("volume", "rm", "-f", data.Identifier("second")) + } + + testCase.SubTests = []*test.Case{ + { + Description: "arg missing should fail", + Command: test.Command("volume", "inspect"), + Expected: test.Expects(1, []error{errors.New("requires at least 1 arg")}, nil), }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("volume", "rm", "-f", data.Identifier()) - helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-second") + { + Description: "invalid identifier should fail", + Command: test.Command("volume", "inspect", "∞"), + Expected: test.Expects(1, []error{errdefs.ErrInvalidArgument}, nil), }, - - SubTests: []*test.Case{ - { - Description: "arg missing should fail", - Command: test.RunCommand("volume", "inspect"), - Expected: test.Expects(1, []error{errors.New("requires at least 1 arg")}, nil), + { + Description: "non existent volume should fail", + Command: test.Command("volume", "inspect", "doesnotexist"), + Expected: test.Expects(1, []error{errdefs.ErrNotFound}, nil), + }, + { + Description: "success", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "inspect", data.Get("vol1")) }, - { - Description: "invalid identifier should fail", - Command: test.RunCommand("volume", "inspect", "∞"), - Expected: test.Expects(1, []error{errdefs.ErrInvalidArgument}, nil), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(data.Get("vol1")), + func(stdout string, info string, t *testing.T) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))+info) + assert.Assert(t, dc[0].Name == data.Get("vol1"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("vol1"), dc[0].Name)+info) + assert.Assert(t, dc[0].Labels == nil, fmt.Sprintf("expected labels to be nil and were %v", dc[0].Labels)+info) + }, + ), + } + }, + }, + { + Description: "inspect labels", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "inspect", data.Get("vol2")) }, - { - Description: "non existent volume should fail", - Command: test.RunCommand("volume", "inspect", "doesnotexist"), - Expected: test.Expects(1, []error{errdefs.ErrNotFound}, nil), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(data.Get("vol2")), + func(stdout string, info string, t *testing.T) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + labels := *dc[0].Labels + assert.Assert(t, len(labels) == 2, fmt.Sprintf("two results, not %d", len(labels))) + assert.Assert(t, labels["foo"] == "fooval", fmt.Sprintf("label foo should be fooval, not %s", labels["foo"])) + assert.Assert(t, labels["bar"] == "barval", fmt.Sprintf("label bar should be barval, not %s", labels["bar"])) + }, + ), + } }, - { - Description: "success", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "inspect", data.Get("volprefix")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.Contains(data.Get("volprefix")), - func(stdout string, info string, t *testing.T) { - var dc []native.Volume - if err := json.Unmarshal([]byte(stdout), &dc); err != nil { - t.Fatal(err) - } - assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))+info) - assert.Assert(t, dc[0].Name == data.Get("volprefix"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("volprefix"), dc[0].Name)+info) - assert.Assert(t, dc[0].Labels == nil, fmt.Sprintf("expected labels to be nil and were %v", dc[0].Labels)+info) - }, - ), - } - }, + }, + { + Description: "inspect size", + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "inspect", "--size", data.Get("vol1")) }, - { - Description: "inspect labels", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "inspect", data.Get("volprefix")+"-second") - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.Contains(data.Get("volprefix")), - func(stdout string, info string, t *testing.T) { - var dc []native.Volume - if err := json.Unmarshal([]byte(stdout), &dc); err != nil { - t.Fatal(err) - } - labels := *dc[0].Labels - assert.Assert(t, len(labels) == 2, fmt.Sprintf("two results, not %d", len(labels))) - assert.Assert(t, labels["foo"] == "fooval", fmt.Sprintf("label foo should be fooval, not %s", labels["foo"])) - assert.Assert(t, labels["bar"] == "barval", fmt.Sprintf("label bar should be barval, not %s", labels["bar"])) - }, - ), - } - }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(data.Get("vol1")), + func(stdout string, info string, t *testing.T) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, dc[0].Size == size, fmt.Sprintf("expected size to be %d (was %d)", size, dc[0].Size)) + }, + ), + } }, - { - Description: "inspect size", - Require: test.Not(nerdtest.Docker), - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "inspect", "--size", data.Get("volprefix")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.Contains(data.Get("volprefix")), - func(stdout string, info string, t *testing.T) { - var dc []native.Volume - if err := json.Unmarshal([]byte(stdout), &dc); err != nil { - t.Fatal(err) - } - assert.Assert(t, dc[0].Size == size, fmt.Sprintf("expected size to be %d (was %d)", size, dc[0].Size)) - }, - ), - } - }, + }, + { + Description: "multi success", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "inspect", data.Get("vol1"), data.Get("vol2")) }, - { - Description: "multi success", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "inspect", data.Get("volprefix"), data.Get("volprefix")+"-second") - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.Contains(data.Get("volprefix")), - test.Contains(data.Get("volprefix")+"-second"), - func(stdout string, info string, t *testing.T) { - var dc []native.Volume - if err := json.Unmarshal([]byte(stdout), &dc); err != nil { - t.Fatal(err) - } - assert.Assert(t, len(dc) == 2, fmt.Sprintf("two results, not %d", len(dc))) - assert.Assert(t, dc[0].Name == data.Get("volprefix"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("volprefix"), dc[0].Name)) - assert.Assert(t, dc[1].Name == data.Get("volprefix")+"-second", fmt.Sprintf("expected name to be %q (was %q)", data.Get("volprefix")+"-second", dc[1].Name)) - }, - ), - } - }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(data.Get("vol1")), + test.Contains(data.Get("vol2")), + func(stdout string, info string, t *testing.T) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, len(dc) == 2, fmt.Sprintf("two results, not %d", len(dc))) + assert.Assert(t, dc[0].Name == data.Get("vol1"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("vol1"), dc[0].Name)) + assert.Assert(t, dc[1].Name == data.Get("vol2"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("vol2"), dc[1].Name)) + }, + ), + } }, - { - Description: "part success multi", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "inspect", "invalid∞", "nonexistent", data.Get("volprefix")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - ExitCode: 1, - Errors: []error{errdefs.ErrNotFound, errdefs.ErrInvalidArgument}, - Output: test.All( - test.Contains(data.Get("volprefix")), - func(stdout string, info string, t *testing.T) { - var dc []native.Volume - if err := json.Unmarshal([]byte(stdout), &dc); err != nil { - t.Fatal(err) - } - assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))) - assert.Assert(t, dc[0].Name == data.Get("volprefix"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("volprefix"), dc[0].Name)) - }, - ), - } - }, + }, + { + Description: "part success multi", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "inspect", "invalid∞", "nonexistent", data.Get("vol1")) }, - { - Description: "multi failure", - Command: test.RunCommand("volume", "inspect", "invalid∞", "nonexistent"), - Expected: test.Expects(1, []error{errdefs.ErrNotFound, errdefs.ErrInvalidArgument}, nil), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errdefs.ErrNotFound, errdefs.ErrInvalidArgument}, + Output: test.All( + test.Contains(data.Get("vol1")), + func(stdout string, info string, t *testing.T) { + var dc []native.Volume + if err := json.Unmarshal([]byte(stdout), &dc); err != nil { + t.Fatal(err) + } + assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))) + assert.Assert(t, dc[0].Name == data.Get("vol1"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("vol1"), dc[0].Name)) + }, + ), + } }, }, + { + Description: "multi failure", + Command: test.Command("volume", "inspect", "invalid∞", "nonexistent"), + Expected: test.Expects(1, []error{errdefs.ErrNotFound, errdefs.ErrInvalidArgument}, nil), + }, } - tc.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/volume/volume_list_test.go b/cmd/nerdctl/volume/volume_list_test.go index 8f5892cb6d9..77954ee5b19 100644 --- a/cmd/nerdctl/volume/volume_list_test.go +++ b/cmd/nerdctl/volume/volume_list_test.go @@ -32,30 +32,34 @@ func TestVolumeLsSize(t *testing.T) { nerdtest.Setup() tc := &test.Case{ - Description: "Volume ls --size", - Require: test.Not(nerdtest.Docker), + Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("volume", "create", data.Identifier()+"-1") - helpers.Ensure("volume", "create", data.Identifier()+"-2") - helpers.Ensure("volume", "create", data.Identifier()+"-empty") - vol1 := nerdtest.InspectVolume(helpers, data.Identifier()+"-1") - vol2 := nerdtest.InspectVolume(helpers, data.Identifier()+"-2") + helpers.Ensure("volume", "create", data.Identifier("1")) + helpers.Ensure("volume", "create", data.Identifier("2")) + helpers.Ensure("volume", "create", data.Identifier("empty")) + vol1 := nerdtest.InspectVolume(helpers, data.Identifier("1")) + vol2 := nerdtest.InspectVolume(helpers, data.Identifier("2")) err := createFileWithSize(vol1.Mountpoint, 102400) assert.NilError(t, err, "File creation failed") err = createFileWithSize(vol2.Mountpoint, 204800) assert.NilError(t, err, "File creation failed") }, - Command: test.RunCommand("volume", "ls", "--size"), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Identifier("1")) + helpers.Anyhow("volume", "rm", "-f", data.Identifier("2")) + helpers.Anyhow("volume", "rm", "-f", data.Identifier("empty")) + }, + Command: test.Command("volume", "ls", "--size"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: func(stdout string, info string, t *testing.T) { var lines = strings.Split(strings.TrimSpace(stdout), "\n") assert.Assert(t, len(lines) >= 4, "expected at least 4 lines"+info) volSizes := map[string]string{ - data.Identifier() + "-1": "100.0 KiB", - data.Identifier() + "-2": "200.0 KiB", - data.Identifier() + "-empty": "0.0 B", + data.Identifier("1"): "100.0 KiB", + data.Identifier("2"): "200.0 KiB", + data.Identifier("empty"): "0.0 B", } var numMatches = 0 @@ -77,313 +81,320 @@ func TestVolumeLsSize(t *testing.T) { }, } }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-1") - helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-2") - helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-empty") - }, } tc.Run(t) } func TestVolumeLsFilter(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - tc := &test.Case{ - Description: "Volume ls", - Setup: func(data test.Data, helpers test.Helpers) { - var vol1, vol2, vol3, vol4 = data.Identifier() + "-1", data.Identifier() + "-2", data.Identifier() + "-3", data.Identifier() + "-4" - var label1, label2, label3, label4 = data.Identifier() + "=label-1", data.Identifier() + "=label-2", data.Identifier() + "=label-3", data.Identifier() + "-group=label-4" + testCase.Require = nerdtest.BrokenTest("This test assumes that the host-side of a volume can be written into, "+ + "which is not always true. To be replaced by cp into the container.", + &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (bool, string) { + isDocker, _ := nerdtest.Docker.Check(data, helpers) + return !isDocker || test.IsRoot(), "docker cli needs to be run as root" + }, + }) - helpers.Ensure("volume", "create", "--label="+label1, "--label="+label4, vol1) - helpers.Ensure("volume", "create", "--label="+label2, "--label="+label4, vol2) - helpers.Ensure("volume", "create", "--label="+label3, vol3) - helpers.Ensure("volume", "create", vol4) + testCase.Setup = func(data test.Data, helpers test.Helpers) { + var vol1, vol2, vol3, vol4 = data.Identifier("1"), data.Identifier("2"), data.Identifier("3"), data.Identifier("4") + var label1, label2, label3, label4 = "mylabel=label-1", "mylabel=label-2", "mylabel=label-3", "mylabel-group=label-4" - err := createFileWithSize(nerdtest.InspectVolume(helpers, vol1).Mountpoint, 409600) - assert.NilError(t, err, "File creation failed") - err = createFileWithSize(nerdtest.InspectVolume(helpers, vol2).Mountpoint, 1024000) - assert.NilError(t, err, "File creation failed") - err = createFileWithSize(nerdtest.InspectVolume(helpers, vol3).Mountpoint, 409600) - assert.NilError(t, err, "File creation failed") - err = createFileWithSize(nerdtest.InspectVolume(helpers, vol4).Mountpoint, 1024000) - assert.NilError(t, err, "File creation failed") + helpers.Ensure("volume", "create", "--label="+label1, "--label="+label4, vol1) + helpers.Ensure("volume", "create", "--label="+label2, "--label="+label4, vol2) + helpers.Ensure("volume", "create", "--label="+label3, vol3) + helpers.Ensure("volume", "create", vol4) + + // FIXME + // This will not work with Docker rootful and Docker cli run as a user + // We should replace it with cp inside the container + err := createFileWithSize(nerdtest.InspectVolume(helpers, vol1).Mountpoint, 409600) + assert.NilError(t, err, "File creation failed") + err = createFileWithSize(nerdtest.InspectVolume(helpers, vol2).Mountpoint, 1024000) + assert.NilError(t, err, "File creation failed") + err = createFileWithSize(nerdtest.InspectVolume(helpers, vol3).Mountpoint, 409600) + assert.NilError(t, err, "File creation failed") + err = createFileWithSize(nerdtest.InspectVolume(helpers, vol4).Mountpoint, 1024000) + assert.NilError(t, err, "File creation failed") - data.Set("vol1", vol1) - data.Set("vol2", vol2) - data.Set("vol3", vol3) - data.Set("vol4", vol4) - data.Set("mainlabel", data.Identifier()) - data.Set("label1", label1) - data.Set("label2", label2) - data.Set("label3", label3) - data.Set("label4", label4) + data.Set("vol1", vol1) + data.Set("vol2", vol2) + data.Set("vol3", vol3) + data.Set("vol4", vol4) + data.Set("mainlabel", "mylabel") + data.Set("label1", label1) + data.Set("label2", label2) + data.Set("label3", label3) + data.Set("label4", label4) + } + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", "-f", data.Get("vol1")) + helpers.Anyhow("volume", "rm", "-f", data.Get("vol2")) + helpers.Anyhow("volume", "rm", "-f", data.Get("vol3")) + helpers.Anyhow("volume", "rm", "-f", data.Get("vol4")) + } + testCase.SubTests = []*test.Case{ + { + Description: "No filter", + Command: test.Command("volume", "ls", "--quiet"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 4, "expected at least 4 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + data.Get("vol2"): {}, + data.Get("vol3"): {}, + data.Get("vol4"): {}, + } + var numMatches = 0 + for _, name := range lines { + _, ok := volNames[name] + if !ok { + continue + } + numMatches++ + } + assert.Assert(t, len(volNames) == numMatches, fmt.Sprintf("expected %d volumes, got: %d", len(volNames), numMatches)) + }, + } + }, }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("volume", "rm", "-f", data.Get("vol1")) - helpers.Anyhow("volume", "rm", "-f", data.Get("vol2")) - helpers.Anyhow("volume", "rm", "-f", data.Get("vol3")) - helpers.Anyhow("volume", "rm", "-f", data.Get("vol4")) + { + Description: "Retrieving label=mainlabel", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("mainlabel")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + data.Get("vol2"): {}, + data.Get("vol3"): {}, + } + for _, name := range lines { + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, + } + }, }, - SubTests: []*test.Case{ - { - Description: "No filter", - Command: test.RunCommand("volume", "ls", "--quiet"), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 4, "expected at least 4 lines"+info) - volNames := map[string]struct{}{ - data.Get("vol1"): {}, - data.Get("vol2"): {}, - data.Get("vol3"): {}, - data.Get("vol4"): {}, - } - var numMatches = 0 - for _, name := range lines { - _, ok := volNames[name] - if !ok { - continue - } - numMatches++ - } - assert.Assert(t, len(volNames) == numMatches, fmt.Sprintf("expected %d volumes, got: %d", len(volNames), numMatches)) - }, - } - }, + { + Description: "Retrieving label=mainlabel=label2", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("label2")) }, - { - Description: "Retrieving label=mainlabel", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("mainlabel")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) - volNames := map[string]struct{}{ - data.Get("vol1"): {}, - data.Get("vol2"): {}, - data.Get("vol3"): {}, - } - for _, name := range lines { - _, ok := volNames[name] - assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) - } - }, - } - }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 1, "expected at least 1 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol2"): {}, + } + for _, name := range lines { + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, + } }, - { - Description: "Retrieving label=mainlabel=label2", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("label2")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 1, "expected at least 1 lines"+info) - volNames := map[string]struct{}{ - data.Get("vol2"): {}, - } - for _, name := range lines { - _, ok := volNames[name] - assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) - } - }, - } - }, + }, + { + Description: "Retrieving label=mainlabel=", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("mainlabel")+"=") }, - { - Description: "Retrieving label=mainlabel=", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("mainlabel")+"=") - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - assert.Assert(t, strings.TrimSpace(stdout) == "", "expected no result"+info) - }, - } - }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + assert.Assert(t, strings.TrimSpace(stdout) == "", "expected no result"+info) + }, + } }, - { - Description: "Retrieving label=mainlabel=label1 and label=mainlabel=label2", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("label1"), "--filter", "label="+data.Get("label2")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - assert.Assert(t, strings.TrimSpace(stdout) == "", "expected no result"+info) - }, - } - }, + }, + { + Description: "Retrieving label=mainlabel=label1 and label=mainlabel=label2", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("label1"), "--filter", "label="+data.Get("label2")) }, - { - Description: "Retrieving label=mainlabel and label=grouplabel=label4", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("mainlabel"), "--filter", "label="+data.Get("label4")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 2, "expected at least 2 lines"+info) - volNames := map[string]struct{}{ - data.Get("vol1"): {}, - data.Get("vol2"): {}, - } - for _, name := range lines { - _, ok := volNames[name] - assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) - } - }, - } - }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + assert.Assert(t, strings.TrimSpace(stdout) == "", "expected no result"+info) + }, + } }, - { - Description: "Retrieving name=volume1", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "ls", "--quiet", "--filter", "name="+data.Get("vol1")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 1, "expected at least 1 line"+info) - volNames := map[string]struct{}{ - data.Get("vol1"): {}, - } - for _, name := range lines { - _, ok := volNames[name] - assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) - } - }, - } - }, + }, + { + Description: "Retrieving label=mainlabel and label=grouplabel=label4", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "ls", "--quiet", "--filter", "label="+data.Get("mainlabel"), "--filter", "label="+data.Get("label4")) }, - { - Description: "Retrieving name=volume1 and name=volume2", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "ls", "--quiet", "--filter", "name="+data.Get("vol1"), "--filter", "name="+data.Get("vol2")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 2, "expected at least 2 lines"+info) - volNames := map[string]struct{}{ - data.Get("vol1"): {}, - data.Get("vol2"): {}, - } - for _, name := range lines { - _, ok := volNames[name] - assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) - } - }, - } - }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 2, "expected at least 2 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + data.Get("vol2"): {}, + } + for _, name := range lines { + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, + } }, - { - Description: "Retrieving size=1024000", - Require: test.Not(nerdtest.Docker), - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "ls", "--size", "--filter", "size=1024000") - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) - volNames := map[string]struct{}{ - data.Get("vol2"): {}, - data.Get("vol4"): {}, - } - var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") - var err = tab.ParseHeader(lines[0]) - assert.NilError(t, err, "Tab reader failed") - for _, line := range lines { + }, + { + Description: "Retrieving name=volume1", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "ls", "--quiet", "--filter", "name="+data.Get("vol1")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 1, "expected at least 1 line"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + } + for _, name := range lines { + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, + } + }, + }, + { + Description: "Retrieving name=volume1 and name=volume2", + // Nerdctl filter behavior is broken + Require: nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3452"), + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "ls", "--quiet", "--filter", "name="+data.Get("vol1"), "--filter", "name="+data.Get("vol2")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 2, "expected at least 2 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + data.Get("vol2"): {}, + } + for _, name := range lines { + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, + } + }, + }, + { + Description: "Retrieving size=1024000", + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "ls", "--size", "--filter", "size=1024000") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol2"): {}, + data.Get("vol4"): {}, + } + var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") + var err = tab.ParseHeader(lines[0]) + assert.NilError(t, err, "Tab reader failed") + for _, line := range lines { - name, _ := tab.ReadRow(line, "VOLUME NAME") - if name == "VOLUME NAME" { - continue - } - _, ok := volNames[name] - assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + name, _ := tab.ReadRow(line, "VOLUME NAME") + if name == "VOLUME NAME" { + continue } - }, - } - }, + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, + } }, - { - Description: "Retrieving size>=1024000 size<=2048000", - Require: test.Not(nerdtest.Docker), - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "ls", "--size", "--filter", "size>=1024000", "--filter", "size<=2048000") - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) - volNames := map[string]struct{}{ - data.Get("vol2"): {}, - data.Get("vol4"): {}, - } - var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") - var err = tab.ParseHeader(lines[0]) - assert.NilError(t, err, "Tab reader failed") - for _, line := range lines { + }, + { + Description: "Retrieving size>=1024000 size<=2048000", + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "ls", "--size", "--filter", "size>=1024000", "--filter", "size<=2048000") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol2"): {}, + data.Get("vol4"): {}, + } + var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") + var err = tab.ParseHeader(lines[0]) + assert.NilError(t, err, "Tab reader failed") + for _, line := range lines { - name, _ := tab.ReadRow(line, "VOLUME NAME") - if name == "VOLUME NAME" { - continue - } - _, ok := volNames[name] - assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + name, _ := tab.ReadRow(line, "VOLUME NAME") + if name == "VOLUME NAME" { + continue } - }, - } - }, + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, + } }, - { - Description: "Retrieving size>204800 size<1024000", - Require: test.Not(nerdtest.Docker), - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "ls", "--size", "--filter", "size>204800", "--filter", "size<1024000") - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) - volNames := map[string]struct{}{ - data.Get("vol1"): {}, - data.Get("vol3"): {}, - } - var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") - var err = tab.ParseHeader(lines[0]) - assert.NilError(t, err, "Tab reader failed") - for _, line := range lines { + }, + { + Description: "Retrieving size>204800 size<1024000", + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "ls", "--size", "--filter", "size>204800", "--filter", "size<1024000") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 3, "expected at least 3 lines"+info) + volNames := map[string]struct{}{ + data.Get("vol1"): {}, + data.Get("vol3"): {}, + } + var tab = tabutil.NewReader("VOLUME NAME\tDIRECTORY\tSIZE") + var err = tab.ParseHeader(lines[0]) + assert.NilError(t, err, "Tab reader failed") + for _, line := range lines { - name, _ := tab.ReadRow(line, "VOLUME NAME") - if name == "VOLUME NAME" { - continue - } - _, ok := volNames[name] - assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + name, _ := tab.ReadRow(line, "VOLUME NAME") + if name == "VOLUME NAME" { + continue } - }, - } - }, + _, ok := volNames[name] + assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info) + } + }, + } }, }, } - tc.Run(t) + + testCase.Run(t) } diff --git a/cmd/nerdctl/volume/volume_namespace_test.go b/cmd/nerdctl/volume/volume_namespace_test.go index b20f64984dc..c2a2d6ce3db 100644 --- a/cmd/nerdctl/volume/volume_namespace_test.go +++ b/cmd/nerdctl/volume/volume_namespace_test.go @@ -26,71 +26,81 @@ import ( ) func TestVolumeNamespace(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - tg := &test.Case{ - Description: "Namespaces", - Require: test.Not(nerdtest.Docker), - Setup: func(data test.Data, helpers test.Helpers) { - data.Set("root_namespace", data.Identifier()) - data.Set("root_volume", data.Identifier()) - helpers.Ensure("--namespace", data.Identifier(), "volume", "create", data.Identifier()) - }, - SubTests: []*test.Case{ - { - Description: "inspect another namespace volume should fail", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "inspect", data.Get("root_volume")) - }, - Expected: test.Expects(1, []error{ - errdefs.ErrNotFound, - }, nil), - }, - { - Description: "removing another namespace volume should fail", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "remove", data.Get("root_volume")) - }, - Expected: test.Expects(1, []error{ - errdefs.ErrNotFound, - }, nil), + // Docker does not support namespaces + testCase.Require = test.Not(nerdtest.Docker) + + // Create a volume in a different namespace + testCase.Setup = func(data test.Data, helpers test.Helpers) { + data.Set("root_namespace", data.Identifier()) + data.Set("root_volume", data.Identifier()) + helpers.Ensure("--namespace", data.Identifier(), "volume", "create", data.Identifier()) + } + + // Cleanup once done + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if data.Get("root_namespace") != "" { + helpers.Anyhow("--namespace", data.Identifier(), "volume", "remove", data.Identifier()) + helpers.Anyhow("namespace", "remove", data.Identifier()) + } + } + + testCase.SubTests = []*test.Case{ + { + Description: "inspect another namespace volume should fail", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "inspect", data.Get("root_volume")) }, - { - Description: "prune should leave another namespace volume untouched", - NoParallel: true, - Command: test.RunCommand("volume", "prune", "-a", "-f"), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.DoesNotContain(data.Get("root_volume")), - func(stdout string, info string, t *testing.T) { - helpers.Ensure("--namespace", data.Get("root_namespace"), "volume", "inspect", data.Get("root_volume")) - }, - ), - } - }, + Expected: test.Expects(1, []error{ + errdefs.ErrNotFound, + }, nil), + }, + { + Description: "removing another namespace volume should fail", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "remove", data.Get("root_volume")) }, - { - Description: "create with the same name should work, then delete it", - NoParallel: true, - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "create", data.Get("root_volume")) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("volume", "rm", data.Get("root_volume")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - helpers.Ensure("volume", "inspect", data.Get("root_volume")) - helpers.Ensure("volume", "rm", data.Get("root_volume")) + Expected: test.Expects(1, []error{ + errdefs.ErrNotFound, + }, nil), + }, + { + Description: "prune should leave another namespace volume untouched", + // Make it private so that we do not interact with other tests in the main namespace + Require: nerdtest.Private, + Command: test.Command("volume", "prune", "-a", "-f"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain(data.Get("root_volume")), + func(stdout string, info string, t *testing.T) { helpers.Ensure("--namespace", data.Get("root_namespace"), "volume", "inspect", data.Get("root_volume")) }, - } - }, + ), + } + }, + }, + { + Description: "create with the same name should work, then delete it", + NoParallel: true, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "create", data.Get("root_volume")) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("volume", "rm", data.Get("root_volume")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + helpers.Ensure("volume", "inspect", data.Get("root_volume")) + helpers.Ensure("volume", "rm", data.Get("root_volume")) + helpers.Ensure("--namespace", data.Get("root_namespace"), "volume", "inspect", data.Get("root_volume")) + }, + } }, }, } - tg.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/volume/volume_prune_linux_test.go b/cmd/nerdctl/volume/volume_prune_linux_test.go index da859b1af43..c33922c730b 100644 --- a/cmd/nerdctl/volume/volume_prune_linux_test.go +++ b/cmd/nerdctl/volume/volume_prune_linux_test.go @@ -26,20 +26,18 @@ import ( ) func TestVolumePrune(t *testing.T) { - nerdtest.Setup() - var setup = func(data test.Data, helpers test.Helpers) { anonIDBusy := strings.TrimSpace(helpers.Capture("volume", "create")) anonIDDangling := strings.TrimSpace(helpers.Capture("volume", "create")) - namedBusy := data.Identifier() + "-busy" - namedDangling := data.Identifier() + "-free" + namedBusy := data.Identifier("busy") + namedDangling := data.Identifier("free") helpers.Ensure("volume", "create", namedBusy) helpers.Ensure("volume", "create", namedDangling) helpers.Ensure("run", "--name", data.Identifier(), - "-v", namedBusy+":/whatever", - "-v", anonIDBusy+":/other", testutil.CommonImage) + "-v", namedBusy+":/namedbusyvolume", + "-v", anonIDBusy+":/anonbusyvolume", testutil.CommonImage) data.Set("anonIDBusy", anonIDBusy) data.Set("anonIDDangling", anonIDDangling) @@ -49,62 +47,61 @@ func TestVolumePrune(t *testing.T) { var cleanup = func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("rm", "-f", data.Get("anonIDBusy")) - helpers.Anyhow("rm", "-f", data.Get("anonIDDangling")) - helpers.Anyhow("rm", "-f", data.Get("namedBusy")) - helpers.Anyhow("rm", "-f", data.Get("namedDangling")) + helpers.Anyhow("volume", "rm", "-f", data.Get("anonIDBusy")) + helpers.Anyhow("volume", "rm", "-f", data.Get("anonIDDangling")) + helpers.Anyhow("volume", "rm", "-f", data.Get("namedBusy")) + helpers.Anyhow("volume", "rm", "-f", data.Get("namedDangling")) } + testCase := nerdtest.Setup() // This set must be marked as private, since we cannot prune without interacting with other tests. - testCase := &test.Case{ - Description: "Prune", - Require: nerdtest.Private, - SubTests: []*test.Case{ - { - Description: "prune anonymous only", - NoParallel: true, - Command: test.RunCommand("volume", "prune", "-f"), - Setup: setup, - Cleanup: cleanup, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.DoesNotContain(data.Get("anonIDBusy")), - test.Contains(data.Get("anonIDDangling")), - test.DoesNotContain(data.Get("namedBusy")), - test.DoesNotContain(data.Get("namedDangling")), - func(stdout string, info string, t *testing.T) { - helpers.Ensure("volume", "inspect", data.Get("anonIDBusy")) - helpers.Fail("volume", "inspect", data.Get("anonIDDangling")) - helpers.Ensure("volume", "inspect", data.Get("namedBusy")) - helpers.Ensure("volume", "inspect", data.Get("namedDangling")) - }, - ), - } - }, + testCase.Require = nerdtest.Private + // Furthermore, these two subtests cannot be run in parallel + testCase.SubTests = []*test.Case{ + { + Description: "prune anonymous only", + NoParallel: true, + Setup: setup, + Cleanup: cleanup, + Command: test.Command("volume", "prune", "-f"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain(data.Get("anonIDBusy")), + test.Contains(data.Get("anonIDDangling")), + test.DoesNotContain(data.Get("namedBusy")), + test.DoesNotContain(data.Get("namedDangling")), + func(stdout string, info string, t *testing.T) { + helpers.Ensure("volume", "inspect", data.Get("anonIDBusy")) + helpers.Fail("volume", "inspect", data.Get("anonIDDangling")) + helpers.Ensure("volume", "inspect", data.Get("namedBusy")) + helpers.Ensure("volume", "inspect", data.Get("namedDangling")) + }, + ), + } }, - { - Description: "prune all", - NoParallel: true, - Command: test.RunCommand("volume", "prune", "-f", "--all"), - Setup: setup, - Cleanup: cleanup, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.DoesNotContain(data.Get("anonIDBusy")), - test.Contains(data.Get("anonIDDangling")), - test.DoesNotContain(data.Get("namedBusy")), - test.Contains(data.Get("namedDangling")), - func(stdout string, info string, t *testing.T) { - helpers.Ensure("volume", "inspect", data.Get("anonIDBusy")) - helpers.Fail("volume", "inspect", data.Get("anonIDDangling")) - helpers.Ensure("volume", "inspect", data.Get("namedBusy")) - helpers.Fail("volume", "inspect", data.Get("namedDangling")) - }, - ), - } - }, + }, + { + Description: "prune all", + NoParallel: true, + Setup: setup, + Cleanup: cleanup, + Command: test.Command("volume", "prune", "-f", "--all"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain(data.Get("anonIDBusy")), + test.Contains(data.Get("anonIDDangling")), + test.DoesNotContain(data.Get("namedBusy")), + test.Contains(data.Get("namedDangling")), + func(stdout string, info string, t *testing.T) { + helpers.Ensure("volume", "inspect", data.Get("anonIDBusy")) + helpers.Fail("volume", "inspect", data.Get("anonIDDangling")) + helpers.Ensure("volume", "inspect", data.Get("namedBusy")) + helpers.Fail("volume", "inspect", data.Get("namedDangling")) + }, + ), + } }, }, } diff --git a/cmd/nerdctl/volume/volume_remove_linux_test.go b/cmd/nerdctl/volume/volume_remove_linux_test.go index ba775614766..50bd936d6da 100644 --- a/cmd/nerdctl/volume/volume_remove_linux_test.go +++ b/cmd/nerdctl/volume/volume_remove_linux_test.go @@ -35,22 +35,22 @@ import ( // Behavior in such cases is largely unspecified, as there is no easy way to compare with Docker. // Anyhow, borked filesystem conditions is not something we should be expected to deal with in a smart way. func TestVolumeRemove(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - testGroup := &test.Group{ + testCase.SubTests = []*test.Case{ { Description: "arg missing should fail", - Command: test.RunCommand("volume", "rm"), + Command: test.Command("volume", "rm"), Expected: test.Expects(1, []error{errors.New("requires at least 1 arg")}, nil), }, { Description: "invalid identifier should fail", - Command: test.RunCommand("volume", "rm", "∞"), + Command: test.Command("volume", "rm", "∞"), Expected: test.Expects(1, []error{errdefs.ErrInvalidArgument}, nil), }, { Description: "non existent volume should fail", - Command: test.RunCommand("volume", "rm", "doesnotexist"), + Command: test.Command("volume", "rm", "doesnotexist"), Expected: test.Expects(1, []error{errdefs.ErrNotFound}, nil), }, { @@ -62,22 +62,22 @@ func TestVolumeRemove(t *testing.T) { "--name", data.Identifier(), testutil.CommonImage) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "rm", data.Identifier()) - }, - - Expected: test.Expects(1, []error{errdefs.ErrFailedPrecondition}, nil), - Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) helpers.Anyhow("volume", "rm", "-f", data.Identifier()) }, + + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "rm", data.Identifier()) + }, + + Expected: test.Expects(1, []error{errdefs.ErrFailedPrecondition}, nil), }, { Description: "busy anonymous volume should fail", Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()), "--name", data.Identifier(), testutil.CommonImage) + helpers.Ensure("run", "-v", "/volume", "--name", data.Identifier(), testutil.CommonImage) // Inspect the container and find the anonymous volume id inspect := nerdtest.InspectContainer(helpers, data.Identifier()) var anonName string @@ -87,20 +87,21 @@ func TestVolumeRemove(t *testing.T) { break } } - assert.Assert(t, anonName != "", "Failed to find anonymous volume id") + assert.Assert(t, anonName != "", "Failed to find anonymous volume id", inspect) data.Set("anonName", anonName) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("volume", "rm", "-f", data.Get("anonName")) + }, + + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { // Try to remove that anon volume return helpers.Command("volume", "rm", data.Get("anonName")) }, Expected: test.Expects(1, []error{errdefs.ErrFailedPrecondition}, nil), - - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) - }, }, { Description: "freed volume should succeed", @@ -111,7 +112,12 @@ func TestVolumeRemove(t *testing.T) { helpers.Ensure("rm", "-f", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("volume", "rm", "-f", data.Identifier()) + }, + + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("volume", "rm", data.Identifier()) }, @@ -120,19 +126,10 @@ func TestVolumeRemove(t *testing.T) { Output: test.Equals(data.Identifier() + "\n"), } }, - - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("volume", "rm", "-f", data.Identifier()) - }, }, { Description: "dangling volume should succeed", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "rm", data.Identifier()) - }, - Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("volume", "create", data.Identifier()) }, @@ -141,6 +138,10 @@ func TestVolumeRemove(t *testing.T) { helpers.Anyhow("volume", "rm", "-f", data.Identifier()) }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "rm", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: test.Equals(data.Identifier() + "\n"), @@ -150,20 +151,20 @@ func TestVolumeRemove(t *testing.T) { { Description: "part success multi-remove", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "rm", "invalid∞", "nonexistent", data.Identifier()+"-busy", data.Identifier()) - }, - Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("volume", "create", data.Identifier()) - helpers.Ensure("volume", "create", data.Identifier()+"-busy") - helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()+"-busy"), "--name", data.Identifier(), testutil.CommonImage) + helpers.Ensure("volume", "create", data.Identifier("busy")) + helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier("busy")), "--name", data.Identifier(), testutil.CommonImage) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) helpers.Anyhow("volume", "rm", "-f", data.Identifier()) - helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-busy") + helpers.Anyhow("volume", "rm", "-f", data.Identifier("busy")) + }, + + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "rm", "invalid∞", "nonexistent", data.Identifier("busy"), data.Identifier()) }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { @@ -181,22 +182,22 @@ func TestVolumeRemove(t *testing.T) { { Description: "success multi-remove", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "rm", data.Identifier()+"-1", data.Identifier()+"-2") - }, - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("volume", "create", data.Identifier()+"-1") - helpers.Ensure("volume", "create", data.Identifier()+"-2") + helpers.Ensure("volume", "create", data.Identifier("1")) + helpers.Ensure("volume", "create", data.Identifier("2")) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-1", data.Identifier()+"-2") + helpers.Anyhow("volume", "rm", "-f", data.Identifier("1"), data.Identifier("2")) + }, + + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "rm", data.Identifier("1"), data.Identifier("2")) }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ - Output: test.Equals(data.Identifier() + "-1\n" + data.Identifier() + "-2" + "\n"), + Output: test.Equals(data.Identifier("1") + "\n" + data.Identifier("2") + "\n"), } }, }, @@ -204,17 +205,17 @@ func TestVolumeRemove(t *testing.T) { Description: "failing multi-remove", Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("volume", "create", data.Identifier()+"-busy") - helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()+"-busy"), "--name", data.Identifier(), testutil.CommonImage) + helpers.Ensure("volume", "create", data.Identifier("busy")) + helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier("busy")), "--name", data.Identifier(), testutil.CommonImage) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("volume", "rm", "-f", data.Identifier()+"-busy") + helpers.Anyhow("volume", "rm", "-f", data.Identifier("busy")) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("volume", "rm", "invalid∞", "nonexistent", data.Identifier()+"-busy") + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("volume", "rm", "invalid∞", "nonexistent", data.Identifier("busy")) }, Expected: test.Expects(1, []error{ @@ -225,5 +226,5 @@ func TestVolumeRemove(t *testing.T) { }, } - testGroup.Run(t) + testCase.Run(t) } From 0fafd1af284120f048c4942fecac26505d4667dd Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 7 Oct 2024 00:16:29 -0700 Subject: [PATCH 0813/1066] ./cmd/nerdctl/system touchups With the updated tooling, a few changes are required to existing (migrated) tests. Specifically: - removal of test.Group - renaming of test.RunCommand (test.Command) and test.Command (test.TestableCommand) Signed-off-by: apostasie --- .../system/system_events_linux_test.go | 8 +- cmd/nerdctl/system/system_info_test.go | 18 +-- cmd/nerdctl/system/system_prune_linux_test.go | 124 ++++++++---------- 3 files changed, 67 insertions(+), 83 deletions(-) diff --git a/cmd/nerdctl/system/system_events_linux_test.go b/cmd/nerdctl/system/system_events_linux_test.go index c12d0161576..3dd5d30c40d 100644 --- a/cmd/nerdctl/system/system_events_linux_test.go +++ b/cmd/nerdctl/system/system_events_linux_test.go @@ -25,7 +25,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func testEventFilterExecutor(data test.Data, helpers test.Helpers) test.Command { +func testEventFilterExecutor(data test.Data, helpers test.Helpers) test.TestableCommand { cmd := helpers.Command("events", "--filter", data.Get("filter"), "--format", "json") cmd.Background(1 * time.Second) helpers.Ensure("run", "--rm", testutil.CommonImage) @@ -33,9 +33,9 @@ func testEventFilterExecutor(data test.Data, helpers test.Helpers) test.Command } func TestEventFilters(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - testGroup := &test.Group{ + testCase.SubTests = []*test.Case{ { Description: "CapitalizedFilter", Require: test.Not(nerdtest.Docker), @@ -96,5 +96,5 @@ func TestEventFilters(t *testing.T) { }, } - testGroup.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/system/system_info_test.go b/cmd/nerdctl/system/system_info_test.go index 3c8f5c252da..dc4af4b0381 100644 --- a/cmd/nerdctl/system/system_info_test.go +++ b/cmd/nerdctl/system/system_info_test.go @@ -38,24 +38,24 @@ func testInfoComparator(stdout string, info string, t *testing.T) { } func TestInfo(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - testGroup := &test.Group{ + testCase.SubTests = []*test.Case{ { Description: "info", - Command: test.RunCommand("info", "--format", "{{json .}}"), + Command: test.Command("info", "--format", "{{json .}}"), Expected: test.Expects(0, nil, testInfoComparator), }, { Description: "info convenience form", - Command: test.RunCommand("info", "--format", "json"), + Command: test.Command("info", "--format", "json"), Expected: test.Expects(0, nil, testInfoComparator), }, { Description: "info with namespace", Require: test.Not(nerdtest.Docker), - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command().Clear().WithBinary("nerdctl").WithArgs("info") + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("nerdctl", "info") }, Expected: test.Expects(0, nil, test.Contains("Namespace: default")), }, @@ -65,12 +65,12 @@ func TestInfo(t *testing.T) { "CONTAINERD_NAMESPACE": "test", }, Require: test.Not(nerdtest.Docker), - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command().Clear().WithBinary("nerdctl").WithArgs("info") + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("nerdctl", "info") }, Expected: test.Expects(0, nil, test.Contains("Namespace: test")), }, } - testGroup.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/system/system_prune_linux_test.go b/cmd/nerdctl/system/system_prune_linux_test.go index dbf78726fcd..1d47b26690c 100644 --- a/cmd/nerdctl/system/system_prune_linux_test.go +++ b/cmd/nerdctl/system/system_prune_linux_test.go @@ -23,86 +23,70 @@ import ( "gotest.tools/v3/assert" - "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestSystemPrune(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - testCase := &test.Case{ - Description: "TestSystemPrune", - NoParallel: true, - SubTests: []*test.Case{ - { - Description: "volume prune all success", - // Private because of prune evidently - Require: nerdtest.Private, - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("volume", "create", data.Identifier()) - anonIdentifier := helpers.Capture("volume", "create") - helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()), - "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) + testCase.NoParallel = true - data.Set("anonIdentifier", anonIdentifier) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("network", "rm", data.Identifier()) - helpers.Anyhow("volume", "rm", data.Identifier()) - helpers.Anyhow("volume", "rm", data.Get("anonIdentifier")) - helpers.Anyhow("rm", "-f", data.Identifier()) - }, - Command: test.RunCommand("system", "prune", "-f", "--volumes", "--all"), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - ExitCode: 0, - Output: func(stdout string, info string, t *testing.T) { - volumes := helpers.Capture("volume", "ls") - networks := helpers.Capture("network", "ls") - images := helpers.Capture("images") - containers := helpers.Capture("ps", "-a") - assert.Assert(t, strings.Contains(volumes, data.Identifier()), volumes) - assert.Assert(t, !strings.Contains(volumes, data.Get("anonIdentifier")), volumes) - assert.Assert(t, !strings.Contains(containers, data.Identifier()), containers) - assert.Assert(t, !strings.Contains(networks, data.Identifier()), networks) - assert.Assert(t, !strings.Contains(images, testutil.CommonImage), images) - }, - } - }, - }, - { - Description: "buildkit", - // FIXME: using a dedicated namespace does not work with rootful (because of buildkitd) - NoParallel: true, - // buildkitd is not available with docker - Require: test.Require(nerdtest.Build, test.Not(nerdtest.Docker)), - // FIXME: this test will happily say "green" even if the command actually fails to do its duty - // if there is nothing in the build cache. - // Ensure with setup here that we DO build something first - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("system", "prune", "-f", "--volumes", "--all") - }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - buildctlBinary, err := buildkitutil.BuildctlBinary() - if err != nil { - t.Fatal(err) - } - - host, err := buildkitutil.GetBuildkitHost(testutil.Namespace) - if err != nil { - t.Fatal(err) - } + testCase.SubTests = []*test.Case{ + { + Description: "volume prune all success", + // Private because of prune evidently + Require: nerdtest.Private, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("volume", "create", data.Identifier()) + anonIdentifier := helpers.Capture("volume", "create") + helpers.Ensure("run", "-v", fmt.Sprintf("%s:/volume", data.Identifier()), + "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) - buildctlArgs := buildkitutil.BuildctlBaseArgs(host) - buildctlArgs = append(buildctlArgs, "du") - - return helpers.CustomCommand(buildctlBinary, buildctlArgs...) - }, - Expected: test.Expects(0, nil, test.Contains("Total:\t\t0B")), + data.Set("anonIdentifier", anonIdentifier) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + helpers.Anyhow("volume", "rm", data.Identifier()) + helpers.Anyhow("volume", "rm", data.Get("anonIdentifier")) + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("system", "prune", "-f", "--volumes", "--all"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + volumes := helpers.Capture("volume", "ls") + networks := helpers.Capture("network", "ls") + images := helpers.Capture("images") + containers := helpers.Capture("ps", "-a") + assert.Assert(t, strings.Contains(volumes, data.Identifier()), volumes) + assert.Assert(t, !strings.Contains(volumes, data.Get("anonIdentifier")), volumes) + assert.Assert(t, !strings.Contains(containers, data.Identifier()), containers) + assert.Assert(t, !strings.Contains(networks, data.Identifier()), networks) + assert.Assert(t, !strings.Contains(images, testutil.CommonImage), images) + }, + } + }, + }, + { + Description: "buildkit", + // FIXME: using a dedicated namespace does not work with rootful (because of buildkitd) + NoParallel: true, + // buildkitd is not available with docker + Require: test.Require(nerdtest.Build, test.Not(nerdtest.Docker)), + // FIXME: this test will happily say "green" even if the command actually fails to do its duty + // if there is nothing in the build cache. + // Ensure with setup here that we DO build something first + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("system", "prune", "-f", "--volumes", "--all") + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return nerdtest.BuildCtlCommand(helpers, "du") }, + Expected: test.Expects(0, nil, test.Contains("Total:\t\t0B")), }, } From 91f4eb4ad4b892e0e39f5b9b19302681c1978160 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 7 Oct 2024 00:18:15 -0700 Subject: [PATCH 0814/1066] ./cmd/nerdctl/network touchups With the updated tooling, a few changes are required to existing (migrated) tests. Specifically: - removal of test.Group - renaming of test.RunCommand (test.Command) and test.Command (test.TestableCommand) - some requirements are now functions linking to github issues Signed-off-by: apostasie --- .../network/network_create_linux_test.go | 32 +-- cmd/nerdctl/network/network_inspect_test.go | 54 ++--- .../network/network_list_linux_test.go | 112 +++++----- .../network/network_prune_linux_test.go | 77 ++++--- .../network/network_remove_linux_test.go | 191 +++++++++--------- 5 files changed, 237 insertions(+), 229 deletions(-) diff --git a/cmd/nerdctl/network/network_create_linux_test.go b/cmd/nerdctl/network/network_create_linux_test.go index ae590d94836..2d1274f19ea 100644 --- a/cmd/nerdctl/network/network_create_linux_test.go +++ b/cmd/nerdctl/network/network_create_linux_test.go @@ -30,25 +30,27 @@ import ( ) func TestNetworkCreate(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - testGroup := &test.Group{ + testCase.SubTests = []*test.Case{ { - Description: "Network create", + Description: "vanilla", + // #3491 and #3508 may have helped - commenting this out for now + // Require: nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3086"), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("network", "create", data.Identifier()) netw := nerdtest.InspectNetwork(helpers, data.Identifier()) assert.Equal(t, len(netw.IPAM.Config), 1) data.Set("subnet", netw.IPAM.Config[0].Subnet) - helpers.Ensure("network", "create", data.Identifier()+"-1") + helpers.Ensure("network", "create", data.Identifier("1")) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("network", "rm", data.Identifier()) - helpers.Anyhow("network", "rm", data.Identifier()+"-1") + helpers.Anyhow("network", "rm", data.Identifier("1")) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - data.Set("container2", helpers.Capture("run", "--rm", "--net", data.Identifier()+"-1", testutil.AlpineImage, "ip", "route")) + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + data.Set("container2", helpers.Capture("run", "--rm", "--net", data.Identifier("1"), testutil.AlpineImage, "ip", "route")) return helpers.Command("run", "--rm", "--net", data.Identifier(), testutil.AlpineImage, "ip", "route") }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { @@ -63,21 +65,25 @@ func TestNetworkCreate(t *testing.T) { }, }, { - Description: "Network create with MTU", + Description: "with MTU", + // #3491 and #3508 may have helped - commenting this out for now + // Require: nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3086"), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("network", "create", data.Identifier(), "--driver", "bridge", "--opt", "com.docker.network.driver.mtu=9216") }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("network", "rm", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("run", "--rm", "--net", data.Identifier(), testutil.AlpineImage, "ifconfig", "eth0") }, Expected: test.Expects(0, nil, test.Contains("MTU:9216")), }, { - Description: "Network create with ipv6", - Require: nerdtest.OnlyIPv6, + Description: "with ipv6", + // #3491 and #3508 may have helped - commenting this out for now + // Require: nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3086"), + Require: nerdtest.OnlyIPv6, Setup: func(data test.Data, helpers test.Helpers) { subnetStr := "2001:db8:8::/64" data.Set("subnetStr", subnetStr) @@ -89,7 +95,7 @@ func TestNetworkCreate(t *testing.T) { Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("network", "rm", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("run", "--rm", "--net", data.Identifier(), testutil.CommonImage, "ip", "addr", "show", "dev", "eth0") }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { @@ -105,5 +111,5 @@ func TestNetworkCreate(t *testing.T) { }, } - testGroup.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/network/network_inspect_test.go b/cmd/nerdctl/network/network_inspect_test.go index 5dfe9b88612..64d5631e2bf 100644 --- a/cmd/nerdctl/network/network_inspect_test.go +++ b/cmd/nerdctl/network/network_inspect_test.go @@ -30,7 +30,7 @@ import ( ) func TestNetworkInspect(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() const ( testSubnet = "10.24.24.0/24" @@ -38,23 +38,23 @@ func TestNetworkInspect(t *testing.T) { testIPRange = "10.24.24.0/25" ) - testGroup := &test.Group{ + testCase.SubTests = []*test.Case{ { Description: "non existent network", - Command: test.RunCommand("network", "inspect", "nonexistent"), + Command: test.Command("network", "inspect", "nonexistent"), // FIXME: where is this error even comin from? Expected: test.Expects(1, []error{errors.New("no network found matching")}, nil), }, { Description: "invalid name network", - Command: test.RunCommand("network", "inspect", "∞"), + Command: test.Command("network", "inspect", "∞"), // FIXME: this is not even a valid identifier Expected: test.Expects(1, []error{errors.New("no network found matching")}, nil), }, { Description: "none", - Require: nerdtest.NerdctlNeedsFixing, - Command: test.RunCommand("network", "inspect", "none"), + Require: nerdtest.NerdctlNeedsFixing("no issue opened"), + Command: test.Command("network", "inspect", "none"), Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { var dc []dockercompat.Network err := json.Unmarshal([]byte(stdout), &dc) @@ -65,8 +65,8 @@ func TestNetworkInspect(t *testing.T) { }, { Description: "host", - Require: nerdtest.NerdctlNeedsFixing, - Command: test.RunCommand("network", "inspect", "host"), + Require: nerdtest.NerdctlNeedsFixing("no issue opened"), + Command: test.Command("network", "inspect", "host"), Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { var dc []dockercompat.Network err := json.Unmarshal([]byte(stdout), &dc) @@ -78,7 +78,7 @@ func TestNetworkInspect(t *testing.T) { { Description: "bridge", Require: test.Not(test.Windows), - Command: test.RunCommand("network", "inspect", "bridge"), + Command: test.Command("network", "inspect", "bridge"), Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { var dc []dockercompat.Network err := json.Unmarshal([]byte(stdout), &dc) @@ -95,7 +95,7 @@ func TestNetworkInspect(t *testing.T) { Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("network", "remove", "custom") }, - Command: test.RunCommand("network", "inspect", "custom"), + Command: test.Command("network", "inspect", "custom"), Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { var dc []dockercompat.Network err := json.Unmarshal([]byte(stdout), &dc) @@ -107,7 +107,7 @@ func TestNetworkInspect(t *testing.T) { { Description: "match exact id", Require: test.Not(test.Windows), - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) return helpers.Command("network", "inspect", id) }, @@ -122,7 +122,7 @@ func TestNetworkInspect(t *testing.T) { { Description: "match part of id", Require: test.Not(test.Windows), - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) return helpers.Command("network", "inspect", id[0:25]) }, @@ -146,7 +146,7 @@ func TestNetworkInspect(t *testing.T) { id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) helpers.Anyhow("network", "remove", id[0:12]) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("network", "inspect", data.Get("netname")) }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { @@ -162,7 +162,7 @@ func TestNetworkInspect(t *testing.T) { }, }, { - Description: "Test network inspect", + Description: "basic", // IPAMConfig is not implemented on Windows yet Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { @@ -172,7 +172,7 @@ func TestNetworkInspect(t *testing.T) { Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("network", "rm", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("network", "inspect", data.Identifier()) }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { @@ -197,13 +197,13 @@ func TestNetworkInspect(t *testing.T) { }, }, { - Description: "Test network with namespace", + Description: "with namespace", Require: test.Not(nerdtest.Docker), Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("network", "rm", data.Identifier()) helpers.Anyhow("namespace", "remove", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("network", "create", data.Identifier()) }, @@ -211,23 +211,31 @@ func TestNetworkInspect(t *testing.T) { return &test.Expected{ ExitCode: 0, Output: func(stdout string, info string, t *testing.T) { - cmd := helpers.CustomCommand("nerdctl", "--namespace", data.Identifier()) + cmd := helpers.Custom("nerdctl", "--namespace", data.Identifier()) - cmd.Clone().WithArgs("network", "inspect", data.Identifier()).Run(&test.Expected{ + com := cmd.Clone() + com.WithArgs("network", "inspect", data.Identifier()) + com.Run(&test.Expected{ ExitCode: 1, Errors: []error{errors.New("no network found")}, }) - cmd.Clone().WithArgs("network", "remove", data.Identifier()).Run(&test.Expected{ + com = cmd.Clone() + com.WithArgs("network", "remove", data.Identifier()) + com.Run(&test.Expected{ ExitCode: 1, Errors: []error{errors.New("no network found")}, }) - cmd.Clone().WithArgs("network", "ls").Run(&test.Expected{ + com = cmd.Clone() + com.WithArgs("network", "ls") + com.Run(&test.Expected{ Output: test.DoesNotContain(data.Identifier()), }) - cmd.Clone().WithArgs("network", "prune", "-f").Run(&test.Expected{ + com = cmd.Clone() + com.WithArgs("network", "prune", "-f") + com.Run(&test.Expected{ Output: test.DoesNotContain(data.Identifier()), }) }, @@ -236,5 +244,5 @@ func TestNetworkInspect(t *testing.T) { }, } - testGroup.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/network/network_list_linux_test.go b/cmd/nerdctl/network/network_list_linux_test.go index a9d2f0124eb..af8c8d1ca0b 100644 --- a/cmd/nerdctl/network/network_list_linux_test.go +++ b/cmd/nerdctl/network/network_list_linux_test.go @@ -27,64 +27,68 @@ import ( ) func TestNetworkLsFilter(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - testCase := &test.Case{ - Description: "Test network list", - Setup: func(data test.Data, helpers test.Helpers) { - data.Set("identifier", data.Identifier()) - data.Set("label", data.Identifier()+"=label-1") - data.Set("netID1", helpers.Capture("network", "create", "--label="+data.Get("label"), data.Identifier()+"-1")) - data.Set("netID2", helpers.Capture("network", "create", data.Identifier()+"-2")) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("network", "rm", data.Identifier()+"-1") - helpers.Anyhow("network", "rm", data.Identifier()+"-2") - }, - SubTests: []*test.Case{ - { - Description: "filter label", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("network", "ls", "--quiet", "--filter", "label="+data.Get("label")) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 1, info) - netNames := map[string]struct{}{ - data.Get("netID1")[:12]: {}, - } + // #3491 and #3508 may have helped - commenting this out for now + // testCase.Require = nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3086"), + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + data.Set("identifier", data.Identifier()) + data.Set("label", "mylabel=label-1") + data.Set("net1", data.Identifier("1")) + data.Set("net2", data.Identifier("2")) + data.Set("netID1", helpers.Capture("network", "create", "--label="+data.Get("label"), data.Get("net1"))) + data.Set("netID2", helpers.Capture("network", "create", data.Get("net2"))) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier("1")) + helpers.Anyhow("network", "rm", data.Identifier("2")) + } + + testCase.SubTests = []*test.Case{ + { + Description: "filter label", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("network", "ls", "--quiet", "--filter", "label="+data.Get("label")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 1, info) + netNames := map[string]struct{}{ + data.Get("netID1")[:12]: {}, + } - for _, name := range lines { - _, ok := netNames[name] - assert.Assert(t, ok, info) - } - }, - } - }, + for _, name := range lines { + _, ok := netNames[name] + assert.Assert(t, ok, info) + } + }, + } + }, + }, + { + Description: "filter name", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("network", "ls", "--quiet", "--filter", "name="+data.Get("net2")) }, - { - Description: "filter name", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("network", "ls", "--quiet", "--filter", "name="+data.Get("identifier")+"-2") - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var lines = strings.Split(strings.TrimSpace(stdout), "\n") - assert.Assert(t, len(lines) >= 1, info) - netNames := map[string]struct{}{ - data.Get("netID2")[:12]: {}, - } + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var lines = strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 1, info) + netNames := map[string]struct{}{ + data.Get("netID2")[:12]: {}, + } - for _, name := range lines { - _, ok := netNames[name] - assert.Assert(t, ok, info) - } - }, - } - }, + for _, name := range lines { + _, ok := netNames[name] + assert.Assert(t, ok, info) + } + }, + } }, }, } diff --git a/cmd/nerdctl/network/network_prune_linux_test.go b/cmd/nerdctl/network/network_prune_linux_test.go index 333b3aefd95..62f6417c736 100644 --- a/cmd/nerdctl/network/network_prune_linux_test.go +++ b/cmd/nerdctl/network/network_prune_linux_test.go @@ -25,49 +25,46 @@ import ( ) func TestNetworkPrune(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - testCase := &test.Case{ - Description: "TestNetworkPrune", - Require: nerdtest.Private, + testCase.Require = nerdtest.Private - SubTests: []*test.Case{ - { - Description: "Prune does not collect started container network", - NoParallel: true, - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("network", "rm", data.Identifier()) - }, - Command: test.RunCommand("network", "prune", "-f"), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.DoesNotContain(data.Identifier()), - } - }, + testCase.SubTests = []*test.Case{ + { + Description: "Prune does not collect started container network", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) }, - { - Description: "Prune does collect stopped container network", - NoParallel: true, - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) - helpers.Ensure("stop", data.Identifier()) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("network", "rm", data.Identifier()) - }, - Command: test.RunCommand("network", "prune", "-f"), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.Contains(data.Identifier()), - } - }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Command: test.Command("network", "prune", "-f"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.DoesNotContain(data.Identifier()), + } + }, + }, + { + Description: "Prune does collect stopped container network", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) + helpers.Ensure("stop", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Command: test.Command("network", "prune", "-f"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Identifier()), + } }, }, } diff --git a/cmd/nerdctl/network/network_remove_linux_test.go b/cmd/nerdctl/network/network_remove_linux_test.go index 9e5bbaf200a..b8804772f4b 100644 --- a/cmd/nerdctl/network/network_remove_linux_test.go +++ b/cmd/nerdctl/network/network_remove_linux_test.go @@ -29,109 +29,102 @@ import ( ) func TestNetworkRemove(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - testCase := &test.Case{ - Description: "TestNetworkRemove", - Require: test.Not(nerdtest.Rootless), - SubTests: []*test.Case{ - { - Description: "Simple network remove", - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - data.Set("netID", nerdtest.InspectNetwork(helpers, data.Identifier()).ID) - helpers.Ensure("run", "--rm", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) - // Verity the network is here - _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) - assert.NilError(t, err, "failed to find network br-"+data.Get("netID")[:12], "%v") - }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("network", "rm", data.Identifier()) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("network", "rm", data.Identifier()) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - ExitCode: 0, - Output: func(stdout string, info string, t *testing.T) { - _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) - assert.Error(t, err, "Link not found", info) - }, - } - }, + testCase.Require = nerdtest.RootFul + + testCase.SubTests = []*test.Case{ + { + Description: "Simple network remove", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + data.Set("netID", nerdtest.InspectNetwork(helpers, data.Identifier()).ID) + helpers.Ensure("run", "--rm", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) + // Verity the network is here + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.NilError(t, err, "failed to find network br-"+data.Get("netID")[:12], "%v") + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("network", "rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.Error(t, err, "Link not found", info) + }, + } + }, + }, + { + Description: "Network remove when linked to container", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("network", "rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Expected: test.Expects(1, []error{errors.New("is in use")}, nil), + }, + { + Description: "Network remove by id", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + data.Set("netID", nerdtest.InspectNetwork(helpers, data.Identifier()).ID) + helpers.Ensure("run", "--rm", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) + // Verity the network is here + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.NilError(t, err, "failed to find network br-"+data.Get("netID")[:12], "%v") + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("network", "rm", data.Get("netID")) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.Error(t, err, "Link not found", info) + }, + } + }, + }, + { + Description: "Network remove by short id", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier()) + data.Set("netID", nerdtest.InspectNetwork(helpers, data.Identifier()).ID) + helpers.Ensure("run", "--rm", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) + // Verity the network is here + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.NilError(t, err, "failed to find network br-"+data.Get("netID")[:12], "%v") }, - { - Description: "Network remove when linked to container", - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") - }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("network", "rm", data.Identifier()) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("network", "rm", data.Identifier()) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - ExitCode: 1, - Errors: []error{errors.New("is in use")}, - } - }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("network", "rm", data.Get("netID")[:12]) }, - { - Description: "Network remove by id", - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - data.Set("netID", nerdtest.InspectNetwork(helpers, data.Identifier()).ID) - helpers.Ensure("run", "--rm", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) - // Verity the network is here - _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) - assert.NilError(t, err, "failed to find network br-"+data.Get("netID")[:12], "%v") - }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("network", "rm", data.Get("netID")) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("network", "rm", data.Identifier()) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - ExitCode: 0, - Output: func(stdout string, info string, t *testing.T) { - _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) - assert.Error(t, err, "Link not found", info) - }, - } - }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) }, - { - Description: "Network remove by short id", - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - data.Set("netID", nerdtest.InspectNetwork(helpers, data.Identifier()).ID) - helpers.Ensure("run", "--rm", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) - // Verity the network is here - _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) - assert.NilError(t, err, "failed to find network br-"+data.Get("netID")[:12], "%v") - }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command("network", "rm", data.Get("netID")[:12]) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("network", "rm", data.Identifier()) - }, - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - ExitCode: 0, - Output: func(stdout string, info string, t *testing.T) { - _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) - assert.Error(t, err, "Link not found", info) - }, - } - }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) + assert.Error(t, err, "Link not found", info) + }, + } }, }, } From 7190bc662b38cca2f2a66eeb33baf8a4aac506d1 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 7 Oct 2024 00:21:08 -0700 Subject: [PATCH 0815/1066] ./cmd/nerdctl/. + issues + completion touchups With the updated tooling, a few changes are required to existing (migrated) tests. Specifically: - removal of test.Group - renaming of test.RunCommand (test.Command) and test.Command (test.TestableCommand) - moved regression test to ./issues, where it belongs - simplified syntax with helpers.Custom Signed-off-by: apostasie --- .../completion/completion_linux_test.go | 59 +++++----- .../container/container_create_linux_test.go | 10 +- cmd/nerdctl/issues/issues_linux_test.go | 35 +----- cmd/nerdctl/{ => issues}/main_linux_test.go | 30 +++-- cmd/nerdctl/main_test.go | 108 +++++++++--------- cmd/nerdctl/main_test_test.go | 74 +++--------- 6 files changed, 124 insertions(+), 192 deletions(-) rename cmd/nerdctl/{ => issues}/main_linux_test.go (75%) diff --git a/cmd/nerdctl/completion/completion_linux_test.go b/cmd/nerdctl/completion/completion_linux_test.go index 234c9a21ebc..81156e15b16 100644 --- a/cmd/nerdctl/completion/completion_linux_test.go +++ b/cmd/nerdctl/completion/completion_linux_test.go @@ -28,8 +28,7 @@ func TestCompletion(t *testing.T) { nerdtest.Setup() testCase := &test.Case{ - Description: "Base completion", - Require: test.Not(nerdtest.Docker), + Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("pull", testutil.AlpineImage) helpers.Ensure("network", "create", data.Identifier()) @@ -43,37 +42,37 @@ func TestCompletion(t *testing.T) { SubTests: []*test.Case{ { Description: "--cgroup-manager", - Command: test.RunCommand("__complete", "--cgroup-manager", ""), + Command: test.Command("__complete", "--cgroup-manager", ""), Expected: test.Expects(0, nil, test.Contains("cgroupfs\n")), }, { Description: "--snapshotter", - Command: test.RunCommand("__complete", "--snapshotter", ""), + Command: test.Command("__complete", "--snapshotter", ""), Expected: test.Expects(0, nil, test.Contains("native\n")), }, { Description: "empty", - Command: test.RunCommand("__complete", ""), + Command: test.Command("__complete", ""), Expected: test.Expects(0, nil, test.Contains("run\t")), }, { Description: "run -", - Command: test.RunCommand("__complete", "run", "-"), + Command: test.Command("__complete", "run", "-"), Expected: test.Expects(0, nil, test.Contains("--network\t")), }, { Description: "run --n", - Command: test.RunCommand("__complete", "run", "--n"), + Command: test.Command("__complete", "run", "--n"), Expected: test.Expects(0, nil, test.Contains("--network\t")), }, { Description: "run --ne", - Command: test.RunCommand("__complete", "run", "--ne"), + Command: test.Command("__complete", "run", "--ne"), Expected: test.Expects(0, nil, test.Contains("--network\t")), }, { Description: "run --net", - Command: test.RunCommand("__complete", "run", "--net", ""), + Command: test.Command("__complete", "run", "--net", ""), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: test.All( @@ -85,7 +84,7 @@ func TestCompletion(t *testing.T) { }, { Description: "run -it --net", - Command: test.RunCommand("__complete", "run", "-it", "--net", ""), + Command: test.Command("__complete", "run", "-it", "--net", ""), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: test.All( @@ -97,7 +96,7 @@ func TestCompletion(t *testing.T) { }, { Description: "run -ti --rm --net", - Command: test.RunCommand("__complete", "run", "-it", "--rm", "--net", ""), + Command: test.Command("__complete", "run", "-it", "--rm", "--net", ""), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: test.All( @@ -109,12 +108,12 @@ func TestCompletion(t *testing.T) { }, { Description: "run --restart", - Command: test.RunCommand("__complete", "run", "--restart", ""), + Command: test.Command("__complete", "run", "--restart", ""), Expected: test.Expects(0, nil, test.Contains("always\n")), }, { Description: "network --rm", - Command: test.RunCommand("__complete", "network", "rm", ""), + Command: test.Command("__complete", "network", "rm", ""), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: test.All( @@ -126,7 +125,7 @@ func TestCompletion(t *testing.T) { }, { Description: "run --cap-add", - Command: test.RunCommand("__complete", "run", "--cap-add", ""), + Command: test.Command("__complete", "run", "--cap-add", ""), Expected: test.Expects(0, nil, test.All( test.Contains("sys_admin\n"), test.DoesNotContain("CAP_SYS_ADMIN\n"), @@ -134,7 +133,7 @@ func TestCompletion(t *testing.T) { }, { Description: "volume inspect", - Command: test.RunCommand("__complete", "volume", "inspect", ""), + Command: test.Command("__complete", "volume", "inspect", ""), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: test.Contains(data.Get("identifier") + "\n"), @@ -143,7 +142,7 @@ func TestCompletion(t *testing.T) { }, { Description: "volume rm", - Command: test.RunCommand("__complete", "volume", "rm", ""), + Command: test.Command("__complete", "volume", "rm", ""), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: test.Contains(data.Get("identifier") + "\n"), @@ -152,52 +151,46 @@ func TestCompletion(t *testing.T) { }, { Description: "no namespace --cgroup-manager", - Command: func(data test.Data, helpers test.Helpers) test.Command { - cmd := helpers.Command() - cmd.Clear() - cmd.WithBinary("nerdctl") - cmd.WithArgs("__complete", "--cgroup-manager", "") - return cmd + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("nerdctl", "__complete", "--cgroup-manager", "") }, Expected: test.Expects(0, nil, test.Contains("cgroupfs\n")), }, { Description: "no namespace empty", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.Command().Clear().WithBinary("nerdctl").WithArgs("__complete", "") + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("nerdctl", "__complete", "") }, Expected: test.Expects(0, nil, test.Contains("run\t")), }, { Description: "namespace space empty", - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { // mind {"--namespace=nerdctl-test"} vs {"--namespace", "nerdctl-test"} - return helpers.Command().Clear().WithBinary("nerdctl"). - WithArgs("__complete", "--namespace", testutil.Namespace, "") + return helpers.Custom("nerdctl", "__complete", "--namespace", string(helpers.Read(nerdtest.Namespace)), "") }, Expected: test.Expects(0, nil, test.Contains("run\t")), }, { Description: "run -i", - Command: test.RunCommand("__complete", "run", "-i", ""), + Command: test.Command("__complete", "run", "-i", ""), Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage)), }, { Description: "run -it", - Command: test.RunCommand("__complete", "run", "-it", ""), + Command: test.Command("__complete", "run", "-it", ""), Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage)), }, { Description: "run -it --rm", - Command: test.RunCommand("__complete", "run", "-it", "--rm", ""), + Command: test.Command("__complete", "run", "-it", "--rm", ""), Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage)), }, { Description: "namespace run -i", - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { // mind {"--namespace=nerdctl-test"} vs {"--namespace", "nerdctl-test"} - return helpers.Command().Clear().WithBinary("nerdctl"). - WithArgs("__complete", "--namespace", testutil.Namespace, "run", "-i", "") + return helpers.Custom("nerdctl", "__complete", "--namespace", string(helpers.Read(nerdtest.Namespace)), "run", "-i", "") }, Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage+"\n")), }, diff --git a/cmd/nerdctl/container/container_create_linux_test.go b/cmd/nerdctl/container/container_create_linux_test.go index ff5e076d241..56b71ce854a 100644 --- a/cmd/nerdctl/container/container_create_linux_test.go +++ b/cmd/nerdctl/container/container_create_linux_test.go @@ -185,9 +185,9 @@ func TestCreateWithTty(t *testing.T) { // TestIssue2993 tests https://github.com/containerd/nerdctl/issues/2993 func TestIssue2993(t *testing.T) { - testutil.DockerIncompatible(t) + testCase := nerdtest.Setup() - nerdtest.Setup() + testCase.Require = test.Not(nerdtest.Docker) const ( containersPathKey = "containersPath" @@ -203,7 +203,7 @@ func TestIssue2993(t *testing.T) { return h } - testCase := &test.Group{ + testCase.SubTests = []*test.Case{ { Description: "Issue #2993 - nerdctl no longer leaks containers and etchosts directories and files when container creation fails.", Setup: func(data test.Data, helpers test.Helpers) { @@ -233,7 +233,7 @@ func TestIssue2993(t *testing.T) { Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "--data-root", data.TempDir(), "-f", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("run", "--data-root", data.TempDir(), "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { @@ -281,7 +281,7 @@ func TestIssue2993(t *testing.T) { Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("--data-root", data.TempDir(), "rm", "-f", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("--data-root", data.TempDir(), "rm", "-f", data.Identifier()) }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { diff --git a/cmd/nerdctl/issues/issues_linux_test.go b/cmd/nerdctl/issues/issues_linux_test.go index 6e8939f8467..0a59126fc13 100644 --- a/cmd/nerdctl/issues/issues_linux_test.go +++ b/cmd/nerdctl/issues/issues_linux_test.go @@ -20,40 +20,20 @@ package issues import ( "fmt" - "os" - "path/filepath" "testing" - "gotest.tools/v3/assert" - - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" "github.com/containerd/nerdctl/v2/pkg/testutil/test" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) -func TestMain(m *testing.M) { - testutil.M(m) -} - func TestIssue3425(t *testing.T) { nerdtest.Setup() var registry *testregistry.RegistryServer - var ipfsPath string - if rootlessutil.IsRootless() { - var err error - ipfsPath, err = rootlessutil.XDGDataHome() - ipfsPath = filepath.Join(ipfsPath, "ipfs") - assert.NilError(t, err) - } else { - ipfsPath = filepath.Join(os.Getenv("HOME"), ".ipfs") - } - testCase := &test.Case{ - Description: "TestIssue3425", Setup: func(data test.Data, helpers test.Helpers) { base := testutil.NewBase(t) registry = testregistry.NewWithNoAuth(base, 0, false) @@ -78,7 +58,7 @@ func TestIssue3425(t *testing.T) { helpers.Anyhow("rm", "-f", data.Identifier()) helpers.Anyhow("rmi", "-f", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("push", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) }, Expected: test.Expects(0, nil, nil), @@ -97,7 +77,7 @@ func TestIssue3425(t *testing.T) { helpers.Anyhow("rm", "-f", data.Identifier()) helpers.Anyhow("rmi", "-f", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("push", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) }, Expected: test.Expects(0, nil, nil), @@ -114,7 +94,7 @@ func TestIssue3425(t *testing.T) { Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("save", testutil.CommonImage) }, Expected: test.Expects(0, nil, nil), @@ -136,7 +116,7 @@ func TestIssue3425(t *testing.T) { helpers.Anyhow("rm", "-f", data.Identifier()) helpers.Anyhow("rmi", "-f", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("image", "convert", "--oci", "--estargz", testutil.CommonImage, data.Identifier()) }, Expected: test.Expects(0, nil, nil), @@ -145,13 +125,10 @@ func TestIssue3425(t *testing.T) { Description: "with ipfs", Require: test.Require( nerdtest.Private, + nerdtest.IPFS, test.Not(test.Windows), test.Not(nerdtest.Docker), - test.Binary("ipfs"), ), - Env: map[string]string{ - "IPFS_PATH": ipfsPath, - }, Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("image", "pull", testutil.CommonImage) helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage) @@ -162,7 +139,7 @@ func TestIssue3425(t *testing.T) { helpers.Anyhow("rm", "-f", data.Identifier()) helpers.Anyhow("rmi", "-f", data.Identifier()) }, - Command: func(data test.Data, helpers test.Helpers) test.Command { + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("image", "push", "ipfs://"+testutil.CommonImage) }, Expected: test.Expects(0, nil, nil), diff --git a/cmd/nerdctl/main_linux_test.go b/cmd/nerdctl/issues/main_linux_test.go similarity index 75% rename from cmd/nerdctl/main_linux_test.go rename to cmd/nerdctl/issues/main_linux_test.go index 274604e27b9..64ca72e2da4 100644 --- a/cmd/nerdctl/main_linux_test.go +++ b/cmd/nerdctl/issues/main_linux_test.go @@ -14,7 +14,7 @@ limitations under the License. */ -package main +package issues import ( "testing" @@ -24,19 +24,24 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) +func TestMain(m *testing.M) { + testutil.M(m) +} + // TestIssue108 tests https://github.com/containerd/nerdctl/issues/108 // ("`nerdctl run --net=host -it` fails while `nerdctl run -it --net=host` works") func TestIssue108(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - testGroup := &test.Group{ + testCase.SubTests = []*test.Case{ { Description: "-it --net=host", Require: test.Binary("unbuffer"), - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers. - Command("run", "-it", "--rm", "--net=host", testutil.AlpineImage, "echo", "this was always working"). - WithWrapper("unbuffer") + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers. + Command("run", "-it", "--rm", "--net=host", testutil.AlpineImage, "echo", "this was always working") + cmd.WithWrapper("unbuffer") + return cmd }, // Note: unbuffer will merge stdout and stderr, preventing exact match here Expected: test.Expects(0, nil, test.Contains("this was always working")), @@ -44,15 +49,16 @@ func TestIssue108(t *testing.T) { { Description: "--net=host -it", Require: test.Binary("unbuffer"), - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers. - Command("run", "--rm", "--net=host", "-it", testutil.AlpineImage, "echo", "this was not working due to issue #108"). - WithWrapper("unbuffer") + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers. + Command("run", "--rm", "--net=host", "-it", testutil.AlpineImage, "echo", "this was not working due to issue #108") + cmd.WithWrapper("unbuffer") + return cmd }, // Note: unbuffer will merge stdout and stderr, preventing exact match here Expected: test.Expects(0, nil, test.Contains("this was not working due to issue #108")), }, } - testGroup.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/main_test.go b/cmd/nerdctl/main_test.go index c1e3caf94fd..e2ca845e490 100644 --- a/cmd/nerdctl/main_test.go +++ b/cmd/nerdctl/main_test.go @@ -33,100 +33,98 @@ func TestMain(m *testing.M) { // TestUnknownCommand tests https://github.com/containerd/nerdctl/issues/487 func TestUnknownCommand(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() var unknownSubCommand = errors.New("unknown subcommand") - testGroup := &test.Group{ + testCase.SubTests = []*test.Case{ { Description: "non-existent-command", - Command: test.RunCommand("non-existent-command"), + Command: test.Command("non-existent-command"), Expected: test.Expects(1, []error{unknownSubCommand}, nil), }, { Description: "non-existent-command info", - Command: test.RunCommand("non-existent-command", "info"), + Command: test.Command("non-existent-command", "info"), Expected: test.Expects(1, []error{unknownSubCommand}, nil), }, { Description: "system non-existent-command", - Command: test.RunCommand("system", "non-existent-command"), + Command: test.Command("system", "non-existent-command"), Expected: test.Expects(1, []error{unknownSubCommand}, nil), }, { Description: "system non-existent-command info", - Command: test.RunCommand("system", "non-existent-command", "info"), + Command: test.Command("system", "non-existent-command", "info"), Expected: test.Expects(1, []error{unknownSubCommand}, nil), }, { Description: "system", - Command: test.RunCommand("system"), + Command: test.Command("system"), Expected: test.Expects(0, nil, nil), }, { Description: "system info", - Command: test.RunCommand("system", "info"), + Command: test.Command("system", "info"), Expected: test.Expects(0, nil, test.Contains("Kernel Version:")), }, { Description: "info", - Command: test.RunCommand("info"), + Command: test.Command("info"), Expected: test.Expects(0, nil, test.Contains("Kernel Version:")), }, } - testGroup.Run(t) + testCase.Run(t) } // TestNerdctlConfig validates the configuration precedence [CLI, Env, TOML, Default] and broken config rejection func TestNerdctlConfig(t *testing.T) { - nerdtest.Setup() - - tc := &test.Case{ - Description: "Nerdctl configuration", - // Docker does not support nerdctl.toml obviously - Require: test.Not(nerdtest.Docker), - SubTests: []*test.Case{ - { - Description: "Default", - Command: test.RunCommand("info", "-f", "{{.Driver}}"), - Expected: test.Expects(0, nil, test.Equals(defaults.DefaultSnapshotter+"\n")), - }, - { - Description: "TOML > Default", - Command: test.RunCommand("info", "-f", "{{.Driver}}"), - Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-toml\n")), - Data: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), - }, - { - Description: "Cli > TOML > Default", - Command: test.RunCommand("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli"), - Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-cli\n")), - Data: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), - }, - { - Description: "Env > TOML > Default", - Command: test.RunCommand("info", "-f", "{{.Driver}}"), - Env: map[string]string{"CONTAINERD_SNAPSHOTTER": "dummy-snapshotter-via-env"}, - Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-env\n")), - Data: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), - }, - { - Description: "Cli > Env > TOML > Default", - Command: test.RunCommand("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli"), - Env: map[string]string{"CONTAINERD_SNAPSHOTTER": "dummy-snapshotter-via-env"}, - Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-cli\n")), - Data: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), - }, - { - Description: "Broken config", - Command: test.RunCommand("info"), - Expected: test.Expects(1, []error{errors.New("failed to load nerdctl config")}, nil), - Data: test.WithConfig(nerdtest.NerdctlToml, `# containerd config, not nerdctl config + testCase := nerdtest.Setup() + + // Docker does not support nerdctl.toml obviously + testCase.Require = test.Not(nerdtest.Docker) + + testCase.SubTests = []*test.Case{ + { + Description: "Default", + Command: test.Command("info", "-f", "{{.Driver}}"), + Expected: test.Expects(0, nil, test.Equals(defaults.DefaultSnapshotter+"\n")), + }, + { + Description: "TOML > Default", + Command: test.Command("info", "-f", "{{.Driver}}"), + Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-toml\n")), + Config: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), + }, + { + Description: "Cli > TOML > Default", + Command: test.Command("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli"), + Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-cli\n")), + Config: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), + }, + { + Description: "Env > TOML > Default", + Command: test.Command("info", "-f", "{{.Driver}}"), + Env: map[string]string{"CONTAINERD_SNAPSHOTTER": "dummy-snapshotter-via-env"}, + Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-env\n")), + Config: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), + }, + { + Description: "Cli > Env > TOML > Default", + Command: test.Command("info", "-f", "{{.Driver}}", "--snapshotter=dummy-snapshotter-via-cli"), + Env: map[string]string{"CONTAINERD_SNAPSHOTTER": "dummy-snapshotter-via-env"}, + Expected: test.Expects(0, nil, test.Equals("dummy-snapshotter-via-cli\n")), + Config: test.WithConfig(nerdtest.NerdctlToml, `snapshotter = "dummy-snapshotter-via-toml"`), + }, + { + Description: "Broken config", + Command: test.Command("info"), + Expected: test.Expects(1, []error{errors.New("failed to load nerdctl config")}, nil), + Config: test.WithConfig(nerdtest.NerdctlToml, `# containerd config, not nerdctl config version = 2`), - }, }, } - tc.Run(t) + testCase.Run(t) } diff --git a/cmd/nerdctl/main_test_test.go b/cmd/nerdctl/main_test_test.go index a515df48536..695c52bac07 100644 --- a/cmd/nerdctl/main_test_test.go +++ b/cmd/nerdctl/main_test_test.go @@ -27,44 +27,44 @@ import ( // TestTest is testing the test tooling itself func TestTest(t *testing.T) { - nerdtest.Setup() + testCase := nerdtest.Setup() - tg := &test.Group{ + testCase.SubTests = []*test.Case{ { Description: "failure", - Command: test.RunCommand("undefinedcommand"), + Command: test.Command("undefinedcommand"), Expected: test.Expects(1, nil, nil), }, { Description: "success", - Command: test.RunCommand("info"), + Command: test.Command("info"), Expected: test.Expects(0, nil, nil), }, { Description: "failure with single error testing", - Command: test.RunCommand("undefinedcommand"), + Command: test.Command("undefinedcommand"), Expected: test.Expects(1, []error{errors.New("unknown subcommand")}, nil), }, { Description: "success with contains output testing", - Command: test.RunCommand("info"), + Command: test.Command("info"), Expected: test.Expects(0, nil, test.Contains("Kernel")), }, { Description: "success with negative output testing", - Command: test.RunCommand("info"), + Command: test.Command("info"), Expected: test.Expects(0, nil, test.DoesNotContain("foobar")), }, // Note that docker annoyingly returns 125 in a few conditions like this { Description: "failure with multiple error testing", - Command: test.RunCommand("-fail"), + Command: test.Command("-fail"), Expected: test.Expects(-1, []error{errors.New("unknown"), errors.New("shorthand")}, nil), }, { Description: "success with exact output testing", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.CustomCommand("echo", "foobar") + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("echo", "foobar") }, Expected: test.Expects(0, nil, test.Equals("foobar\n")), }, @@ -74,14 +74,13 @@ func TestTest(t *testing.T) { Setup: func(data test.Data, helpers test.Helpers) { data.Set("status", data.Get("status")+"-setup") }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - cmd := helpers.CustomCommand("printf", data.Get("status")) + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Custom("printf", data.Get("status")) data.Set("status", data.Get("status")+"-command") return cmd }, Cleanup: func(data test.Data, helpers test.Helpers) { - if data.Get("first-run") == "" { - data.Set("first-run", "first cleanup") + if data.Get("status") == "uninitialized" { return } if data.Get("status") != "uninitialized-setup-command" { @@ -92,56 +91,15 @@ func TestTest(t *testing.T) { SubTests: []*test.Case{ { Description: "Subtest data propagation", - Command: func(data test.Data, helpers test.Helpers) test.Command { - return helpers.CustomCommand("printf", data.Get("status")) + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("printf", data.Get("status")) }, Expected: test.Expects(0, nil, test.Equals("uninitialized-setup-command")), }, }, Expected: test.Expects(0, nil, test.Equals("uninitialized-setup")), }, - { - Description: "env propagation and isolation", - Env: map[string]string{ - "GLOBAL_ENV": "in this test", - }, - Setup: func(data test.Data, helpers test.Helpers) { - cmd := helpers.CustomCommand("sh", "-c", "--", "printf \"$GLOBAL_ENV\"") - cmd.Run(&test.Expected{ - Output: test.Equals("in this test"), - }) - cmd.WithEnv(map[string]string{ - "GLOBAL_ENV": "overridden in setup", - }) - cmd.Run(&test.Expected{ - Output: test.Equals("overridden in setup"), - }) - }, - Command: func(data test.Data, helpers test.Helpers) test.Command { - cmd := helpers.CustomCommand("sh", "-c", "--", "printf \"$GLOBAL_ENV\"") - cmd.Run(&test.Expected{ - Output: test.Equals("in this test"), - }) - cmd.WithEnv(map[string]string{ - "GLOBAL_ENV": "overridden in command", - }) - return cmd - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - cmd := helpers.CustomCommand("sh", "-c", "--", "printf \"$GLOBAL_ENV\"") - cmd.Run(&test.Expected{ - Output: test.Equals("in this test"), - }) - cmd.WithEnv(map[string]string{ - "GLOBAL_ENV": "overridden in cleanup", - }) - cmd.Run(&test.Expected{ - Output: test.Equals("overridden in cleanup"), - }) - }, - Expected: test.Expects(0, nil, test.Equals("overridden in command")), - }, } - tg.Run(t) + testCase.Run(t) } From 157d1838011fdf7a373687c39b1f5433f0c2e514 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 7 Oct 2024 00:27:23 -0700 Subject: [PATCH 0816/1066] Migrate IPFS tests Tests have been re-organized & re-structured in places. Some have been expended in scope. No test has been removed. The full IPFS suite now runs under 100 seconds on a modern M1 max inside Lima. Signed-off-by: apostasie --- cmd/nerdctl/ipfs/ipfs_build_linux_test.go | 67 ---- cmd/nerdctl/ipfs/ipfs_compose_linux_test.go | 331 ++++++++++++++----- cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go | 105 ++++++ cmd/nerdctl/ipfs/ipfs_linux_test.go | 148 --------- cmd/nerdctl/ipfs/ipfs_registry_linux_test.go | 143 ++++++-- cmd/nerdctl/ipfs/ipfs_simple_linux_test.go | 227 +++++++++++++ 6 files changed, 696 insertions(+), 325 deletions(-) delete mode 100644 cmd/nerdctl/ipfs/ipfs_build_linux_test.go create mode 100644 cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go delete mode 100644 cmd/nerdctl/ipfs/ipfs_linux_test.go create mode 100644 cmd/nerdctl/ipfs/ipfs_simple_linux_test.go diff --git a/cmd/nerdctl/ipfs/ipfs_build_linux_test.go b/cmd/nerdctl/ipfs/ipfs_build_linux_test.go deleted file mode 100644 index 7ca00803bdb..00000000000 --- a/cmd/nerdctl/ipfs/ipfs_build_linux_test.go +++ /dev/null @@ -1,67 +0,0 @@ -/* - 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 ipfs - -import ( - "fmt" - "strings" - "testing" - "time" - - "gotest.tools/v3/assert" - "gotest.tools/v3/icmd" - - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestIPFSBuild(t *testing.T) { - testutil.DockerIncompatible(t) - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage) - ipfsCIDBase := strings.TrimPrefix(ipfsCID, "ipfs://") - - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() - - dockerfile := fmt.Sprintf(`FROM localhost:5050/ipfs/%s -CMD ["echo", "nerdctl-build-test-string"] - `, ipfsCIDBase) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - done := ipfsRegistryUp(t, base) - defer done() - base.Cmd("build", "-t", imageName, buildCtx).AssertOK() - base.Cmd("build", buildCtx, "-t", imageName).AssertOK() - - base.Cmd("run", "--rm", imageName).AssertOutContains("nerdctl-build-test-string") -} - -func ipfsRegistryUp(t *testing.T, base *testutil.Base, args ...string) (done func() error) { - res := icmd.StartCmd(base.Cmd(append([]string{"ipfs", "registry", "serve"}, args...)...).Cmd) - time.Sleep(time.Second) - assert.Assert(t, res.Cmd.Process != nil) - assert.NilError(t, res.Error) - return func() error { - res.Cmd.Process.Kill() - icmd.WaitOnCmd(3*time.Second, res) - return nil - } -} diff --git a/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go index 1ac2b682482..7619e0b0591 100644 --- a/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go @@ -19,84 +19,144 @@ package ipfs import ( "fmt" "io" + "strconv" "strings" "testing" + "time" "gotest.tools/v3/assert" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/registry" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" - "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" + "github.com/containerd/nerdctl/v2/pkg/testutil/portlock" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func TestIPFSComposeUp(t *testing.T) { - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - - iReg := testregistry.NewIPFSRegistry(base, nil, 0, nil, nil) - t.Cleanup(func() { - iReg.Cleanup(nil) - }) - ipfsaddr := fmt.Sprintf("/ip4/%s/tcp/%d", iReg.IP, iReg.Port) - - tests := []struct { - name string - snapshotter string - pushOptions []string - composeOptions []string - requiresStargz bool - }{ - { - name: "overlayfs", - snapshotter: "overlayfs", - }, - { - name: "stargz", - snapshotter: "stargz", - pushOptions: []string{"--estargz"}, - requiresStargz: true, - }, - { - name: "ipfs-address", - snapshotter: "overlayfs", - pushOptions: []string{fmt.Sprintf("--ipfs-address=%s", ipfsaddr)}, - composeOptions: []string{fmt.Sprintf("--ipfs-address=%s", ipfsaddr)}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - base := testutil.NewBase(t) - if tt.requiresStargz { - helpers.RequiresStargz(base) - } - ipfsImgs := make([]string, 2) - for i, img := range []string{testutil.WordpressImage, testutil.MariaDBImage} { - ipfsImgs[i] = pushImageToIPFS(t, base, img, tt.pushOptions...) +func TestIPFSCompNoBuild(t *testing.T) { + testCase := nerdtest.Setup() + + const ipfsAddrKey = "ipfsAddrKey" + + var ipfsRegistry *registry.Server + + testCase.Require = test.Require( + test.Linux, + test.Not(nerdtest.Docker), + nerdtest.Registry, + nerdtest.IPFS, + // See note below + // nerdtest.Private, + ) + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + // Start Kubo + ipfsRegistry = registry.NewKuboRegistry(data, helpers, t, nil, 0, nil) + ipfsRegistry.Setup(data, helpers) + data.Set(ipfsAddrKey, fmt.Sprintf("/ip4/%s/tcp/%d", ipfsRegistry.IP, ipfsRegistry.Port)) + + // Ensure we have the images + helpers.Ensure("pull", "--quiet", testutil.WordpressImage) + helpers.Ensure("pull", "--quiet", testutil.MariaDBImage) + } + + testCase.SubTests = []*test.Case{ + subtestTestIPFSCompNoB(t, false, false), + subtestTestIPFSCompNoB(t, true, false), + subtestTestIPFSCompNoB(t, false, true), + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if ipfsRegistry != nil { + ipfsRegistry.Cleanup(data, helpers) + } + // Speeding up repeat tests... + helpers.Anyhow("rmi", testutil.WordpressImage) + helpers.Anyhow("rmi", testutil.MariaDBImage) + } + + testCase.Run(t) +} + +func subtestTestIPFSCompNoB(t *testing.T, stargz bool, byAddr bool) *test.Case { + t.Helper() + + const ipfsAddrKey = "ipfsAddrKey" + const mariaImageCIDKey = "mariaImageCIDKey" + const wordpressImageCIDKey = "wordpressImageCIDKey" + const composeExtraKey = "composeExtraKey" + + testCase := &test.Case{} + + testCase.Description += "with" + + if stargz { + testCase.Description += "-stargz" + } + + if byAddr { + testCase.Description += "-byAddr" + } + + if stargz { + testCase.Require = nerdtest.Stargz + } + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + var ipfsCIDWP, ipfsCIDMD string + if stargz { + ipfsCIDWP = pushToIPFS(helpers, testutil.WordpressImage, "--estargz") + ipfsCIDMD = pushToIPFS(helpers, testutil.MariaDBImage, "--estargz") + } else if byAddr { + ipfsCIDWP = pushToIPFS(helpers, testutil.WordpressImage, "--ipfs-address="+data.Get(ipfsAddrKey)) + ipfsCIDMD = pushToIPFS(helpers, testutil.MariaDBImage, "--ipfs-address="+data.Get(ipfsAddrKey)) + data.Set(composeExtraKey, "--ipfs-address="+data.Get(ipfsAddrKey)) + } else { + ipfsCIDWP = pushToIPFS(helpers, testutil.WordpressImage) + ipfsCIDMD = pushToIPFS(helpers, testutil.MariaDBImage) + } + data.Set(wordpressImageCIDKey, ipfsCIDWP) + data.Set(mariaImageCIDKey, ipfsCIDMD) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + // NOTE: + // Removing these images locally forces tests to be sequentials (as IPFS being content addressable, + // they have the same cid - except for the estargz version obviously) + // Deliberately electing to not remove them here so that we can parallelize and cut down the running time + /* + if data.Get(mariaImageCIDKey) != "" { + helpers.Anyhow("rmi", data.Get(mariaImageCIDKey)) + helpers.Anyhow("rmi", data.Get(wordpressImageCIDKey)) } - base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER="+tt.snapshotter) - helpers.ComposeUp(t, base, fmt.Sprintf(` + */ + } + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + safePort, err := portlock.Acquire(0) + assert.NilError(helpers.T(), err) + data.Set("wordpressPort", strconv.Itoa(safePort)) + composeUP(data, helpers, fmt.Sprintf(` version: '3.1' services: wordpress: - image: %s + image: ipfs://%s restart: always ports: - - 8080:80 + - %d:80 environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: exampleuser WORDPRESS_DB_PASSWORD: examplepass WORDPRESS_DB_NAME: exampledb volumes: - # workaround for https://github.com/containerd/stargz-snapshotter/issues/444 - - "/run" - wordpress:/var/www/html db: - image: %s + image: ipfs://%s restart: always environment: MYSQL_DATABASE: exampledb @@ -104,53 +164,160 @@ services: MYSQL_PASSWORD: examplepass MYSQL_RANDOM_ROOT_PASSWORD: '1' volumes: - # workaround for https://github.com/containerd/stargz-snapshotter/issues/444 - - "/run" - db:/var/lib/mysql volumes: wordpress: db: -`, ipfsImgs[0], ipfsImgs[1]), tt.composeOptions...) - }) +`, data.Get(wordpressImageCIDKey), safePort, data.Get(mariaImageCIDKey)), data.Get(composeExtraKey)) + // FIXME: need to break down composeUP into testable commands instead + // Right now, this is just a dummy placeholder + return helpers.Command("info") } + + testCase.Expected = test.Expects(0, nil, nil) + + return testCase } -func TestIPFSComposeUpBuild(t *testing.T) { - testutil.DockerIncompatible(t) - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - ipfsCID := pushImageToIPFS(t, base, testutil.NginxAlpineImage) - ipfsCIDBase := strings.TrimPrefix(ipfsCID, "ipfs://") +func TestIPFSCompBuild(t *testing.T) { + testCase := nerdtest.Setup() + + var ipfsServer test.TestableCommand + var comp *testutil.ComposeDir + + const mainImageCIDKey = "mainImageCIDKey" + safePort, err := portlock.Acquire(0) + assert.NilError(t, err) + var listenAddr = "localhost:" + strconv.Itoa(safePort) + + testCase.Require = test.Require( + // Linux only + test.Linux, + // Obviously not docker supported + test.Not(nerdtest.Docker), + nerdtest.Build, + nerdtest.IPFS, + ) + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + // Get alpine + helpers.Ensure("pull", "--quiet", testutil.NginxAlpineImage) + // Start a local ipfs backed registry + // FIXME: this is bad and likely to collide with other tests + ipfsServer = helpers.Command("ipfs", "registry", "serve", "--listen-registry", listenAddr) + // Once foregrounded, do not wait for it more than a second + ipfsServer.Background(1 * time.Second) + // Apparently necessary to let it start... + time.Sleep(time.Second) - const dockerComposeYAML = ` + // Save nginx to ipfs + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.NginxAlpineImage)) + + const dockerComposeYAML = ` services: web: build: . ports: - - 8080:80 + - 8081:80 ` - dockerfile := fmt.Sprintf(`FROM localhost:5050/ipfs/%s + dockerfile := fmt.Sprintf(`FROM %s/ipfs/%s COPY index.html /usr/share/nginx/html/index.html -`, ipfsCIDBase) - indexHTML := t.Name() +`, listenAddr, data.Get(mainImageCIDKey)) - comp := testutil.NewComposeDir(t, dockerComposeYAML) - defer comp.CleanUp() + comp = testutil.NewComposeDir(t, dockerComposeYAML) + comp.WriteFile("Dockerfile", dockerfile) + comp.WriteFile("index.html", data.Identifier("indexhtml")) + } - comp.WriteFile("Dockerfile", dockerfile) - comp.WriteFile("index.html", indexHTML) + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if ipfsServer != nil { + // Close the server once done + helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + ipfsServer.Run(nil) + } + if comp != nil { + helpers.Anyhow("compose", "-f", comp.YAMLFullPath(), "down", "-v") + comp.CleanUp() + } + } - done := ipfsRegistryUp(t, base) - defer done() - base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "-d", "--build").AssertOK() - defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").Run() + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("compose", "-f", comp.YAMLFullPath(), "up", "-d", "--build") + } - resp, err := nettestutil.HTTPGet("http://127.0.0.1:8080", 50, false) - assert.NilError(t, err) - respBody, err := io.ReadAll(resp.Body) - assert.NilError(t, err) - t.Logf("respBody=%q", respBody) - assert.Assert(t, strings.Contains(string(respBody), indexHTML)) + testCase.Expected = func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + resp, err := nettestutil.HTTPGet("http://127.0.0.1:8081", 10, false) + assert.NilError(t, err) + respBody, err := io.ReadAll(resp.Body) + assert.NilError(t, err) + t.Logf("respBody=%q", respBody) + assert.Assert(t, strings.Contains(string(respBody), data.Identifier("indexhtml"))) + }, + } + } + + testCase.Run(t) +} + +func composeUP(data test.Data, helpers test.Helpers, dockerComposeYAML string, opts string) { + comp := testutil.NewComposeDir(helpers.T(), dockerComposeYAML) + // defer comp.CleanUp() + + // Because it might or might not happen, and + helpers.Anyhow("compose", "-f", comp.YAMLFullPath(), "down", "-v") + defer helpers.Anyhow("compose", "-f", comp.YAMLFullPath(), "down", "-v") + + projectName := comp.ProjectName() + + args := []string{"compose", "-f", comp.YAMLFullPath()} + if opts != "" { + args = append(args, opts) + } + + helpers.Ensure(append(args, "up", "--quiet-pull", "-d")...) + + helpers.Ensure("volume", "inspect", fmt.Sprintf("%s_db", projectName)) + helpers.Ensure("network", "inspect", fmt.Sprintf("%s_default", projectName)) + + checkWordpress := func() error { + // FIXME: see other notes on using the same port repeatedly + resp, err := nettestutil.HTTPGet("http://127.0.0.1:"+data.Get("wordpressPort"), 5, false) + if err != nil { + return err + } + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + if !strings.Contains(string(respBody), testutil.WordpressIndexHTMLSnippet) { + return fmt.Errorf("respBody does not contain %q (%s)", testutil.WordpressIndexHTMLSnippet, string(respBody)) + } + return nil + } + + var wordpressWorking bool + var err error + // 15 seconds is long enough + for i := 0; i < 5; i++ { + err = checkWordpress() + if err == nil { + wordpressWorking = true + break + } + time.Sleep(3 * time.Second) + } + + if !wordpressWorking { + ccc := helpers.Capture("ps", "-a") + helpers.T().Log(ccc) + helpers.T().Error(helpers.Err("logs", projectName+"-wordpress-1")) + helpers.T().Fatalf("wordpress is not working %v", err) + } + + helpers.Ensure("compose", "-f", comp.YAMLFullPath(), "down", "-v") + helpers.Fail("volume", "inspect", fmt.Sprintf("%s_db", projectName)) + helpers.Fail("network", "inspect", fmt.Sprintf("%s_default", projectName)) } diff --git a/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go b/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go new file mode 100644 index 00000000000..3738ceb4514 --- /dev/null +++ b/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go @@ -0,0 +1,105 @@ +/* + 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 ipfs + +import ( + "fmt" + "regexp" + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/registry" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestIPFSAddrWithKubo(t *testing.T) { + testCase := nerdtest.Setup() + + const mainImageCIDKey = "mainImagemainImageCIDKey" + const ipfsAddrKey = "ipfsAddrKey" + + var ipfsRegistry *registry.Server + + testCase.Require = test.Require( + test.Linux, + test.Not(nerdtest.Docker), + nerdtest.Registry, + nerdtest.Private, + ) + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "--quiet", testutil.AlpineImage) + + ipfsRegistry = registry.NewKuboRegistry(data, helpers, t, nil, 0, nil) + ipfsRegistry.Setup(data, helpers) + ipfsAddr := fmt.Sprintf("/ip4/%s/tcp/%d", ipfsRegistry.IP, ipfsRegistry.Port) + data.Set(ipfsAddrKey, ipfsAddr) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if ipfsRegistry != nil { + ipfsRegistry.Cleanup(data, helpers) + } + } + + testCase.SubTests = []*test.Case{ + { + Description: "with default snapshotter", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + ipfsCID := pushToIPFS(helpers, testutil.AlpineImage, fmt.Sprintf("--ipfs-address=%s", data.Get(ipfsAddrKey))) + helpers.Ensure("pull", "--ipfs-address", data.Get(ipfsAddrKey), "ipfs://"+ipfsCID) + data.Set(mainImageCIDKey, ipfsCID) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get(mainImageCIDKey) != "" { + helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get(mainImageCIDKey), "echo", "hello") + }, + Expected: test.Expects(0, nil, test.Equals("hello\n")), + }, + { + Description: "with stargz snapshotter", + NoParallel: true, + Require: test.Require( + nerdtest.Stargz, + nerdtest.Private, + nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3475"), + ), + Setup: func(data test.Data, helpers test.Helpers) { + ipfsCID := pushToIPFS(helpers, testutil.AlpineImage, fmt.Sprintf("--ipfs-address=%s", data.Get(ipfsAddrKey)), "--estargz") + helpers.Ensure("pull", "--ipfs-address", data.Get(ipfsAddrKey), "ipfs://"+ipfsCID) + data.Set(mainImageCIDKey, ipfsCID) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get(mainImageCIDKey) != "" { + helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get(mainImageCIDKey), "ls", "/.stargz-snapshotter") + }, + Expected: test.Expects(0, nil, test.Match(regexp.MustCompile("sha256:.*[.]json[\n]"))), + }, + } + + testCase.Run(t) +} diff --git a/cmd/nerdctl/ipfs/ipfs_linux_test.go b/cmd/nerdctl/ipfs/ipfs_linux_test.go deleted file mode 100644 index a50e426ae0f..00000000000 --- a/cmd/nerdctl/ipfs/ipfs_linux_test.go +++ /dev/null @@ -1,148 +0,0 @@ -/* - 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 ipfs - -import ( - "fmt" - "testing" - - "gotest.tools/v3/assert" - - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" - "github.com/containerd/nerdctl/v2/pkg/infoutil" - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/containerd/nerdctl/v2/pkg/testutil" - "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" -) - -func TestIPFS(t *testing.T) { - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage) - base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=overlayfs") - base.Cmd("pull", ipfsCID).AssertOK() - base.Cmd("run", "--rm", ipfsCID, "echo", "hello").AssertOK() - - // encryption - keyPair := helpers.NewJWEKeyPair(t) - defer keyPair.Cleanup() - tID := testutil.Identifier(t) - encryptImageRef := tID + ":enc" - layersNum := 1 - base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, ipfsCID, encryptImageRef).AssertOK() - base.Cmd("image", "inspect", "--mode=native", "--format={{len .Manifest.Layers}}", encryptImageRef).AssertOutExactly(fmt.Sprintf("%d\n", layersNum)) - for i := 0; i < layersNum; i++ { - base.Cmd("image", "inspect", "--mode=native", fmt.Sprintf("--format={{json (index .Manifest.Layers %d) }}", i), encryptImageRef).AssertOutContains("org.opencontainers.image.enc.keys.jwe") - } - ipfsCIDEnc := cidOf(t, base.Cmd("push", "ipfs://"+encryptImageRef).OutLines()) - helpers.RmiAll(base) - - decryptImageRef := tID + ":dec" - base.Cmd("pull", "--unpack=false", ipfsCIDEnc).AssertOK() - base.Cmd("image", "decrypt", "--key="+keyPair.Pub, ipfsCIDEnc, decryptImageRef).AssertFail() // decryption needs prv key, not pub key - base.Cmd("image", "decrypt", "--key="+keyPair.Prv, ipfsCIDEnc, decryptImageRef).AssertOK() - base.Cmd("run", "--rm", decryptImageRef, "/bin/sh", "-c", "echo hello").AssertOK() -} - -func TestIPFSAddress(t *testing.T) { - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - iReg := testregistry.NewIPFSRegistry(base, nil, 0, nil, nil) - t.Cleanup(func() { - iReg.Cleanup(nil) - }) - ipfsaddr := fmt.Sprintf("/ip4/%s/tcp/%d", iReg.IP, iReg.Port) - - ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, fmt.Sprintf("--ipfs-address=%s", ipfsaddr)) - base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=overlayfs") - base.Cmd("pull", "--ipfs-address", ipfsaddr, ipfsCID).AssertOK() - base.Cmd("run", "--ipfs-address", ipfsaddr, "--rm", ipfsCID, "echo", "hello").AssertOK() -} - -func TestIPFSCommit(t *testing.T) { - // cgroup is required for nerdctl commit - if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { - t.Skip("test skipped for rootless containers on cgroup v1") - } - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage) - - base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=overlayfs") - base.Cmd("pull", ipfsCID).AssertOK() - base.Cmd("run", "--rm", ipfsCID, "echo", "hello").AssertOK() - tID := testutil.Identifier(t) - newContainer, newImg := tID, tID+":v1" - base.Cmd("run", "--name", newContainer, "-d", ipfsCID, "/bin/sh", "-c", "echo hello > /hello ; sleep 10000").AssertOK() - base.Cmd("commit", newContainer, newImg).AssertOK() - base.Cmd("kill", newContainer).AssertOK() - base.Cmd("rm", newContainer).AssertOK() - ipfsCID2 := cidOf(t, base.Cmd("push", "ipfs://"+newImg).OutLines()) - helpers.RmiAll(base) - base.Cmd("pull", ipfsCID2).AssertOK() - base.Cmd("run", "--rm", ipfsCID2, "/bin/sh", "-c", "cat /hello").AssertOK() -} - -func TestIPFSWithLazyPulling(t *testing.T) { - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - helpers.RequiresStargz(base) - ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") - - base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=stargz") - base.Cmd("pull", ipfsCID).AssertOK() - base.Cmd("run", "--rm", ipfsCID, "ls", "/.stargz-snapshotter").AssertOK() -} - -func TestIPFSWithLazyPullingCommit(t *testing.T) { - // cgroup is required for nerdctl commit - if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { - t.Skip("test skipped for rootless containers on cgroup v1") - } - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - helpers.RequiresStargz(base) - ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") - - base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=stargz") - base.Cmd("pull", ipfsCID).AssertOK() - base.Cmd("run", "--rm", ipfsCID, "ls", "/.stargz-snapshotter").AssertOK() - tID := testutil.Identifier(t) - newContainer, newImg := tID, tID+":v1" - base.Cmd("run", "--name", newContainer, "-d", ipfsCID, "/bin/sh", "-c", "echo hello > /hello ; sleep 10000").AssertOK() - base.Cmd("commit", newContainer, newImg).AssertOK() - base.Cmd("kill", newContainer).AssertOK() - base.Cmd("rm", newContainer).AssertOK() - ipfsCID2 := cidOf(t, base.Cmd("push", "--estargz", "ipfs://"+newImg).OutLines()) - helpers.RmiAll(base) - - base.Cmd("pull", ipfsCID2).AssertOK() - base.Cmd("run", "--rm", ipfsCID2, "/bin/sh", "-c", "ls /.stargz-snapshotter && cat /hello").AssertOK() - base.Cmd("image", "rm", ipfsCID2).AssertOK() -} - -func pushImageToIPFS(t *testing.T, base *testutil.Base, name string, opts ...string) string { - base.Cmd("pull", name).AssertOK() - ipfsCID := cidOf(t, base.Cmd(append([]string{"push"}, append(opts, "ipfs://"+name)...)...).OutLines()) - base.Cmd("rmi", name).Run() - return ipfsCID -} - -func cidOf(t *testing.T, lines []string) string { - assert.Equal(t, len(lines) >= 2, true) - return "ipfs://" + lines[len(lines)-2] -} diff --git a/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go index d367d0d9f86..63a461361cc 100644 --- a/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go @@ -17,44 +17,131 @@ package ipfs import ( + "fmt" + "regexp" "strings" "testing" + "time" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "gotest.tools/v3/assert" + + testhelpers "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func TestIPFSRegistry(t *testing.T) { - testutil.DockerIncompatible(t) +func pushToIPFS(helpers test.Helpers, name string, opts ...string) string { + var ipfsCID string + cmd := helpers.Command("push", "ipfs://"+name) + cmd.WithArgs(opts...) + cmd.Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(stdout, "\n") + assert.Equal(t, len(lines) >= 2, true) + ipfsCID = lines[len(lines)-2] + }, + }) + return ipfsCID +} - base := testutil.NewBase(t) - base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=overlayfs") - ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage) - ipfsRegistryAddr := "localhost:5555" - ipfsRegistryRef := ipfsRegistryReference(ipfsRegistryAddr, ipfsCID) +func TestIPFSNerdctlRegistry(t *testing.T) { + testCase := nerdtest.Setup() - done := ipfsRegistryUp(t, base, "--listen-registry", ipfsRegistryAddr) - defer done() - base.Cmd("pull", ipfsRegistryRef).AssertOK() - base.Cmd("run", "--rm", ipfsRegistryRef, "echo", "hello").AssertOK() -} + // FIXME: this is bad and likely to collide with other tests + const listenAddr = "localhost:5555" -func TestIPFSRegistryWithLazyPulling(t *testing.T) { - testutil.DockerIncompatible(t) + const ipfsImageURLKey = "ipfsImageURLKey" - base := testutil.NewBase(t) - helpers.RequiresStargz(base) - base.Env = append(base.Env, "CONTAINERD_SNAPSHOTTER=stargz") - ipfsCID := pushImageToIPFS(t, base, testutil.AlpineImage, "--estargz") - ipfsRegistryAddr := "localhost:5555" - ipfsRegistryRef := ipfsRegistryReference(ipfsRegistryAddr, ipfsCID) + var ipfsServer test.TestableCommand - done := ipfsRegistryUp(t, base, "--listen-registry", ipfsRegistryAddr) - defer done() - base.Cmd("pull", ipfsRegistryRef).AssertOK() - base.Cmd("run", "--rm", ipfsRegistryRef, "ls", "/.stargz-snapshotter").AssertOK() -} + testCase.Require = test.Require( + test.Linux, + test.Not(nerdtest.Docker), + nerdtest.IPFS, + ) + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "--quiet", testutil.AlpineImage) + + // Start a local ipfs backed registry + ipfsServer = helpers.Command("ipfs", "registry", "serve", "--listen-registry", listenAddr) + // Once foregrounded, do not wait for it more than a second + ipfsServer.Background(1 * time.Second) + // Apparently necessary to let it start... + time.Sleep(time.Second) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + if ipfsServer != nil { + // Close the server once done + ipfsServer.Run(nil) + } + } + + testCase.SubTests = []*test.Case{ + { + Description: "with default snapshotter", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.AlpineImage)) + helpers.Ensure("pull", data.Get(ipfsImageURLKey)) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get(ipfsImageURLKey) != "" { + helpers.Anyhow("rmi", data.Get(ipfsImageURLKey)) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get(ipfsImageURLKey), "echo", "hello") + }, + Expected: test.Expects(0, nil, test.Equals("hello\n")), + }, + { + Description: "with stargz snapshotterr", + NoParallel: true, + Require: nerdtest.Stargz, + Setup: func(data test.Data, helpers test.Helpers) { + data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.AlpineImage, "--estargz")) + helpers.Ensure("pull", data.Get(ipfsImageURLKey)) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get(ipfsImageURLKey) != "" { + helpers.Anyhow("rmi", data.Get(ipfsImageURLKey)) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get(ipfsImageURLKey), "ls", "/.stargz-snapshotter") + }, + Expected: test.Expects(0, nil, test.Match(regexp.MustCompile("sha256:.*[.]json[\n]"))), + }, + { + Description: "with build", + NoParallel: true, + Require: nerdtest.Build, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier("built-image")) + if data.Get(ipfsImageURLKey) != "" { + helpers.Anyhow("rmi", data.Get(ipfsImageURLKey)) + } + }, + Setup: func(data test.Data, helpers test.Helpers) { + data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.AlpineImage)) + + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-build-test-string"] + `, data.Get(ipfsImageURLKey)) + + buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + + helpers.Ensure("build", "-t", data.Identifier("built-image"), buildCtx) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier("built-image")) + }, + Expected: test.Expects(0, nil, test.Equals("nerdctl-build-test-string\n")), + }, + } -func ipfsRegistryReference(addr string, c string) string { - return addr + "/ipfs/" + strings.TrimPrefix(c, "ipfs://") + testCase.Run(t) } diff --git a/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go b/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go new file mode 100644 index 00000000000..e18acc332ee --- /dev/null +++ b/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go @@ -0,0 +1,227 @@ +/* + 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 ipfs + +import ( + "regexp" + "testing" + + testhelpers "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestIPFSSimple(t *testing.T) { + testCase := nerdtest.Setup() + + const mainImageCIDKey = "mainImageCIDKey" + const transformedImageCIDKey = "transformedImageCIDKey" + + testCase.Require = test.Require( + test.Linux, + test.Not(nerdtest.Docker), + nerdtest.IPFS, + // We constantly rmi the image by its CID which is shared across tests, so, we make this group private + // and every subtest NoParallel + nerdtest.Private, + ) + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "--quiet", testutil.AlpineImage) + } + + testCase.SubTests = []*test.Case{ + { + Description: "with default snapshotter", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.AlpineImage)) + helpers.Ensure("pull", "ipfs://"+data.Get(mainImageCIDKey)) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get(mainImageCIDKey) != "" { + helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get(mainImageCIDKey), "echo", "hello") + }, + Expected: test.Expects(0, nil, test.Equals("hello\n")), + }, + { + Description: "with stargz snapshotter", + NoParallel: true, + Require: test.Require( + nerdtest.Stargz, + nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3475"), + ), + Setup: func(data test.Data, helpers test.Helpers) { + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.AlpineImage, "--estargz")) + helpers.Ensure("pull", "ipfs://"+data.Get(mainImageCIDKey)) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get(mainImageCIDKey) != "" { + helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get(mainImageCIDKey), "ls", "/.stargz-snapshotter") + }, + Expected: test.Expects(0, nil, test.Match(regexp.MustCompile("sha256:.*[.]json[\n]"))), + }, + { + Description: "with commit and push", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.AlpineImage)) + helpers.Ensure("pull", "ipfs://"+data.Get(mainImageCIDKey)) + + // Run a container that does modify something, then commit and push it + helpers.Ensure("run", "--name", data.Identifier("commit-container"), data.Get(mainImageCIDKey), "sh", "-c", "--", "echo hello > /hello") + helpers.Ensure("commit", data.Identifier("commit-container"), data.Identifier("commit-image")) + data.Set(transformedImageCIDKey, pushToIPFS(helpers, data.Identifier("commit-image"))) + + // Clean-up + helpers.Ensure("rm", data.Identifier("commit-container")) + helpers.Ensure("rmi", data.Identifier("commit-image")) + + // Pull back the committed image + helpers.Ensure("pull", "ipfs://"+data.Get(transformedImageCIDKey)) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", data.Identifier("commit-container")) + helpers.Anyhow("rmi", data.Identifier("commit-image")) + if data.Get(mainImageCIDKey) != "" { + helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + helpers.Anyhow("rmi", data.Get(transformedImageCIDKey)) + } + }, + + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get(transformedImageCIDKey), "cat", "/hello") + }, + + Expected: test.Expects(0, nil, test.Equals("hello\n")), + }, + { + Description: "with commit and push, stargz lazy pulling", + NoParallel: true, + Require: test.Require( + nerdtest.Stargz, + nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3475"), + ), + Setup: func(data test.Data, helpers test.Helpers) { + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.AlpineImage, "--estargz")) + helpers.Ensure("pull", "ipfs://"+data.Get(mainImageCIDKey)) + + // Run a container that does modify something, then commit and push it + helpers.Ensure("run", "--name", data.Identifier("commit-container"), data.Get(mainImageCIDKey), "sh", "-c", "--", "echo hello > /hello") + helpers.Ensure("commit", data.Identifier("commit-container"), data.Identifier("commit-image")) + data.Set(transformedImageCIDKey, pushToIPFS(helpers, data.Identifier("commit-image"))) + + // Clean-up + helpers.Ensure("rm", data.Identifier("commit-container")) + helpers.Ensure("rmi", data.Identifier("commit-image")) + + // Pull back the image + helpers.Ensure("pull", "ipfs://"+data.Get(transformedImageCIDKey)) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", data.Identifier("commit-container")) + helpers.Anyhow("rmi", data.Identifier("commit-image")) + if data.Get(mainImageCIDKey) != "" { + helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + helpers.Anyhow("rmi", data.Get(transformedImageCIDKey)) + } + }, + + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get(transformedImageCIDKey), "sh", "-c", "--", "cat /hello && ls /.stargz-snapshotter") + }, + + Expected: test.Expects(0, nil, test.Match(regexp.MustCompile("hello[\n]sha256:.*[.]json[\n]"))), + }, + { + Description: "with encryption", + NoParallel: true, + Require: test.Binary("openssl"), + Setup: func(data test.Data, helpers test.Helpers) { + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.AlpineImage)) + helpers.Ensure("pull", "ipfs://"+data.Get(mainImageCIDKey)) + + // Prep a key pair + keyPair := testhelpers.NewJWEKeyPair(t) + // FIXME: this will only cleanup when the group is done, not right, but it works + t.Cleanup(keyPair.Cleanup) + data.Set("pub", keyPair.Pub) + data.Set("prv", keyPair.Prv) + + // Encrypt the image, and verify it is encrypted + helpers.Ensure("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, data.Get(mainImageCIDKey), data.Identifier("encrypted")) + cmd := helpers.Command("image", "inspect", "--mode=native", "--format={{len .Index.Manifests}}", data.Identifier("encrypted")) + cmd.Run(&test.Expected{ + Output: test.Equals("1\n"), + }) + cmd = helpers.Command("image", "inspect", "--mode=native", "--format={{json (index .Manifest.Layers 0) }}", data.Identifier("encrypted")) + cmd.Run(&test.Expected{ + Output: test.Contains("org.opencontainers.image.enc.keys.jwe"), + }) + + // Push the encrypted image and save the CID + data.Set(transformedImageCIDKey, pushToIPFS(helpers, data.Identifier("encrypted"))) + + // Remove both images locally + helpers.Ensure("rmi", "-f", data.Get(mainImageCIDKey)) + helpers.Ensure("rmi", "-f", data.Get(transformedImageCIDKey)) + + // Pull back without unpacking + helpers.Ensure("pull", "--unpack=false", "ipfs://"+data.Get(transformedImageCIDKey)) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get(mainImageCIDKey) != "" { + helpers.Anyhow("rmi", "-f", data.Get(mainImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(transformedImageCIDKey)) + } + }, + SubTests: []*test.Case{ + { + Description: "decrypt with pub key does not work", + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier("decrypted")) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("image", "decrypt", "--key="+data.Get("pub"), data.Get(transformedImageCIDKey), data.Identifier("decrypted")) + }, + Expected: test.Expects(1, nil, nil), + }, + { + Description: "decrypt with priv key does work", + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier("decrypted")) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("image", "decrypt", "--key="+data.Get("prv"), data.Get(transformedImageCIDKey), data.Identifier("decrypted")) + }, + Expected: test.Expects(0, nil, nil), + }, + }, + }, + } + + testCase.Run(t) +} From 4451d75d1a189474cba6b2b0f93e0a230705b74a Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 7 Oct 2024 00:39:29 -0700 Subject: [PATCH 0817/1066] Migrate image tests Signed-off-by: apostasie --- cmd/nerdctl/image/image_convert_linux_test.go | 152 +++++-- cmd/nerdctl/image/image_convert_test.go | 70 --- cmd/nerdctl/image/image_encrypt_linux_test.go | 82 ++-- cmd/nerdctl/image/image_history_test.go | 192 ++++----- cmd/nerdctl/image/image_inspect_test.go | 17 +- cmd/nerdctl/image/image_list_test.go | 385 +++++++++++------ cmd/nerdctl/image/image_load_linux_test.go | 70 --- cmd/nerdctl/image/image_load_test.go | 81 ++++ cmd/nerdctl/image/image_prune_test.go | 297 ++++++++----- cmd/nerdctl/image/image_pull_linux_test.go | 316 ++++++++------ cmd/nerdctl/image/image_push_linux_test.go | 403 +++++++++++------- cmd/nerdctl/image/image_remove_linux_test.go | 107 ----- cmd/nerdctl/image/image_remove_test.go | 304 +++++++++++++ cmd/nerdctl/image/image_save_linux_test.go | 50 --- cmd/nerdctl/image/image_save_test.go | 141 ++++-- 15 files changed, 1642 insertions(+), 1025 deletions(-) delete mode 100644 cmd/nerdctl/image/image_convert_test.go delete mode 100644 cmd/nerdctl/image/image_load_linux_test.go create mode 100644 cmd/nerdctl/image/image_load_test.go delete mode 100644 cmd/nerdctl/image/image_remove_linux_test.go create mode 100644 cmd/nerdctl/image/image_remove_test.go delete mode 100644 cmd/nerdctl/image/image_save_linux_test.go diff --git a/cmd/nerdctl/image/image_convert_linux_test.go b/cmd/nerdctl/image/image_convert_linux_test.go index ae90cca5af9..1b16d079bde 100644 --- a/cmd/nerdctl/image/image_convert_linux_test.go +++ b/cmd/nerdctl/image/image_convert_linux_test.go @@ -20,63 +20,125 @@ import ( "fmt" "testing" - "gotest.tools/v3/icmd" - - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) -func TestImageConvertNydus(t *testing.T) { - testutil.RequireExecutable(t, "nydus-image") - testutil.DockerIncompatible(t) +func TestImageConvert(t *testing.T) { + nerdtest.Setup() - base := testutil.NewBase(t) - t.Parallel() + testCase := &test.Case{ + Description: "Test image conversion", + Require: test.Require( + test.Not(test.Windows), + test.Not(nerdtest.Docker), + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + }, + SubTests: []*test.Case{ + { + Description: "esgz", + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier("converted-image")) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("image", "convert", "--oci", "--estargz", + testutil.CommonImage, data.Identifier("converted-image")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "nydus", + Require: test.Require( + test.Binary("nydus-image"), + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier("converted-image")) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("image", "convert", "--oci", "--nydus", + testutil.CommonImage, data.Identifier("converted-image")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "zstd", + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier("converted-image")) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("image", "convert", "--oci", "--zstd", "--zstd-compression-level", "3", + testutil.CommonImage, data.Identifier("converted-image")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "zstdchunked", + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier("converted-image")) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("image", "convert", "--oci", "--zstdchunked", "--zstdchunked-compression-level", "3", + testutil.CommonImage, data.Identifier("converted-image")) + }, + Expected: test.Expects(0, nil, nil), + }, + }, + } - convertedImage := testutil.Identifier(t) + ":nydus" - base.Cmd("rmi", convertedImage).Run() - base.Cmd("pull", testutil.CommonImage).AssertOK() - base.Cmd("image", "convert", "--nydus", "--oci", - testutil.CommonImage, convertedImage).AssertOK() - defer base.Cmd("rmi", convertedImage).Run() + testCase.Run(t) - // use `nydusify` check whether the convertd nydus image is valid +} - // skip if rootless - if rootlessutil.IsRootless() { - t.Skip("Nydusify check is not supported rootless mode.") - } +func TestImageConvertNydusVerify(t *testing.T) { + nerdtest.Setup() - // skip if nydusify and nydusd are not installed - testutil.RequireExecutable(t, "nydusify") - testutil.RequireExecutable(t, "nydusd") + const remoteImageKey = "remoteImageKey" - // setup local docker registry - registry := testregistry.NewWithNoAuth(base, 0, false) - remoteImage := fmt.Sprintf("%s:%d/nydusd-image:test", "localhost", registry.Port) - t.Cleanup(func() { - base.Cmd("rmi", remoteImage).Run() - registry.Cleanup(nil) - }) + var registry *testregistry.RegistryServer - base.Cmd("tag", convertedImage, remoteImage).AssertOK() - base.Cmd("push", remoteImage).AssertOK() - nydusifyCmd := testutil.Cmd{ - Cmd: icmd.Command( - "nydusify", - "check", - "--source", - testutil.CommonImage, - "--target", - remoteImage, - "--source-insecure", - "--target-insecure", + testCase := &test.Case{ + Description: "TestImageConvertNydusVerify", + Require: test.Require( + test.Linux, + test.Binary("nydus-image"), + test.Binary("nydusify"), + test.Binary("nydusd"), + test.Not(nerdtest.Docker), + nerdtest.RootFul, ), - Base: base, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + base := testutil.NewBase(t) + registry = testregistry.NewWithNoAuth(base, 0, false) + data.Set(remoteImageKey, fmt.Sprintf("%s:%d/nydusd-image:test", "localhost", registry.Port)) + helpers.Ensure("image", "convert", "--nydus", "--oci", testutil.CommonImage, data.Identifier("converted-image")) + helpers.Ensure("tag", data.Identifier("converted-image"), data.Get(remoteImageKey)) + helpers.Ensure("push", data.Get(remoteImageKey)) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier("converted-image")) + if registry != nil { + registry.Cleanup(nil) + helpers.Anyhow("rmi", data.Get(remoteImageKey)) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("nydusify", + "check", + "--source", + testutil.CommonImage, + "--target", + data.Get(remoteImageKey), + "--source-insecure", + "--target-insecure", + ) + }, + Expected: test.Expects(0, nil, nil), } - // nydus is creating temporary files - make sure we are in a proper location for that - nydusifyCmd.Cmd.Dir = base.T.TempDir() - nydusifyCmd.AssertOK() + testCase.Run(t) } diff --git a/cmd/nerdctl/image/image_convert_test.go b/cmd/nerdctl/image/image_convert_test.go deleted file mode 100644 index ca5780597d3..00000000000 --- a/cmd/nerdctl/image/image_convert_test.go +++ /dev/null @@ -1,70 +0,0 @@ -/* - 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 image - -import ( - "runtime" - "testing" - - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestImageConvert(t *testing.T) { - if runtime.GOOS == "windows" { - t.Skip("no windows support yet") - } - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - t.Parallel() - - base.Cmd("pull", testutil.CommonImage).AssertOK() - - testCases := []struct { - identifier string - args []string - }{ - { - "esgz", - []string{"--estargz"}, - }, - { - "zstd", - []string{"--zstd", "--zstd-compression-level", "3"}, - }, - { - "zstdchunked", - []string{"--zstdchunked", "--zstdchunked-compression-level", "3"}, - }, - } - - for _, tc := range testCases { - convertedImage := testutil.Identifier(t) + ":" + tc.identifier - args := append([]string{"image", "convert", "--oci"}, tc.args...) - args = append(args, testutil.CommonImage, convertedImage) - - t.Run(tc.identifier, func(t *testing.T) { - t.Parallel() - - base.Cmd("rmi", convertedImage).Run() - t.Cleanup(func() { - base.Cmd("rmi", convertedImage).Run() - }) - - base.Cmd(args...).AssertOK() - }) - } -} diff --git a/cmd/nerdctl/image/image_encrypt_linux_test.go b/cmd/nerdctl/image/image_encrypt_linux_test.go index 80ff117c007..136e03cdd95 100644 --- a/cmd/nerdctl/image/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image/image_encrypt_linux_test.go @@ -18,39 +18,65 @@ package image import ( "fmt" + "strings" "testing" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "gotest.tools/v3/assert" + + testhelpers "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) func TestImageEncryptJWE(t *testing.T) { - testutil.RequiresBuild(t) - testutil.DockerIncompatible(t) - keyPair := helpers.NewJWEKeyPair(t) - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - reg := testregistry.NewWithNoAuth(base, 0, false) - - defer keyPair.Cleanup() - defer reg.Cleanup(nil) - - base.Cmd("pull", testutil.CommonImage).AssertOK() - encryptImageRef := fmt.Sprintf("127.0.0.1:%d/%s:encrypted", reg.Port, tID) - base.Cmd("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, testutil.CommonImage, encryptImageRef).AssertOK() - base.Cmd("image", "inspect", "--mode=native", "--format={{len .Index.Manifests}}", encryptImageRef).AssertOutExactly("1\n") - base.Cmd("image", "inspect", "--mode=native", "--format={{json .Manifest.Layers}}", encryptImageRef).AssertOutContains("org.opencontainers.image.enc.keys.jwe") - base.Cmd("push", encryptImageRef).AssertOK() - - defer base.Cmd("rmi", encryptImageRef).Run() - - // remove all local images (in the nerdctl-test namespace), to ensure that we do not have blobs of the original image. - helpers.RmiAll(base) - base.Cmd("pull", encryptImageRef).AssertFail() // defaults to --unpack=true, and fails due to missing prv key - base.Cmd("pull", "--unpack=false", encryptImageRef).AssertOK() - decryptImageRef := tID + ":decrypted" - defer base.Cmd("rmi", decryptImageRef).Run() - base.Cmd("image", "decrypt", "--key="+keyPair.Pub, encryptImageRef, decryptImageRef).AssertFail() // decryption needs prv key, not pub key - base.Cmd("image", "decrypt", "--key="+keyPair.Prv, encryptImageRef, decryptImageRef).AssertOK() + nerdtest.Setup() + + var registry *testregistry.RegistryServer + var keyPair *testhelpers.JweKeyPair + + const remoteImageKey = "remoteImageKey" + + testCase := &test.Case{ + Require: test.Require( + test.Linux, + test.Not(nerdtest.Docker), + // This test needs to rmi the common image + nerdtest.Private, + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + if registry != nil { + registry.Cleanup(nil) + keyPair.Cleanup() + helpers.Anyhow("rmi", "-f", data.Get(remoteImageKey)) + } + helpers.Anyhow("rmi", "-f", data.Identifier("decrypted")) + }, + Setup: func(data test.Data, helpers test.Helpers) { + base := testutil.NewBase(t) + registry = testregistry.NewWithNoAuth(base, 0, false) + keyPair = testhelpers.NewJWEKeyPair(t) + helpers.Ensure("pull", testutil.CommonImage) + encryptImageRef := fmt.Sprintf("127.0.0.1:%d/%s:encrypted", registry.Port, data.Identifier()) + helpers.Ensure("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, testutil.CommonImage, encryptImageRef) + inspector := helpers.Capture("image", "inspect", "--mode=native", "--format={{len .Index.Manifests}}", encryptImageRef) + assert.Equal(t, inspector, "1\n") + inspector = helpers.Capture("image", "inspect", "--mode=native", "--format={{json .Manifest.Layers}}", encryptImageRef) + assert.Assert(t, strings.Contains(inspector, "org.opencontainers.image.enc.keys.jwe")) + helpers.Ensure("push", encryptImageRef) + helpers.Anyhow("rmi", "-f", encryptImageRef) + helpers.Anyhow("rmi", "-f", testutil.CommonImage) + data.Set(remoteImageKey, encryptImageRef) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + helpers.Fail("pull", data.Get(remoteImageKey)) + helpers.Ensure("pull", "--unpack=false", data.Get(remoteImageKey)) + helpers.Fail("image", "decrypt", "--key="+keyPair.Pub, data.Get(remoteImageKey), data.Identifier("decrypted")) // decryption needs prv key, not pub key + return helpers.Command("image", "decrypt", "--key="+keyPair.Prv, data.Get(remoteImageKey), data.Identifier("decrypted")) + }, + Expected: test.Expects(0, nil, nil), + } + + testCase.Run(t) } diff --git a/cmd/nerdctl/image/image_history_test.go b/cmd/nerdctl/image/image_history_test.go index 21bef4f5692..9f05785291c 100644 --- a/cmd/nerdctl/image/image_history_test.go +++ b/cmd/nerdctl/image/image_history_test.go @@ -18,9 +18,8 @@ package image import ( "encoding/json" - "fmt" + "errors" "io" - "runtime" "strings" "testing" "time" @@ -28,6 +27,8 @@ import ( "gotest.tools/v3/assert" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) type historyObj struct { @@ -39,53 +40,20 @@ type historyObj struct { Comment string } -func imageHistoryJSONHelper(base *testutil.Base, reference string, noTrunc bool, quiet bool, human bool) []historyObj { - cmd := []string{"image", "history"} - if noTrunc { - cmd = append(cmd, "--no-trunc") - } - if quiet { - cmd = append(cmd, "--quiet") - } - cmd = append(cmd, fmt.Sprintf("--human=%t", human)) - cmd = append(cmd, "--format", "json") - cmd = append(cmd, reference) - - cmdResult := base.Cmd(cmd...).Run() - assert.Equal(base.T, cmdResult.ExitCode, 0, cmdResult.Stdout()) - - fmt.Println(cmdResult.Stderr()) - - dec := json.NewDecoder(strings.NewReader(cmdResult.Stdout())) +func decode(stdout string) ([]historyObj, error) { + dec := json.NewDecoder(strings.NewReader(stdout)) object := []historyObj{} for { var v historyObj if err := dec.Decode(&v); err == io.EOF { break } else if err != nil { - base.T.Fatal(err) + return nil, errors.New("failed to decode history object") } object = append(object, v) } - return object -} - -func imageHistoryRawHelper(base *testutil.Base, reference string, noTrunc bool, quiet bool, human bool) string { - cmd := []string{"image", "history"} - if noTrunc { - cmd = append(cmd, "--no-trunc") - } - if quiet { - cmd = append(cmd, "--quiet") - } - cmd = append(cmd, fmt.Sprintf("--human=%t", human)) - cmd = append(cmd, reference) - - cmdResult := base.Cmd(cmd...).Run() - assert.Equal(base.T, cmdResult.ExitCode, 0, cmdResult.Stdout()) - - return cmdResult.Stdout() + return object, nil } func TestImageHistory(t *testing.T) { @@ -97,69 +65,91 @@ func TestImageHistory(t *testing.T) { // possibly one is unpacked on the filessystem while the other is the tar file size? // - we do not truncate ids when --quiet has been provided // this is a conscious decision here - truncating with --quiet does not make much sense - testutil.DockerIncompatible(t) - - base := testutil.NewBase(t) - - // XXX the results here are obviously platform dependent - and it seems like windows cannot pull a linux image? - // Disabling for now - if runtime.GOOS == "windows" { - t.Skip("Windows is not supported for this test right now") - } - // XXX Currently, history does not work on non-native platform, so, we cannot test reliably on other platforms - if runtime.GOARCH != "arm64" { - t.Skip("Windows is not supported for this test right now") + nerdtest.Setup() + + testCase := &test.Case{ + Require: test.Require( + test.Not(nerdtest.Docker), + // XXX the results here are obviously platform dependent - and it seems like windows cannot pull a linux image? + test.Not(test.Windows), + // XXX Currently, history does not work on non-native platform, so, we cannot test reliably on other platforms + test.Arm64, + ), + Setup: func(data test.Data, helpers test.Helpers) { + // XXX: despite efforts to isolate this test, it keeps on having side effects linked to + // https://github.com/containerd/nerdctl/issues/3512 + // Isolating it into a completely different root is the last ditched attempt at avoiding the issue + helpers.Write(nerdtest.DataRoot, test.ConfigValue(data.TempDir())) + helpers.Ensure("pull", "--platform", "linux/arm64", testutil.CommonImage) + }, + SubTests: []*test.Case{ + { + Description: "trunc, no quiet, human", + Command: test.Command("image", "history", "--human=true", "--format=json", testutil.CommonImage), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + history, err := decode(stdout) + assert.NilError(t, err, info) + assert.Equal(t, len(history), 2, info) + assert.Equal(t, history[0].Size, "0B", info) + // FIXME: how is this going to age? + assert.Equal(t, history[0].CreatedSince, "3 years ago", info) + assert.Equal(t, history[0].Snapshot, "", info) + assert.Equal(t, history[0].Comment, "", info) + + localTimeL1, _ := time.Parse(time.RFC3339, "2021-03-31T10:21:23-07:00") + localTimeL2, _ := time.Parse(time.RFC3339, "2021-03-31T10:21:21-07:00") + compTime1, _ := time.Parse(time.RFC3339, history[0].CreatedAt) + compTime2, _ := time.Parse(time.RFC3339, history[1].CreatedAt) + assert.Equal(t, compTime1.UTC().String(), localTimeL1.UTC().String(), info) + assert.Equal(t, history[0].CreatedBy, "/bin/sh -c #(nop) CMD [\"/bin/sh\"]", info) + assert.Equal(t, compTime2.UTC().String(), localTimeL2.UTC().String(), info) + assert.Equal(t, history[1].CreatedBy, "/bin/sh -c #(nop) ADD file:3b16ffee2b26d8af5…", info) + + assert.Equal(t, history[1].Size, "5.947MB", info) + assert.Equal(t, history[1].CreatedSince, "3 years ago", info) + assert.Equal(t, history[1].Snapshot, "sha256:56bf55b8eed1f0b4794a30386e4d1d3da949c…", info) + assert.Equal(t, history[1].Comment, "", info) + }), + }, + { + Description: "no human - dates and sizes and not prettyfied", + Command: test.Command("image", "history", "--human=false", "--format=json", testutil.CommonImage), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + history, err := decode(stdout) + assert.NilError(t, err, info) + assert.Equal(t, history[0].Size, "0", info) + assert.Equal(t, history[0].CreatedSince, history[0].CreatedAt, info) + assert.Equal(t, history[1].Size, "5947392", info) + assert.Equal(t, history[1].CreatedSince, history[1].CreatedAt, info) + }), + }, + { + Description: "no trunc - do not truncate sha or cmd", + Command: test.Command("image", "history", "--human=false", "--no-trunc", "--format=json", testutil.CommonImage), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + history, err := decode(stdout) + assert.NilError(t, err, info) + assert.Equal(t, history[1].Snapshot, "sha256:56bf55b8eed1f0b4794a30386e4d1d3da949c25bcb5155e898097cd75dc77c2a") + assert.Equal(t, history[1].CreatedBy, "/bin/sh -c #(nop) ADD file:3b16ffee2b26d8af5db152fcc582aaccd9e1ec9e3343874e9969a205550fe07d in / ") + }), + }, + { + Description: "Quiet has no effect with format, so, go no-json, no-trunc", + Command: test.Command("image", "history", "--human=false", "--no-trunc", "--quiet", testutil.CommonImage), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + assert.Equal(t, stdout, "\nsha256:56bf55b8eed1f0b4794a30386e4d1d3da949c25bcb5155e898097cd75dc77c2a\n") + }), + }, + { + Description: "With quiet, trunc has no effect", + Command: test.Command("image", "history", "--human=false", "--no-trunc", "--quiet", testutil.CommonImage), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + assert.Equal(t, stdout, "\nsha256:56bf55b8eed1f0b4794a30386e4d1d3da949c25bcb5155e898097cd75dc77c2a\n") + }), + }, + }, } - base.Cmd("pull", "--platform", "linux/arm64", testutil.CommonImage).AssertOK() - - localTimeL1, _ := time.Parse(time.RFC3339, "2021-03-31T10:21:23-07:00") - localTimeL2, _ := time.Parse(time.RFC3339, "2021-03-31T10:21:21-07:00") - - // Human, no quiet, truncate - history := imageHistoryJSONHelper(base, testutil.CommonImage, false, false, true) - compTime1, _ := time.Parse(time.RFC3339, history[0].CreatedAt) - compTime2, _ := time.Parse(time.RFC3339, history[1].CreatedAt) - - // Two layers - assert.Equal(base.T, len(history), 2) - // First layer is a comment - zero size, no snap, - assert.Equal(base.T, history[0].Size, "0B") - assert.Equal(base.T, history[0].CreatedSince, "3 years ago") - assert.Equal(base.T, history[0].Snapshot, "") - assert.Equal(base.T, history[0].Comment, "") - - assert.Equal(base.T, compTime1.UTC().String(), localTimeL1.UTC().String()) - assert.Equal(base.T, history[0].CreatedBy, "/bin/sh -c #(nop) CMD [\"/bin/sh\"]") - - assert.Equal(base.T, compTime2.UTC().String(), localTimeL2.UTC().String()) - assert.Equal(base.T, history[1].CreatedBy, "/bin/sh -c #(nop) ADD file:3b16ffee2b26d8af5…") - - assert.Equal(base.T, history[1].Size, "5.947MB") - assert.Equal(base.T, history[1].CreatedSince, "3 years ago") - assert.Equal(base.T, history[1].Snapshot, "sha256:56bf55b8eed1f0b4794a30386e4d1d3da949c…") - assert.Equal(base.T, history[1].Comment, "") - - // No human - dates and sizes and not prettyfied - history = imageHistoryJSONHelper(base, testutil.CommonImage, false, false, false) - - assert.Equal(base.T, history[0].Size, "0") - assert.Equal(base.T, history[0].CreatedSince, history[0].CreatedAt) - - assert.Equal(base.T, history[1].Size, "5947392") - assert.Equal(base.T, history[1].CreatedSince, history[1].CreatedAt) - - // No trunc - do not truncate sha or cmd - history = imageHistoryJSONHelper(base, testutil.CommonImage, true, false, true) - assert.Equal(base.T, history[1].Snapshot, "sha256:56bf55b8eed1f0b4794a30386e4d1d3da949c25bcb5155e898097cd75dc77c2a") - assert.Equal(base.T, history[1].CreatedBy, "/bin/sh -c #(nop) ADD file:3b16ffee2b26d8af5db152fcc582aaccd9e1ec9e3343874e9969a205550fe07d in / ") - - // Quiet has no effect with format, so, go no-json, no-trunc - rawHistory := imageHistoryRawHelper(base, testutil.CommonImage, true, true, true) - assert.Equal(base.T, rawHistory, "\nsha256:56bf55b8eed1f0b4794a30386e4d1d3da949c25bcb5155e898097cd75dc77c2a\n") - - // With quiet, trunc has no effect - rawHistory = imageHistoryRawHelper(base, testutil.CommonImage, false, true, true) - assert.Equal(base.T, rawHistory, "\nsha256:56bf55b8eed1f0b4794a30386e4d1d3da949c25bcb5155e898097cd75dc77c2a\n") + testCase.Run(t) } diff --git a/cmd/nerdctl/image/image_inspect_test.go b/cmd/nerdctl/image/image_inspect_test.go index 5a0f7111a28..93278de9294 100644 --- a/cmd/nerdctl/image/image_inspect_test.go +++ b/cmd/nerdctl/image/image_inspect_test.go @@ -40,7 +40,7 @@ func TestImageInspectSimpleCases(t *testing.T) { SubTests: []*test.Case{ { Description: "Contains some stuff", - Command: test.RunCommand("image", "inspect", testutil.CommonImage), + Command: test.Command("image", "inspect", testutil.CommonImage), Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { var dc []dockercompat.Image err := json.Unmarshal([]byte(stdout), &dc) @@ -53,12 +53,12 @@ func TestImageInspectSimpleCases(t *testing.T) { }, { Description: "RawFormat support (.Id)", - Command: test.RunCommand("image", "inspect", testutil.CommonImage, "--format", "{{.Id}}"), + Command: test.Command("image", "inspect", testutil.CommonImage, "--format", "{{.Id}}"), Expected: test.Expects(0, nil, nil), }, { Description: "typedFormat support (.ID)", - Command: test.RunCommand("image", "inspect", testutil.CommonImage, "--format", "{{.ID}}"), + Command: test.Command("image", "inspect", testutil.CommonImage, "--format", "{{.ID}}"), Expected: test.Expects(0, nil, nil), }, }, @@ -81,7 +81,6 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { } testCase := &test.Case{ - Description: "TestImageInspectDifferentValidReferencesForTheSameImage", Require: test.Require( test.Not(nerdtest.Docker), test.Not(test.Windows), @@ -96,7 +95,7 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { SubTests: []*test.Case{ { Description: "name and tags +/- sha combinations", - Command: test.RunCommand("image", "inspect", "busybox"), + Command: test.Command("image", "inspect", "busybox"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: func(stdout string, info string, t *testing.T) { @@ -121,7 +120,7 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { }, { Description: "by digest, short or long, with or without prefix", - Command: test.RunCommand("image", "inspect", "busybox"), + Command: test.Command("image", "inspect", "busybox"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: func(stdout string, info string, t *testing.T) { @@ -154,7 +153,7 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { }, { Description: "prove that wrong references with correct digest do not get resolved", - Command: test.RunCommand("image", "inspect", "busybox"), + Command: test.Command("image", "inspect", "busybox"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: func(stdout string, info string, t *testing.T) { @@ -176,7 +175,7 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { }, { Description: "prove that invalid reference return no result without crashing", - Command: test.RunCommand("image", "inspect", "busybox"), + Command: test.Command("image", "inspect", "busybox"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: func(stdout string, info string, t *testing.T) { @@ -197,7 +196,7 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { }, { Description: "retrieving multiple entries at once", - Command: test.RunCommand("image", "inspect", "busybox", "busybox"), + Command: test.Command("image", "inspect", "busybox", "busybox"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ Output: func(stdout string, info string, t *testing.T) { diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index 3b3772fe292..76e1095a081 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -24,143 +24,290 @@ import ( "gotest.tools/v3/assert" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + testhelpers "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/tabutil" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func TestImagesWithNames(t *testing.T) { - t.Parallel() - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - - base.Cmd("pull", testutil.CommonImage).AssertOK() - base.Cmd("images", "--names", testutil.CommonImage).AssertOutContains(testutil.CommonImage) - base.Cmd("images", "--names", testutil.CommonImage).AssertOutWithFunc(func(out string) error { - lines := strings.Split(strings.TrimSpace(out), "\n") - if len(lines) < 2 { - return fmt.Errorf("expected at least 2 lines, got %d", len(lines)) - } - tab := tabutil.NewReader("NAME\tIMAGE ID\tCREATED\tPLATFORM\tSIZE\tBLOB SIZE") - err := tab.ParseHeader(lines[0]) - if err != nil { - return fmt.Errorf("failed to parse header: %v", err) - } - name, _ := tab.ReadRow(lines[1], "NAME") - assert.Equal(t, name, testutil.CommonImage) - return nil - }) -} - func TestImages(t *testing.T) { - t.Parallel() - base := testutil.NewBase(t) - header := "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tPLATFORM\tSIZE\tBLOB SIZE" - if base.Target == testutil.Docker { - header = "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tSIZE" + nerdtest.Setup() + + testCase := &test.Case{ + Description: "TestImages", + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", testutil.NginxAlpineImage) + }, + SubTests: []*test.Case{ + { + Description: "No params", + Command: test.Command("images"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 2, info) + header := "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tPLATFORM\tSIZE\tBLOB SIZE" + if nerdtest.IsDocker() { + header = "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tSIZE" + } + tab := tabutil.NewReader(header) + err := tab.ParseHeader(lines[0]) + assert.NilError(t, err, info) + found := false + for _, line := range lines[1:] { + repo, _ := tab.ReadRow(line, "REPOSITORY") + tag, _ := tab.ReadRow(line, "TAG") + if repo+":"+tag == testutil.CommonImage { + found = true + break + } + } + assert.Assert(t, found, info) + }, + } + }, + }, + { + Description: "With names", + Command: test.Command("images", "--names", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(testutil.CommonImage), + func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 2, info) + tab := tabutil.NewReader("NAME\tIMAGE ID\tCREATED\tPLATFORM\tSIZE\tBLOB SIZE") + err := tab.ParseHeader(lines[0]) + assert.NilError(t, err, info) + found := false + for _, line := range lines[1:] { + name, _ := tab.ReadRow(line, "NAME") + if name == testutil.CommonImage { + found = true + break + } + } + + assert.Assert(t, found, info) + }, + ), + } + }, + }, + { + Description: "CheckCreatedTime", + Command: test.Command("images", "--format", "'{{json .CreatedAt}}'"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) >= 2, info) + createdTimes := lines + slices.Reverse(createdTimes) + assert.Assert(t, slices.IsSorted(createdTimes), info) + }, + } + }, + }, + }, } - base.Cmd("pull", testutil.CommonImage).AssertOK() - base.Cmd("images", testutil.CommonImage).AssertOutWithFunc(func(out string) error { - lines := strings.Split(strings.TrimSpace(out), "\n") - if len(lines) < 2 { - return fmt.Errorf("expected at least 2 lines, got %d", len(lines)) - } - tab := tabutil.NewReader(header) - err := tab.ParseHeader(lines[0]) - if err != nil { - return fmt.Errorf("failed to parse header: %v", err) - } - repo, _ := tab.ReadRow(lines[1], "REPOSITORY") - tag, _ := tab.ReadRow(lines[1], "TAG") - assert.Equal(t, repo+":"+tag, testutil.CommonImage) - return nil - }) + testCase.Run(t) } func TestImagesFilter(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - t.Parallel() - base := testutil.NewBase(t) - tempName := testutil.Identifier(base.T) - base.Cmd("pull", testutil.CommonImage).AssertOK() - - dockerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Description: "TestImagesFilter", + Require: nerdtest.Build, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("tag", testutil.CommonImage, "taggedimage:one-fragment-one") + helpers.Ensure("tag", testutil.CommonImage, "taggedimage:two-fragment-two") + + dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-test-string"] \n LABEL foo=bar -LABEL version=0.1`, testutil.CommonImage) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - base.Cmd("build", "-t", tempName, "-f", buildCtx+"/Dockerfile", buildCtx).AssertOK() - defer base.Cmd("rmi", tempName).AssertOK() - - // This test is about testing local filtering of image names - as such, we do not need remote images at all - taggedOne, taggedTwo := "taggedimage:xfoox", "taggedimage:yzfooyz" - base.Cmd("tag", testutil.CommonImage, taggedOne).Run() - base.Cmd("tag", testutil.CommonImage, taggedTwo).Run() - defer base.Cmd("rmi", taggedOne).AssertOK() - defer base.Cmd("rmi", taggedTwo).AssertOK() - - // before/since filters are not compatible with DOCKER_BUILDKIT=1? (but still compatible with DOCKER_BUILDKIT=0) - if base.Target == testutil.Nerdctl { - base.Cmd("images", "--filter", fmt.Sprintf("before=%s:%s", tempName, "latest")).AssertOutContains(testutil.ImageRepo(testutil.CommonImage)) - base.Cmd("images", "--filter", fmt.Sprintf("before=%s:%s", tempName, "latest")).AssertOutNotContains(tempName) - base.Cmd("images", "--filter", fmt.Sprintf("since=%s", testutil.CommonImage)).AssertOutContains(tempName) - base.Cmd("images", "--filter", fmt.Sprintf("since=%s", testutil.CommonImage)).AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) - base.Cmd("images", "--filter", fmt.Sprintf("since=%s", testutil.CommonImage), testutil.CommonImage).AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) - base.Cmd("images", "--filter", fmt.Sprintf("since=%s", testutil.CommonImage), testutil.CommonImage).AssertOutNotContains(tempName) - base.Cmd("images", "--filter", fmt.Sprintf("since=%s:%s", "non-exists-image", "non-exists-image")).AssertOutContains(tempName) - base.Cmd("images", "--filter", fmt.Sprintf("before=%s:%s", "non-exists-image", "non-exists-image")).AssertOutContains(tempName) +LABEL version=0.1 +RUN echo "actually creating a layer so that docker sets the createdAt time" +`, testutil.CommonImage) + buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + data.Set("buildCtx", buildCtx) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "taggedimage:one-fragment-one") + helpers.Anyhow("rmi", "taggedimage:two-fragment-two") + helpers.Anyhow("rmi", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + data.Set("builtImageID", data.Identifier()) + return helpers.Command("build", "-t", data.Identifier(), data.Get("buildCtx")) + }, + Expected: test.Expects(0, nil, nil), + SubTests: []*test.Case{ + { + Description: "label=foo=bar", + Command: test.Command("images", "--filter", "label=foo=bar"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("builtImageID")), + } + }, + }, + { + Description: "label=foo=bar1", + Command: test.Command("images", "--filter", "label=foo=bar1"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.DoesNotContain(data.Get("builtImageID")), + } + }, + }, + { + Description: "label=foo=bar label=version=0.1", + Command: test.Command("images", "--filter", "label=foo=bar", "--filter", "label=version=0.1"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("builtImageID")), + } + }, + }, + { + Description: "label=foo=bar label=version=0.1", + Command: test.Command("images", "--filter", "label=foo=bar", "--filter", "label=version=0.2"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.DoesNotContain(data.Get("builtImageID")), + } + }, + }, + { + Description: "label=version", + Require: nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3512"), + Command: test.Command("images", "--filter", "label=version"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("builtImageID")), + } + }, + }, + { + Description: "reference=ID*", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("images", "--filter", fmt.Sprintf("reference=%s*", data.Get("builtImageID"))) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("builtImageID")), + } + }, + }, + { + Description: "reference=tagged*:*fragment*", + Command: test.Command("images", "--filter", "reference=tagged*:*fragment*"), + Expected: test.Expects(0, nil, test.All( + test.Contains("one-"), + test.Contains("two-"), + )), + }, + { + Description: "before=ID:latest", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("images", "--filter", fmt.Sprintf("before=%s:latest", data.Get("builtImageID"))) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(testutil.ImageRepo(testutil.CommonImage)), + test.DoesNotContain(data.Get("builtImageID")), + ), + } + }, + }, + { + Description: "since=" + testutil.CommonImage, + Command: test.Command("images", "--filter", fmt.Sprintf("since=%s", testutil.CommonImage)), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(data.Get("builtImageID")), + test.DoesNotContain(testutil.ImageRepo(testutil.CommonImage)), + ), + } + }, + }, + { + Description: "since=" + testutil.CommonImage + " " + testutil.CommonImage, + Command: test.Command("images", "--filter", fmt.Sprintf("since=%s", testutil.CommonImage), testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain(data.Get("builtImageID")), + test.DoesNotContain(testutil.ImageRepo(testutil.CommonImage)), + ), + } + }, + }, + { + Description: "since=non-exists-image", + Require: nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3511"), + Command: test.Command("images", "--filter", "since=non-exists-image"), + Expected: test.Expects(-1, nil, nil), + }, + { + Description: "before=non-exists-image", + Require: nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3511"), + Command: test.Command("images", "--filter", "before=non-exists-image"), + Expected: test.Expects(-1, nil, nil), + }, + }, } - base.Cmd("images", "--filter", "label=foo=bar").AssertOutContains(tempName) - base.Cmd("images", "--filter", "label=foo=bar1").AssertOutNotContains(tempName) - base.Cmd("images", "--filter", "label=foo=bar", "--filter", "label=version=0.1").AssertOutContains(tempName) - base.Cmd("images", "--filter", "label=foo=bar", "--filter", "label=version=0.2").AssertOutNotContains(tempName) - base.Cmd("images", "--filter", "label=version").AssertOutContains(tempName) - base.Cmd("images", "--filter", fmt.Sprintf("reference=%s*", tempName)).AssertOutContains(tempName) - base.Cmd("images", "--filter", "reference=tag*:*foo*").AssertOutContains("xfoox") - base.Cmd("images", "--filter", "reference=tag*:*foo*").AssertOutContains("yzfooyz") + + testCase.Run(t) } func TestImagesFilterDangling(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - base.Cmd("container", "prune", "-f").AssertOK() - base.Cmd("image", "prune", "--all", "-f").AssertOK() + nerdtest.Setup() - dockerfile := fmt.Sprintf(`FROM %s + testCase := &test.Case{ + Description: "TestImagesFilterDangling", + // This test relies on a clean slate and the ability to GC everything + NoParallel: true, + Require: nerdtest.Build, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-notag-string"] `, testutil.CommonImage) - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", "-f", buildCtx+"/Dockerfile", buildCtx).AssertOK() - - // dangling image test - base.Cmd("images", "--filter", "dangling=true").AssertOutContains("") - base.Cmd("images", "--filter", "dangling=false").AssertOutNotContains("") -} - -func TestImageListCheckCreatedTime(t *testing.T) { - base := testutil.NewBase(t) - - base.Cmd("pull", testutil.CommonImage).AssertOK() - base.Cmd("pull", testutil.NginxAlpineImage).AssertOK() - - var createdTimes []string - - base.Cmd("images", "--format", "'{{json .CreatedAt}}'").AssertOutWithFunc(func(stdout string) error { - lines := strings.Split(strings.TrimSpace(stdout), "\n") - if len(lines) < 2 { - return fmt.Errorf("expected at least 4 lines, got %d", len(lines)) - } - createdTimes = append(createdTimes, lines...) - return nil - }) - - slices.Reverse(createdTimes) - if !slices.IsSorted(createdTimes) { - t.Errorf("expected images in decending order") + buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + data.Set("buildCtx", buildCtx) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("container", "prune", "-f") + helpers.Anyhow("image", "prune", "--all", "-f") + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", data.Get("buildCtx")) + }, + Expected: test.Expects(0, nil, nil), + SubTests: []*test.Case{ + { + Description: "dangling", + Command: test.Command("images", "--filter", "dangling=true"), + Expected: test.Expects(0, nil, test.Contains("")), + }, + { + Description: "not dangling", + Command: test.Command("images", "--filter", "dangling=false"), + Expected: test.Expects(0, nil, test.DoesNotContain("")), + }, + }, } + + testCase.Run(t) } diff --git a/cmd/nerdctl/image/image_load_linux_test.go b/cmd/nerdctl/image/image_load_linux_test.go deleted file mode 100644 index 4d7b0f83dce..00000000000 --- a/cmd/nerdctl/image/image_load_linux_test.go +++ /dev/null @@ -1,70 +0,0 @@ -/* - 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 image - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "strings" - "testing" - - "gotest.tools/v3/assert" - - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestLoadStdinFromPipe(t *testing.T) { - t.Parallel() - base := testutil.NewBase(t) - img := testutil.Identifier(t) - tmp := t.TempDir() - output := filepath.Join(tmp, "output") - - setup := func() { - base.Cmd("pull", testutil.CommonImage).AssertOK() - base.Cmd("tag", testutil.CommonImage, img).AssertOK() - base.Cmd("save", img, "-o", filepath.Join(tmp, "common.tar")).AssertOK() - base.Cmd("rmi", "-f", img).AssertOK() - } - - tearDown := func() { - base.Cmd("rmi", "-f", img).AssertOK() - } - - t.Cleanup(tearDown) - tearDown() - - setup() - - loadCmd := strings.Join(base.Cmd("load").Command, " ") - combined, err := exec.Command("sh", "-euxc", fmt.Sprintf("`cat %s/common.tar | %s > %s`", tmp, loadCmd, output)).CombinedOutput() - assert.NilError(t, err, "failed with error %s and combined output is %s", err, string(combined)) - - fb, err := os.ReadFile(output) - assert.NilError(t, err) - - assert.Assert(t, strings.Contains(string(fb), fmt.Sprintf("Loaded image: %s:latest", img))) - base.Cmd("images").AssertOutContains(img) -} - -func TestLoadStdinEmpty(t *testing.T) { - t.Parallel() - base := testutil.NewBase(t) - base.Cmd("load").AssertFail() -} diff --git a/cmd/nerdctl/image/image_load_test.go b/cmd/nerdctl/image/image_load_test.go new file mode 100644 index 00000000000..97f31c04b6e --- /dev/null +++ b/cmd/nerdctl/image/image_load_test.go @@ -0,0 +1,81 @@ +/* + 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 image + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestLoadStdinFromPipe(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Description: "TestLoadStdinFromPipe", + Require: test.Linux, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("tag", testutil.CommonImage, data.Identifier()) + helpers.Ensure("save", data.Identifier(), "-o", filepath.Join(data.TempDir(), "common.tar")) + helpers.Ensure("rmi", "-f", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command("load") + reader, err := os.Open(filepath.Join(data.TempDir(), "common.tar")) + assert.NilError(t, err, "failed to open common.tar") + cmd.WithStdin(reader) + return cmd + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(fmt.Sprintf("Loaded image: %s:latest", data.Identifier())), + func(stdout string, info string, t *testing.T) { + assert.Assert(t, strings.Contains(helpers.Capture("images"), data.Identifier())) + }, + ), + } + }, + } + + testCase.Run(t) +} + +func TestLoadStdinEmpty(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Description: "TestLoadStdinEmpty", + Require: test.Linux, + Command: test.Command("load"), + Expected: test.Expects(1, nil, nil), + } + + testCase.Run(t) +} diff --git a/cmd/nerdctl/image/image_prune_test.go b/cmd/nerdctl/image/image_prune_test.go index 94ef0c625f2..c6534253698 100644 --- a/cmd/nerdctl/image/image_prune_test.go +++ b/cmd/nerdctl/image/image_prune_test.go @@ -18,117 +18,212 @@ package image import ( "fmt" + "strings" "testing" "time" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "gotest.tools/v3/assert" + + testhelpers "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestImagePrune(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).AssertOK() - - dockerfile := fmt.Sprintf(`FROM %s - CMD ["echo", "nerdctl-test-image-prune"]`, testutil.CommonImage) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", buildCtx).AssertOK() - base.Cmd("build", "-t", imageName, buildCtx).AssertOK() - base.Cmd("images").AssertOutContainsAll(imageName, "") - - base.Cmd("image", "prune", "--force").AssertOutNotContains(imageName) - base.Cmd("images").AssertOutNotContains("") - base.Cmd("images").AssertOutContains(imageName) -} - -func TestImagePruneAll(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - - dockerfile := fmt.Sprintf(`FROM %s - CMD ["echo", "nerdctl-test-image-prune"]`, testutil.CommonImage) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", "-t", imageName, buildCtx).AssertOK() - // The following commands will clean up all images, so it should fail at this point. - defer base.Cmd("rmi", imageName).AssertFail() - base.Cmd("images").AssertOutContains(imageName) - - tID := testutil.Identifier(t) - base.Cmd("run", "--name", tID, imageName).AssertOK() - base.Cmd("image", "prune", "--force", "--all").AssertOutNotContains(imageName) - base.Cmd("images").AssertOutContains(imageName) - - base.Cmd("rm", "-f", tID).AssertOK() - base.Cmd("image", "prune", "--force", "--all").AssertOutContains(imageName) - base.Cmd("images").AssertOutNotContains(imageName) -} - -func TestImagePruneFilterLabel(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - t.Cleanup(func() { base.Cmd("rmi", "--force", imageName) }) - - dockerfile := fmt.Sprintf(`FROM %s + testCase := nerdtest.Setup() + + // Cannot use a custom namespace with buildkitd right now, so, no parallel it is + testCase.NoParallel = true + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + // We need to delete everything here for prune to make any sense + imgList := strings.TrimSpace(helpers.Capture("images", "--no-trunc", "-aq")) + if imgList != "" { + helpers.Ensure(append([]string{"rmi", "-f"}, strings.Split(imgList, "\n")...)...) + } + } + testCase.SubTests = []*test.Case{ + { + Description: "without all", + NoParallel: true, + Require: test.Require( + // This never worked with Docker - the only reason we ever got was side effects from other tests + // See inline comments. + test.Not(nerdtest.Docker), + nerdtest.Build, + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s + CMD ["echo", "nerdctl-test-image-prune"] + `, testutil.CommonImage) + + buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + helpers.Ensure("build", buildCtx) + // After we rebuild with tag, docker will no longer show the version from above + // Swapping order does not change anything. + helpers.Ensure("build", "-t", data.Identifier(), buildCtx) + imgList := helpers.Capture("images") + assert.Assert(t, strings.Contains(imgList, ""), "Missing ") + assert.Assert(t, strings.Contains(imgList, data.Identifier()), "Missing "+data.Identifier()) + }, + Command: test.Command("image", "prune", "--force"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + func(stdout string, info string, t *testing.T) { + assert.Assert(t, !strings.Contains(stdout, data.Identifier()), info) + }, + func(stdout string, info string, t *testing.T) { + imgList := helpers.Capture("images") + assert.Assert(t, !strings.Contains(imgList, ""), imgList) + assert.Assert(t, strings.Contains(imgList, data.Identifier()), info) + }, + ), + } + }, + }, + { + Description: "with all", + Require: test.Require( + // Same as above + test.Not(nerdtest.Docker), + nerdtest.Build, + ), + // Cannot use a custom namespace with buildkitd right now, so, no parallel it is + NoParallel: true, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier()) + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s + CMD ["echo", "nerdctl-test-image-prune"] + `, testutil.CommonImage) + + buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + helpers.Ensure("build", buildCtx) + helpers.Ensure("build", "-t", data.Identifier(), buildCtx) + imgList := helpers.Capture("images") + assert.Assert(t, strings.Contains(imgList, ""), "Missing ") + assert.Assert(t, strings.Contains(imgList, data.Identifier()), "Missing "+data.Identifier()) + helpers.Ensure("run", "--name", data.Identifier(), data.Identifier()) + }, + Command: test.Command("image", "prune", "--force", "--all"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + func(stdout string, info string, t *testing.T) { + assert.Assert(t, !strings.Contains(stdout, data.Identifier()), info) + }, + func(stdout string, info string, t *testing.T) { + imgList := helpers.Capture("images") + assert.Assert(t, strings.Contains(imgList, data.Identifier()), info) + assert.Assert(t, !strings.Contains(imgList, ""), imgList) + helpers.Ensure("rm", "-f", data.Identifier()) + removed := helpers.Capture("image", "prune", "--force", "--all") + assert.Assert(t, strings.Contains(removed, data.Identifier()), info) + imgList = helpers.Capture("images") + assert.Assert(t, !strings.Contains(imgList, data.Identifier()), info) + }, + ), + } + }, + }, + { + Description: "with filter label", + Require: nerdtest.Build, + // Cannot use a custom namespace with buildkitd right now, so, no parallel it is + NoParallel: true, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune-filter-label"] LABEL foo=bar LABEL version=0.1`, testutil.CommonImage) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", "-t", imageName, buildCtx).AssertOK() - base.Cmd("images", "--all").AssertOutContains(imageName) - - base.Cmd("image", "prune", "--force", "--all", "--filter", "label=foo=baz").AssertOK() - base.Cmd("images", "--all").AssertOutContains(imageName) - - base.Cmd("image", "prune", "--force", "--all", "--filter", "label=foo=bar").AssertOK() - base.Cmd("images", "--all").AssertOutNotContains(imageName) -} - -func TestImagePruneFilterUntil(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - - base := testutil.NewBase(t) - // For deterministically testing the filter, set the image's created timestamp to 2 hours in the past. - base.Env = append(base.Env, fmt.Sprintf("SOURCE_DATE_EPOCH=%d", time.Now().Add(-2*time.Hour).Unix())) - - imageName := testutil.Identifier(t) - teardown := func() { - // Image should have been pruned; but cleanup on failure. - base.Cmd("rmi", "--force", imageName).Run() + buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + helpers.Ensure("build", "-t", data.Identifier(), buildCtx) + imgList := helpers.Capture("images") + assert.Assert(t, strings.Contains(imgList, data.Identifier()), "Missing "+data.Identifier()) + }, + Command: test.Command("image", "prune", "--force", "--all", "--filter", "label=foo=baz"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + func(stdout string, info string, t *testing.T) { + assert.Assert(t, !strings.Contains(stdout, data.Identifier()), info) + }, + func(stdout string, info string, t *testing.T) { + imgList := helpers.Capture("images") + assert.Assert(t, strings.Contains(imgList, data.Identifier()), info) + }, + func(stdout string, info string, t *testing.T) { + prune := helpers.Capture("image", "prune", "--force", "--all", "--filter", "label=foo=bar") + assert.Assert(t, strings.Contains(prune, data.Identifier()), info) + imgList := helpers.Capture("images") + assert.Assert(t, !strings.Contains(imgList, data.Identifier()), info) + }, + ), + } + }, + }, + { + Description: "with until", + Require: nerdtest.Build, + // Cannot use a custom namespace with buildkitd right now, so, no parallel it is + NoParallel: true, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s +RUN echo "Anything, so that we create actual content for docker to set the current time for CreatedAt" +CMD ["echo", "nerdctl-test-image-prune-until"]`, testutil.CommonImage) + buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + helpers.Ensure("build", "-t", data.Identifier(), buildCtx) + imgList := helpers.Capture("images") + assert.Assert(t, strings.Contains(imgList, data.Identifier()), "Missing "+data.Identifier()) + data.Set("imageID", data.Identifier()) + }, + Command: test.Command("image", "prune", "--force", "--all", "--filter", "until=12h"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain(data.Get("imageID")), + func(stdout string, info string, t *testing.T) { + imgList := helpers.Capture("images") + assert.Assert(t, strings.Contains(imgList, data.Get("imageID")), info) + }, + ), + } + }, + SubTests: []*test.Case{ + { + Description: "Wait and remove until=10ms", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + time.Sleep(1 * time.Second) + }, + Command: test.Command("image", "prune", "--force", "--all", "--filter", "until=10ms"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(data.Get("imageID")), + func(stdout string, info string, t *testing.T) { + imgList := helpers.Capture("images") + assert.Assert(t, !strings.Contains(imgList, data.Get("imageID")), imgList, info) + }, + ), + } + }, + }, + }, + }, } - t.Cleanup(teardown) - teardown() - - dockerfile := fmt.Sprintf(`FROM %s -CMD ["echo", "nerdctl-test-image-prune-filter-until"]`, testutil.CommonImage) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", "-t", imageName, buildCtx).AssertOK() - base.Cmd("images", "--all").AssertOutContains(imageName) - - base.Cmd("image", "prune", "--force", "--all", "--filter", "until=12h").AssertOK() - base.Cmd("images", "--all").AssertOutContains(imageName) - - // Pause to ensure enough time has passed for the image to be cleaned on next prune. - time.Sleep(3 * time.Second) - base.Cmd("image", "prune", "--force", "--all", "--filter", "until=10ms").AssertOK() - base.Cmd("images", "--all").AssertOutNotContains(imageName) + testCase.Run(t) } diff --git a/cmd/nerdctl/image/image_pull_linux_test.go b/cmd/nerdctl/image/image_pull_linux_test.go index d3e956238cf..ff9ee84fdd8 100644 --- a/cmd/nerdctl/image/image_pull_linux_test.go +++ b/cmd/nerdctl/image/image_pull_linux_test.go @@ -18,152 +18,218 @@ package image import ( "fmt" - "os/exec" + "strconv" "strings" "testing" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "gotest.tools/v3/assert" + + testhelpers "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) -func TestImageVerifyWithCosign(t *testing.T) { - testutil.RequireExecutable(t, "cosign") - testutil.DockerIncompatible(t) - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - base.Env = append(base.Env, "COSIGN_PASSWORD=1") - keyPair := helpers.NewCosignKeyPair(t, "cosign-key-pair", "1") - defer keyPair.Cleanup() - tID := testutil.Identifier(t) - reg := testregistry.NewWithNoAuth(base, 0, false) - defer reg.Cleanup(nil) - localhostIP := "127.0.0.1" - t.Logf("localhost IP=%q", localhostIP) - testImageRef := fmt.Sprintf("%s:%d/%s", - localhostIP, reg.Port, tID) - t.Logf("testImageRef=%q", testImageRef) - - dockerfile := fmt.Sprintf(`FROM %s +func TestImagePullWithCosign(t *testing.T) { + nerdtest.Setup() + + var registry *testregistry.RegistryServer + var keyPair *testhelpers.CosignKeyPair + + testCase := &test.Case{ + Description: "TestImagePullWithCosign", + Require: test.Require( + test.Linux, + nerdtest.Build, + test.Binary("cosign"), + test.Not(nerdtest.Docker), + ), + Env: map[string]string{ + "COSIGN_PASSWORD": "1", + }, + Setup: func(data test.Data, helpers test.Helpers) { + keyPair = testhelpers.NewCosignKeyPair(t, "cosign-key-pair", "1") + base := testutil.NewBase(t) + registry = testregistry.NewWithNoAuth(base, 0, false) + testImageRef := fmt.Sprintf("%s:%d/%s", "127.0.0.1", registry.Port, data.Identifier()) + dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := helpers.CreateBuildContext(t, dockerfile) + buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + helpers.Ensure("build", "-t", testImageRef+":one", buildCtx) + helpers.Ensure("build", "-t", testImageRef+":two", buildCtx) + helpers.Ensure("push", "--sign=cosign", "--cosign-key="+keyPair.PrivateKey, testImageRef+":one") + helpers.Ensure("push", "--sign=cosign", "--cosign-key="+keyPair.PrivateKey, testImageRef+":two") + helpers.Ensure("rmi", "-f", testImageRef) + data.Set("imageref", testImageRef) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if keyPair != nil { + keyPair.Cleanup() + } + if registry != nil { + registry.Cleanup(nil) + testImageRef := fmt.Sprintf("%s:%d/%s", "127.0.0.1", registry.Port, data.Identifier()) + helpers.Anyhow("rmi", "-f", testImageRef+":one") + helpers.Anyhow("rmi", "-f", testImageRef+":two") + } + }, + SubTests: []*test.Case{ + { + Description: "Pull with the correct key", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("pull", "--verify=cosign", "--cosign-key="+keyPair.PublicKey, data.Get("imageref")+":one") + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "Pull with unrelated key", + Env: map[string]string{ + "COSIGN_PASSWORD": "2", + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + newKeyPair := testhelpers.NewCosignKeyPair(t, "cosign-key-pair-test", "2") + return helpers.Command("pull", "--verify=cosign", "--cosign-key="+newKeyPair.PublicKey, data.Get("imageref")+":two") + }, + Expected: test.Expects(12, nil, nil), + }, + }, + } - base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() - base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.PrivateKey).AssertOK() - base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.PublicKey).AssertOK() + testCase.Run(t) } func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { - testutil.DockerIncompatible(t) - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - reg := testregistry.NewWithNoAuth(base, 80, false) - defer reg.Cleanup(nil) - testImageRef := fmt.Sprintf("%s/%s:%s", - reg.IP.String(), testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) - t.Logf("testImageRef=%q", testImageRef) - t.Logf("testImageRef=%q", testImageRef) - dockerfile := fmt.Sprintf(`FROM %s -CMD ["echo", "nerdctl-build-test-string"] - `, testutil.CommonImage) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() - base.Cmd("--insecure-registry", "push", testImageRef).AssertOK() - base.Cmd("--insecure-registry", "pull", testImageRef).AssertOK() -} - -func TestImageVerifyWithCosignShouldFailWhenKeyIsNotCorrect(t *testing.T) { - testutil.RequireExecutable(t, "cosign") - testutil.DockerIncompatible(t) - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - base.Env = append(base.Env, "COSIGN_PASSWORD=1") - keyPair := helpers.NewCosignKeyPair(t, "cosign-key-pair", "1") - defer keyPair.Cleanup() - tID := testutil.Identifier(t) - reg := testregistry.NewWithNoAuth(base, 0, false) - defer reg.Cleanup(nil) - localhostIP := "127.0.0.1" - t.Logf("localhost IP=%q", localhostIP) - testImageRef := fmt.Sprintf("%s:%d/%s", - localhostIP, reg.Port, tID) - t.Logf("testImageRef=%q", testImageRef) - - dockerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + var registry *testregistry.RegistryServer + + testCase := &test.Case{ + Description: "TestImagePullPlainHttpWithDefaultPort", + Require: test.Require( + test.Linux, + test.Not(nerdtest.Docker), + nerdtest.Build, + ), + Setup: func(data test.Data, helpers test.Helpers) { + base := testutil.NewBase(t) + registry = testregistry.NewWithNoAuth(base, 80, false) + testImageRef := fmt.Sprintf("%s/%s:%s", + registry.IP.String(), data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) + dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", "-t", testImageRef, buildCtx).AssertOK() - base.Cmd("push", testImageRef, "--sign=cosign", "--cosign-key="+keyPair.PrivateKey).AssertOK() - base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+keyPair.PublicKey).AssertOK() - - base.Env = append(base.Env, "COSIGN_PASSWORD=2") - newKeyPair := helpers.NewCosignKeyPair(t, "cosign-key-pair-test", "2") - base.Cmd("pull", testImageRef, "--verify=cosign", "--cosign-key="+newKeyPair.PublicKey).AssertFail() -} - -func TestPullSoci(t *testing.T) { - testutil.DockerIncompatible(t) - tests := []struct { - name string - sociIndexDigest string - image string - remoteSnapshotsExpectedCount int - }{ - { - name: "Run without specifying SOCI index", - sociIndexDigest: "", - image: testutil.FfmpegSociImage, - remoteSnapshotsExpectedCount: 11, + buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + helpers.Ensure("build", "-t", testImageRef, buildCtx) + helpers.Ensure("--insecure-registry", "push", testImageRef) + helpers.Ensure("rmi", "-f", testImageRef) }, - { - name: "Run with bad SOCI index", - sociIndexDigest: "sha256:thisisabadindex0000000000000000000000000000000000000000000000000", - image: testutil.FfmpegSociImage, - remoteSnapshotsExpectedCount: 11, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + testImageRef := fmt.Sprintf("%s/%s:%s", + registry.IP.String(), data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) + return helpers.Command("--insecure-registry", "pull", testImageRef) }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - base := testutil.NewBase(t) - helpers.RequiresSoci(base) - - //counting initial snapshot mounts - initialMounts, err := exec.Command("mount").Output() - if err != nil { - t.Fatal(err) + Expected: test.Expects(0, nil, nil), + Cleanup: func(data test.Data, helpers test.Helpers) { + if registry != nil { + registry.Cleanup(nil) + testImageRef := fmt.Sprintf("%s/%s:%s", + registry.IP.String(), data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) + helpers.Anyhow("rmi", "-f", testImageRef) } + }, + } - remoteSnapshotsInitialCount := strings.Count(string(initialMounts), "fuse.rawBridge") - - pullOutput := base.Cmd("--snapshotter=soci", "pull", tt.image).Out() - base.T.Logf("pull output: %s", pullOutput) - - actualMounts, err := exec.Command("mount").Output() - if err != nil { - t.Fatal(err) - } - remoteSnapshotsActualCount := strings.Count(string(actualMounts), "fuse.rawBridge") - base.T.Logf("number of actual mounts: %v", remoteSnapshotsActualCount-remoteSnapshotsInitialCount) - - rmiOutput := base.Cmd("rmi", testutil.FfmpegSociImage).Out() - base.T.Logf("rmi output: %s", rmiOutput) - - base.T.Logf("number of expected mounts: %v", tt.remoteSnapshotsExpectedCount) + testCase.Run(t) +} - if tt.remoteSnapshotsExpectedCount != (remoteSnapshotsActualCount - remoteSnapshotsInitialCount) { - t.Fatalf("incorrect number of remote snapshots; expected=%d, actual=%d", - tt.remoteSnapshotsExpectedCount, remoteSnapshotsActualCount-remoteSnapshotsInitialCount) - } - }) +func TestImagePullSoci(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Description: "TestImagePullSoci", + Require: test.Require( + test.Linux, + test.Not(nerdtest.Docker), + nerdtest.Soci, + ), + + // NOTE: these tests cannot be run in parallel, as they depend on the output of host `mount` + // They also feel prone to raciness... + SubTests: []*test.Case{ + { + Description: "Run without specifying SOCI index", + NoParallel: true, + Data: test. + WithData("remoteSnapshotsExpectedCount", "11"). + Set("sociIndexDigest", ""), + Setup: func(data test.Data, helpers test.Helpers) { + cmd := helpers.Custom("mount") + cmd.Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + data.Set("remoteSnapshotsInitialCount", strconv.Itoa(strings.Count(stdout, "fuse.rawBridge"))) + }, + }) + helpers.Ensure("--snapshotter=soci", "pull", testutil.FfmpegSociImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", testutil.FfmpegSociImage) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("mount") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + remoteSnapshotsInitialCount, _ := strconv.Atoi(data.Get("remoteSnapshotsInitialCount")) + remoteSnapshotsActualCount := strings.Count(stdout, "fuse.rawBridge") + assert.Equal(t, + data.Get("remoteSnapshotsExpectedCount"), + strconv.Itoa(remoteSnapshotsActualCount-remoteSnapshotsInitialCount), + info) + }, + } + }, + }, + { + Description: "Run with bad SOCI index", + NoParallel: true, + Data: test. + WithData("remoteSnapshotsExpectedCount", "11"). + Set("sociIndexDigest", "sha256:thisisabadindex0000000000000000000000000000000000000000000000000"), + Setup: func(data test.Data, helpers test.Helpers) { + cmd := helpers.Custom("mount") + cmd.Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + data.Set("remoteSnapshotsInitialCount", strconv.Itoa(strings.Count(stdout, "fuse.rawBridge"))) + }, + }) + helpers.Ensure("--snapshotter=soci", "pull", testutil.FfmpegSociImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", testutil.FfmpegSociImage) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("mount") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + remoteSnapshotsInitialCount, _ := strconv.Atoi(data.Get("remoteSnapshotsInitialCount")) + remoteSnapshotsActualCount := strings.Count(stdout, "fuse.rawBridge") + assert.Equal(t, + data.Get("remoteSnapshotsExpectedCount"), + strconv.Itoa(remoteSnapshotsActualCount-remoteSnapshotsInitialCount), + info) + }, + } + }, + }, + }, } + + testCase.Run(t) } diff --git a/cmd/nerdctl/image/image_push_linux_test.go b/cmd/nerdctl/image/image_push_linux_test.go index 17f757703cf..9d3ae4d8598 100644 --- a/cmd/nerdctl/image/image_push_linux_test.go +++ b/cmd/nerdctl/image/image_push_linux_test.go @@ -17,6 +17,7 @@ package image import ( + "errors" "fmt" "net/http" "strings" @@ -24,171 +25,249 @@ import ( "gotest.tools/v3/assert" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) -func TestPushPlainHTTPFails(t *testing.T) { - testutil.RequiresBuild(t) - base := testutil.NewBase(t) - reg := testregistry.NewWithNoAuth(base, 0, false) - defer reg.Cleanup(nil) - - base.Cmd("pull", testutil.CommonImage).AssertOK() - testImageRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) - t.Logf("testImageRef=%q", testImageRef) - base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() - - res := base.Cmd("push", testImageRef).Run() - resCombined := res.Combined() - t.Logf("result: exitCode=%d, out=%q", res.ExitCode, res) - assert.Assert(t, res.ExitCode != 0) - assert.Assert(t, strings.Contains(resCombined, "server gave HTTP response to HTTPS client")) -} - -func TestPushPlainHTTPLocalhost(t *testing.T) { - testutil.RequiresBuild(t) - base := testutil.NewBase(t) - reg := testregistry.NewWithNoAuth(base, 0, false) - defer reg.Cleanup(nil) - localhostIP := "127.0.0.1" - t.Logf("localhost IP=%q", localhostIP) - - base.Cmd("pull", testutil.CommonImage).AssertOK() - testImageRef := fmt.Sprintf("%s:%d/%s:%s", - localhostIP, reg.Port, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) - t.Logf("testImageRef=%q", testImageRef) - base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() - - base.Cmd("push", testImageRef).AssertOK() -} - -func TestPushPlainHTTPInsecure(t *testing.T) { - testutil.RequiresBuild(t) - // Skip docker, because "dockerd --insecure-registries" requires restarting the daemon - testutil.DockerIncompatible(t) - - base := testutil.NewBase(t) - reg := testregistry.NewWithNoAuth(base, 0, false) - defer reg.Cleanup(nil) - - base.Cmd("pull", testutil.CommonImage).AssertOK() - testImageRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) - t.Logf("testImageRef=%q", testImageRef) - base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() - - base.Cmd("--insecure-registry", "push", testImageRef).AssertOK() -} - -func TestPushPlainHttpInsecureWithDefaultPort(t *testing.T) { - testutil.RequiresBuild(t) - // Skip docker, because "dockerd --insecure-registries" requires restarting the daemon - testutil.DockerIncompatible(t) - - base := testutil.NewBase(t) - reg := testregistry.NewWithNoAuth(base, 80, false) - defer reg.Cleanup(nil) - - base.Cmd("pull", testutil.CommonImage).AssertOK() - testImageRef := fmt.Sprintf("%s/%s:%s", - reg.IP.String(), testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) - t.Logf("testImageRef=%q", testImageRef) - base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() - - base.Cmd("--insecure-registry", "push", testImageRef).AssertOK() -} - -func TestPushInsecureWithLogin(t *testing.T) { - testutil.RequiresBuild(t) - // Skip docker, because "dockerd --insecure-registries" requires restarting the daemon - testutil.DockerIncompatible(t) - - base := testutil.NewBase(t) - reg := testregistry.NewWithTokenAuth(base, "admin", "badmin", 0, true) - defer reg.Cleanup(nil) - - base.Cmd("--insecure-registry", "login", "-u", "admin", "-p", "badmin", - fmt.Sprintf("%s:%d", reg.IP.String(), reg.Port)).AssertOK() - base.Cmd("pull", testutil.CommonImage).AssertOK() - testImageRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) - t.Logf("testImageRef=%q", testImageRef) - base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() - - base.Cmd("push", testImageRef).AssertFail() - base.Cmd("--insecure-registry", "push", testImageRef).AssertOK() -} - -func TestPushWithHostsDir(t *testing.T) { - testutil.RequiresBuild(t) - // Skip docker, because Docker doesn't have `--hosts-dir` option, and we don't want to contaminate the global /etc/docker/certs.d during this test - testutil.DockerIncompatible(t) - - base := testutil.NewBase(t) - reg := testregistry.NewWithTokenAuth(base, "admin", "badmin", 0, true) - defer reg.Cleanup(nil) - - base.Cmd("--hosts-dir", reg.HostsDir, "login", "-u", "admin", "-p", "badmin", fmt.Sprintf("%s:%d", reg.IP.String(), reg.Port)).AssertOK() - - base.Cmd("pull", testutil.CommonImage).AssertOK() - testImageRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.CommonImage, ":")[1]) - t.Logf("testImageRef=%q", testImageRef) - base.Cmd("tag", testutil.CommonImage, testImageRef).AssertOK() - - base.Cmd("--debug", "--hosts-dir", reg.HostsDir, "push", testImageRef).AssertOK() -} - -func TestPushNonDistributableArtifacts(t *testing.T) { - testutil.RequiresBuild(t) - // Skip docker, because "dockerd --insecure-registries" requires restarting the daemon - // Skip docker, because "--allow-nondistributable-artifacts" is a daemon-only option and requires restarting the daemon - testutil.DockerIncompatible(t) - - base := testutil.NewBase(t) - reg := testregistry.NewWithNoAuth(base, 0, false) - defer reg.Cleanup(nil) - - base.Cmd("pull", testutil.NonDistBlobImage).AssertOK() - - testImgRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.NonDistBlobImage, ":")[1]) - base.Cmd("tag", testutil.NonDistBlobImage, testImgRef).AssertOK() - - base.Cmd("--debug", "--insecure-registry", "push", testImgRef).AssertOK() - - blobURL := fmt.Sprintf("http://%s:%d/v2/%s/blobs/%s", reg.IP.String(), reg.Port, testutil.Identifier(t), testutil.NonDistBlobDigest) - resp, err := http.Get(blobURL) - assert.Assert(t, err, "error making http request") - if resp.Body != nil { - resp.Body.Close() - } - assert.Equal(t, resp.StatusCode, http.StatusNotFound, "non-distributable blob should not be available") - - base.Cmd("--debug", "--insecure-registry", "push", "--allow-nondistributable-artifacts", testImgRef).AssertOK() - resp, err = http.Get(blobURL) - assert.Assert(t, err, "error making http request") - if resp.Body != nil { - resp.Body.Close() +func TestPush(t *testing.T) { + nerdtest.Setup() + + var registryNoAuthHTTPRandom, registryNoAuthHTTPDefault, registryTokenAuthHTTPSRandom *testregistry.RegistryServer + + testCase := &test.Case{ + Description: "Test push", + + Require: test.Linux, + + Setup: func(data test.Data, helpers test.Helpers) { + base := testutil.NewBase(t) + registryNoAuthHTTPRandom = testregistry.NewWithNoAuth(base, 0, false) + registryNoAuthHTTPDefault = testregistry.NewWithNoAuth(base, 80, false) + registryTokenAuthHTTPSRandom = testregistry.NewWithTokenAuth(base, "admin", "badmin", 0, true) + }, + + Cleanup: func(data test.Data, helpers test.Helpers) { + if registryNoAuthHTTPRandom != nil { + registryNoAuthHTTPRandom.Cleanup(nil) + } + if registryNoAuthHTTPDefault != nil { + registryNoAuthHTTPDefault.Cleanup(nil) + } + if registryTokenAuthHTTPSRandom != nil { + registryTokenAuthHTTPSRandom.Cleanup(nil) + } + }, + + SubTests: []*test.Case{ + { + Description: "plain http", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + testImageRef := fmt.Sprintf("%s:%d/%s:%s", + registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) + data.Set("testImageRef", testImageRef) + helpers.Ensure("tag", testutil.CommonImage, testImageRef) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("testImageRef") != "" { + helpers.Anyhow("rmi", data.Get("testImageRef")) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("push", data.Get("testImageRef")) + }, + Expected: test.Expects(1, []error{errors.New("server gave HTTP response to HTTPS client")}, nil), + }, + { + Description: "plain http with insecure", + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + testImageRef := fmt.Sprintf("%s:%d/%s:%s", + registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) + data.Set("testImageRef", testImageRef) + helpers.Ensure("tag", testutil.CommonImage, testImageRef) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("testImageRef") != "" { + helpers.Anyhow("rmi", data.Get("testImageRef")) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("push", "--insecure-registry", data.Get("testImageRef")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "plain http with localhost", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + testImageRef := fmt.Sprintf("%s:%d/%s:%s", + "127.0.0.1", registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) + data.Set("testImageRef", testImageRef) + helpers.Ensure("tag", testutil.CommonImage, testImageRef) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("push", data.Get("testImageRef")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "plain http with insecure, default port", + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + testImageRef := fmt.Sprintf("%s/%s:%s", + registryNoAuthHTTPDefault.IP.String(), data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) + data.Set("testImageRef", testImageRef) + helpers.Ensure("tag", testutil.CommonImage, testImageRef) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("testImageRef") != "" { + helpers.Anyhow("rmi", data.Get("testImageRef")) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("push", "--insecure-registry", data.Get("testImageRef")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "with insecure, with login", + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + testImageRef := fmt.Sprintf("%s:%d/%s:%s", + registryTokenAuthHTTPSRandom.IP.String(), registryTokenAuthHTTPSRandom.Port, data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) + data.Set("testImageRef", testImageRef) + helpers.Ensure("tag", testutil.CommonImage, testImageRef) + helpers.Ensure("--insecure-registry", "login", "-u", "admin", "-p", "badmin", + fmt.Sprintf("%s:%d", registryTokenAuthHTTPSRandom.IP.String(), registryTokenAuthHTTPSRandom.Port)) + + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("testImageRef") != "" { + helpers.Anyhow("rmi", data.Get("testImageRef")) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("push", "--insecure-registry", data.Get("testImageRef")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "with hosts dir, with login", + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + testImageRef := fmt.Sprintf("%s:%d/%s:%s", + registryTokenAuthHTTPSRandom.IP.String(), registryTokenAuthHTTPSRandom.Port, data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) + data.Set("testImageRef", testImageRef) + helpers.Ensure("tag", testutil.CommonImage, testImageRef) + helpers.Ensure("--hosts-dir", registryTokenAuthHTTPSRandom.HostsDir, "login", "-u", "admin", "-p", "badmin", + fmt.Sprintf("%s:%d", registryTokenAuthHTTPSRandom.IP.String(), registryTokenAuthHTTPSRandom.Port)) + + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("testImageRef") != "" { + helpers.Anyhow("rmi", data.Get("testImageRef")) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("push", "--hosts-dir", registryTokenAuthHTTPSRandom.HostsDir, data.Get("testImageRef")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "non distributable artifacts", + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.NonDistBlobImage) + testImageRef := fmt.Sprintf("%s:%d/%s:%s", + registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.NonDistBlobImage, ":")[1]) + data.Set("testImageRef", testImageRef) + helpers.Ensure("tag", testutil.NonDistBlobImage, testImageRef) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("testImageRef") != "" { + helpers.Anyhow("rmi", data.Get("testImageRef")) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("push", "--insecure-registry", data.Get("testImageRef")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + blobURL := fmt.Sprintf("http://%s:%d/v2/%s/blobs/%s", registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), testutil.NonDistBlobDigest) + resp, err := http.Get(blobURL) + assert.Assert(t, err, "error making http request") + if resp.Body != nil { + resp.Body.Close() + } + assert.Equal(t, resp.StatusCode, http.StatusNotFound, "non-distributable blob should not be available") + }, + } + }, + }, + { + Description: "non distributable artifacts (with)", + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.NonDistBlobImage) + testImageRef := fmt.Sprintf("%s:%d/%s:%s", + registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.NonDistBlobImage, ":")[1]) + data.Set("testImageRef", testImageRef) + helpers.Ensure("tag", testutil.NonDistBlobImage, testImageRef) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("testImageRef") != "" { + helpers.Anyhow("rmi", data.Get("testImageRef")) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("push", "--insecure-registry", "--allow-nondistributable-artifacts", data.Get("testImageRef")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + blobURL := fmt.Sprintf("http://%s:%d/v2/%s/blobs/%s", registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), testutil.NonDistBlobDigest) + resp, err := http.Get(blobURL) + assert.Assert(t, err, "error making http request") + if resp.Body != nil { + resp.Body.Close() + } + assert.Equal(t, resp.StatusCode, http.StatusOK, "non-distributable blob should be available") + }, + } + }, + }, + { + Description: "soci", + Require: test.Require( + nerdtest.Soci, + test.Not(nerdtest.Docker), + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.UbuntuImage) + testImageRef := fmt.Sprintf("%s:%d/%s:%s", + registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.UbuntuImage, ":")[1]) + data.Set("testImageRef", testImageRef) + helpers.Ensure("tag", testutil.UbuntuImage, testImageRef) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("testImageRef") != "" { + helpers.Anyhow("rmi", data.Get("testImageRef")) + } + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("push", "--snapshotter=soci", "--insecure-registry", "--soci-span-size=2097152", "--soci-min-layer-size=20971520", data.Get("testImageRef")) + }, + Expected: test.Expects(0, nil, nil), + }, + }, } - assert.Equal(t, resp.StatusCode, http.StatusOK, "non-distributable blob should be available") -} - -func TestPushSoci(t *testing.T) { - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - helpers.RequiresSoci(base) - reg := testregistry.NewWithNoAuth(base, 0, false) - defer reg.Cleanup(nil) - - base.Cmd("pull", testutil.UbuntuImage).AssertOK() - testImageRef := fmt.Sprintf("%s:%d/%s:%s", - reg.IP.String(), reg.Port, testutil.Identifier(t), strings.Split(testutil.UbuntuImage, ":")[1]) - t.Logf("testImageRef=%q", testImageRef) - base.Cmd("tag", testutil.UbuntuImage, testImageRef).AssertOK() - - base.Cmd("--snapshotter=soci", "--insecure-registry", "push", "--soci-span-size=2097152", "--soci-min-layer-size=20971520", testImageRef).AssertOK() + testCase.Run(t) } diff --git a/cmd/nerdctl/image/image_remove_linux_test.go b/cmd/nerdctl/image/image_remove_linux_test.go deleted file mode 100644 index 5752aa04aa4..00000000000 --- a/cmd/nerdctl/image/image_remove_linux_test.go +++ /dev/null @@ -1,107 +0,0 @@ -/* - 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 image - -import ( - "testing" - - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestRemoveImage(t *testing.T) { - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - base.Cmd("image", "prune", "--force", "--all").AssertOK() - - // ignore error - base.Cmd("rmi", "-f", tID).AssertOK() - - base.Cmd("run", "--name", tID, testutil.CommonImage).AssertOK() - defer base.Cmd("rm", "-f", tID).AssertOK() - - base.Cmd("rmi", testutil.CommonImage).AssertFail() - defer base.Cmd("rmi", "-f", testutil.CommonImage).Run() - base.Cmd("rmi", "-f", testutil.CommonImage).AssertOK() - - base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) -} - -func TestRemoveRunningImage(t *testing.T) { - // If an image is associated with a running/paused containers, `docker rmi -f imageName` - // untags `imageName` (left a `` image) without deletion; `docker rmi -rf imageID` fails. - // In both cases, `nerdctl rmi -f` will fail. - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - - base.Cmd("run", "--name", tID, "-d", testutil.CommonImage, "sleep", "infinity").AssertOK() - defer base.Cmd("rm", "-f", tID).AssertOK() - - base.Cmd("rmi", testutil.CommonImage).AssertFail() - base.Cmd("rmi", "-f", testutil.CommonImage).AssertFail() - base.Cmd("images").AssertOutContains(testutil.ImageRepo(testutil.CommonImage)) - - base.Cmd("kill", tID).AssertOK() - base.Cmd("rmi", testutil.CommonImage).AssertFail() - base.Cmd("rmi", "-f", testutil.CommonImage).AssertOK() - base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) -} - -func TestRemovePausedImage(t *testing.T) { - // If an image is associated with a running/paused containers, `docker rmi -f imageName` - // untags `imageName` (left a `` image) without deletion; `docker rmi -rf imageID` fails. - // In both cases, `nerdctl rmi -f` will fail. - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - switch base.Info().CgroupDriver { - case "none", "": - t.Skip("requires cgroup (for pausing)") - } - tID := testutil.Identifier(t) - - base.Cmd("run", "--name", tID, "-d", testutil.CommonImage, "sleep", "infinity").AssertOK() - base.Cmd("pause", tID).AssertOK() - defer base.Cmd("rm", "-f", tID).AssertOK() - - base.Cmd("rmi", testutil.CommonImage).AssertFail() - base.Cmd("rmi", "-f", testutil.CommonImage).AssertFail() - base.Cmd("images").AssertOutContains(testutil.ImageRepo(testutil.CommonImage)) - - base.Cmd("kill", tID).AssertOK() - base.Cmd("rmi", testutil.CommonImage).AssertFail() - base.Cmd("rmi", "-f", testutil.CommonImage).AssertOK() - base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.CommonImage)) -} - -func TestRemoveImageWithCreatedContainer(t *testing.T) { - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - - base.Cmd("pull", testutil.AlpineImage).AssertOK() - base.Cmd("pull", testutil.NginxAlpineImage).AssertOK() - - base.Cmd("create", "--name", tID, testutil.AlpineImage, "sleep", "infinity").AssertOK() - defer base.Cmd("rm", "-f", tID).AssertOK() - - base.Cmd("rmi", testutil.AlpineImage).AssertFail() - base.Cmd("rmi", "-f", testutil.AlpineImage).AssertOK() - base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.AlpineImage)) - - // a created container with removed image doesn't impact other `rmi` command - base.Cmd("rmi", "-f", testutil.NginxAlpineImage).AssertOK() - base.Cmd("images").AssertOutNotContains(testutil.ImageRepo(testutil.NginxAlpineImage)) -} diff --git a/cmd/nerdctl/image/image_remove_test.go b/cmd/nerdctl/image/image_remove_test.go new file mode 100644 index 00000000000..1d897dccbb9 --- /dev/null +++ b/cmd/nerdctl/image/image_remove_test.go @@ -0,0 +1,304 @@ +/* + 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 image + +import ( + "errors" + "testing" + + "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestRemove(t *testing.T) { + testCase := nerdtest.Setup() + + repoName, _ := imgutil.ParseRepoTag(testutil.CommonImage) + nginxRepoName, _ := imgutil.ParseRepoTag(testutil.NginxAlpineImage) + // NOTES: + // - since all of these are rmi-ing the common image, we need private mode + testCase.Require = nerdtest.Private + + testCase.SubTests = []*test.Case{ + { + Description: "Remove image with stopped container - without -f", + NoParallel: true, + Require: test.Require( + test.Not(test.Windows), + test.Not(nerdtest.Docker), + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("rmi", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("image is being used")}, + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images").Run(&test.Expected{ + Output: test.Contains(repoName), + }) + }, + } + }, + }, + { + Description: "Remove image with stopped container - with -f", + NoParallel: true, + Require: test.Not(test.Windows), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("rmi", "-f", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images").Run(&test.Expected{ + Output: test.DoesNotContain(repoName), + }) + }, + } + }, + }, + { + Description: "Remove image with running container - without -f", + NoParallel: true, + Require: test.Require( + test.Not(test.Windows), + test.Not(nerdtest.Docker), + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("rmi", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("image is being used")}, + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images").Run(&test.Expected{ + Output: test.Contains(repoName), + }) + }, + } + }, + }, + { + Description: "Remove image with running container - with -f", + NoParallel: true, + // FIXME: nerdctl is broken + // https://github.com/containerd/nerdctl/issues/3454 + // If an image is associated with a running/paused containers, `docker rmi -f imageName` + // untags `imageName` (left a `` image) without deletion; `docker rmi -rf imageID` fails. + // In both cases, `nerdctl rmi -f` will fail. + Require: test.Require( + test.Not(test.Windows), + test.Not(nerdtest.Docker), + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("rmi", "-f", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("image is being used")}, + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images").Run(&test.Expected{ + Output: test.Contains(repoName), + }) + }, + } + }, + }, + { + Description: "Remove image with created container - without -f", + NoParallel: true, + Require: test.Not(test.Windows), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("create", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("rmi", "-f", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images").Run(&test.Expected{ + Output: test.DoesNotContain(repoName), + }) + }, + } + }, + }, + { + Description: "Remove image with created container - with -f", + NoParallel: true, + Require: test.Not(test.Windows), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.NginxAlpineImage) + helpers.Ensure("create", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("rmi", testutil.NginxAlpineImage) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("rmi", "-f", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images").Run(&test.Expected{ + Output: test.All( + test.DoesNotContain(repoName), + // a created container with removed image doesn't impact other `rmi` command + test.DoesNotContain(nginxRepoName), + ), + }) + }, + } + }, + }, + { + Description: "Remove image with paused container - without -f", + NoParallel: true, + Require: test.Require( + test.Not(test.Windows), + test.Not(nerdtest.Docker), + nerdtest.CGroup, + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("pause", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("rmi", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("image is being used")}, + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images").Run(&test.Expected{ + Output: test.Contains(repoName), + }) + }, + } + }, + }, + { + Description: "Remove image with paused container - with -f", + NoParallel: true, + Require: test.Require( + test.Not(test.Windows), + nerdtest.CGroup, + // FIXME: nerdctl is broken + // https://github.com/containerd/nerdctl/issues/3454 + // If an image is associated with a running/paused containers, `docker rmi -f imageName` + // untags `imageName` (left a `` image) without deletion; `docker rmi -rf imageID` fails. + // In both cases, `nerdctl rmi -f` will fail. + test.Not(nerdtest.Docker), + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("pause", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("rmi", "-f", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("image is being used")}, + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images").Run(&test.Expected{ + Output: test.Contains(repoName), + }) + }, + } + }, + }, + { + Description: "Remove image with killed container - without -f", + NoParallel: true, + Require: test.Require( + test.Not(test.Windows), + test.Not(nerdtest.Docker), + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("kill", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("rmi", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("image is being used")}, + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images").Run(&test.Expected{ + Output: test.Contains(repoName), + }) + }, + } + }, + }, + { + Description: "Remove image with killed container - with -f", + NoParallel: true, + Require: test.Not(test.Windows), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("kill", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Command: test.Command("rmi", "-f", testutil.CommonImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images").Run(&test.Expected{ + Output: test.DoesNotContain(repoName), + }) + }, + } + }, + }, + } + + testCase.Run(t) +} diff --git a/cmd/nerdctl/image/image_save_linux_test.go b/cmd/nerdctl/image/image_save_linux_test.go deleted file mode 100644 index 0c7c722e97e..00000000000 --- a/cmd/nerdctl/image/image_save_linux_test.go +++ /dev/null @@ -1,50 +0,0 @@ -/* - 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 image - -import ( - "os" - "path/filepath" - "strings" - "testing" - - "gotest.tools/v3/assert" - - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestSave(t *testing.T) { - // See detailed comment in TestRunCustomRootfs for why we need a separate namespace. - base := testutil.NewBaseWithNamespace(t, testutil.Identifier(t)) - t.Cleanup(func() { - base.Cmd("namespace", "remove", testutil.Identifier(t)).Run() - }) - base.Cmd("pull", testutil.AlpineImage).AssertOK() - archiveTarPath := filepath.Join(t.TempDir(), "a.tar") - base.Cmd("save", "-o", archiveTarPath, testutil.AlpineImage).AssertOK() - rootfsPath := filepath.Join(t.TempDir(), "rootfs") - err := helpers.ExtractDockerArchive(archiveTarPath, rootfsPath) - assert.NilError(t, err) - etcOSReleasePath := filepath.Join(rootfsPath, "/etc/os-release") - etcOSReleaseBytes, err := os.ReadFile(etcOSReleasePath) - assert.NilError(t, err) - etcOSRelease := string(etcOSReleaseBytes) - t.Logf("read %q, extracted from %q", etcOSReleasePath, testutil.AlpineImage) - t.Log(etcOSRelease) - assert.Assert(t, strings.Contains(etcOSRelease, "Alpine")) -} diff --git a/cmd/nerdctl/image/image_save_test.go b/cmd/nerdctl/image/image_save_test.go index c8078967477..23860cf443e 100644 --- a/cmd/nerdctl/image/image_save_test.go +++ b/cmd/nerdctl/image/image_save_test.go @@ -17,54 +17,119 @@ package image import ( + "os" "path/filepath" "strings" "testing" + "gotest.tools/v3/assert" + + testhelpers "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func TestSaveById(t *testing.T) { - // See detailed comment in TestRunCustomRootfs for why we need a separate namespace. - base := testutil.NewBaseWithNamespace(t, testutil.Identifier(t)) - t.Cleanup(func() { - base.Cmd("namespace", "remove", testutil.Identifier(t)).Run() - }) - base.Cmd("pull", testutil.CommonImage).AssertOK() - inspect := base.InspectImage(testutil.CommonImage) - var id string - if testutil.GetTarget() == testutil.Docker { - id = inspect.ID - } else { - id = strings.Split(inspect.RepoDigests[0], ":")[1] +func TestSaveContent(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Description: "Test content (linux only)", + Require: test.Not(test.Windows), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "--quiet", testutil.CommonImage) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("save", "-o", filepath.Join(data.TempDir(), "out.tar"), testutil.CommonImage) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + rootfsPath := filepath.Join(data.TempDir(), "rootfs") + err := testhelpers.ExtractDockerArchive(filepath.Join(data.TempDir(), "out.tar"), rootfsPath) + assert.NilError(t, err) + etcOSReleasePath := filepath.Join(rootfsPath, "/etc/os-release") + etcOSReleaseBytes, err := os.ReadFile(etcOSReleasePath) + assert.NilError(t, err) + etcOSRelease := string(etcOSReleaseBytes) + assert.Assert(t, strings.Contains(etcOSRelease, "Alpine")) + }, + } + }, } - archiveTarPath := filepath.Join(t.TempDir(), "id.tar") - base.Cmd("save", "-o", archiveTarPath, id).AssertOK() - base.Cmd("rmi", "-f", testutil.CommonImage).AssertOK() - base.Cmd("load", "-i", archiveTarPath).AssertOK() - base.Cmd("run", "--rm", id, "sh", "-euxc", "echo foo").AssertOK() + + testCase.Run(t) } -func TestSaveByIdWithDifferentNames(t *testing.T) { - // See detailed comment in TestRunCustomRootfs for why we need a separate namespace. - base := testutil.NewBaseWithNamespace(t, testutil.Identifier(t)) - t.Cleanup(func() { - base.Cmd("namespace", "remove", testutil.Identifier(t)).Run() - }) - base.Cmd("pull", testutil.CommonImage).AssertOK() - inspect := base.InspectImage(testutil.CommonImage) - var id string - if testutil.GetTarget() == testutil.Docker { - id = inspect.ID - } else { - id = strings.Split(inspect.RepoDigests[0], ":")[1] - } +func TestSave(t *testing.T) { + testCase := nerdtest.Setup() + + // This test relies on the fact that we can remove the common image, which definitely conflicts with others, + // hence the private mode. + // Further note though, that this will hide the fact this the save command could fail if some layers are missing. + // See https://github.com/containerd/nerdctl/issues/3425 and others for details. + testCase.Require = nerdtest.Private - base.Cmd("tag", testutil.CommonImage, "foobar").AssertOK() + testCase.SubTests = []*test.Case{ + { + Description: "Single image, by id", + NoParallel: true, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("id") != "" { + helpers.Anyhow("rmi", "-f", data.Get("id")) + } + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "--quiet", testutil.CommonImage) + img := nerdtest.InspectImage(helpers, testutil.CommonImage) + var id string + // Docker and Nerdctl do not agree on what is the definition of an image ID + if nerdtest.IsDocker() { + id = img.ID + } else { + id = strings.Split(img.RepoDigests[0], ":")[1] + } + tarPath := filepath.Join(data.TempDir(), "out.tar") + helpers.Ensure("save", "-o", tarPath, id) + helpers.Ensure("rmi", "-f", testutil.CommonImage) + helpers.Ensure("load", "-i", tarPath) + data.Set("id", id) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get("id"), "sh", "-euxc", "echo foo") + }, + Expected: test.Expects(0, nil, test.Equals("foo\n")), + }, + { + Description: "Image with different names, by id", + NoParallel: true, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("id") != "" { + helpers.Anyhow("rmi", "-f", data.Get("id")) + } + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "--quiet", testutil.CommonImage) + img := nerdtest.InspectImage(helpers, testutil.CommonImage) + var id string + if nerdtest.IsDocker() { + id = img.ID + } else { + id = strings.Split(img.RepoDigests[0], ":")[1] + } + helpers.Ensure("tag", testutil.CommonImage, data.Identifier()) + tarPath := filepath.Join(data.TempDir(), "out.tar") + helpers.Ensure("save", "-o", tarPath, id) + helpers.Ensure("rmi", "-f", testutil.CommonImage) + helpers.Ensure("load", "-i", tarPath) + data.Set("id", id) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get("id"), "sh", "-euxc", "echo foo") + }, + Expected: test.Expects(0, nil, test.Equals("foo\n")), + }, + } - archiveTarPath := filepath.Join(t.TempDir(), "id.tar") - base.Cmd("save", "-o", archiveTarPath, id).AssertOK() - base.Cmd("rmi", "-f", testutil.CommonImage).AssertOK() - base.Cmd("load", "-i", archiveTarPath).AssertOK() - base.Cmd("run", "--rm", id, "sh", "-euxc", "echo foo").AssertOK() + testCase.Run(t) } From 33beb32229037ddda303c7a7020eccb69e4a839f Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 10 Oct 2024 16:34:05 -0700 Subject: [PATCH 0818/1066] Migration aftermath This commit bundles a few minor fixes that are necessary following changes in test tooling. Signed-off-by: apostasie --- cmd/nerdctl/login/login_linux_test.go | 28 +++++++++++++++-------- cmd/nerdctl/volume/volume_inspect_test.go | 2 +- cmd/nerdctl/volume/volume_list_test.go | 3 ++- pkg/testutil/nerdtest/requirements.go | 2 +- pkg/testutil/test/utilities.go | 6 ----- pkg/testutil/testutil.go | 2 +- 6 files changed, 23 insertions(+), 20 deletions(-) diff --git a/cmd/nerdctl/login/login_linux_test.go b/cmd/nerdctl/login/login_linux_test.go index 13a68c4900a..0a53a6a623e 100644 --- a/cmd/nerdctl/login/login_linux_test.go +++ b/cmd/nerdctl/login/login_linux_test.go @@ -242,11 +242,15 @@ func TestLoginAgainstVariants(t *testing.T) { "token", }, // Basic auth, with TLS - { - 80, - true, - "basic", - }, + /* + // This is not working currently, unless we would force a server https:// in hosts + // To be fixed with login rewrite + { + 80, + true, + "basic", + }, + */ { 443, true, @@ -258,11 +262,15 @@ func TestLoginAgainstVariants(t *testing.T) { "basic", }, // Token auth, with TLS - { - 80, - true, - "token", - }, + /* + // This is not working currently, unless we would force a server https:// in hosts + // To be fixed with login rewrite + { + 80, + true, + "token", + }, + */ { 443, true, diff --git a/cmd/nerdctl/volume/volume_inspect_test.go b/cmd/nerdctl/volume/volume_inspect_test.go index a1c729b5c52..a7ec478b55a 100644 --- a/cmd/nerdctl/volume/volume_inspect_test.go +++ b/cmd/nerdctl/volume/volume_inspect_test.go @@ -51,7 +51,7 @@ func TestVolumeInspect(t *testing.T) { &test.Requirement{ Check: func(data test.Data, helpers test.Helpers) (bool, string) { isDocker, _ := nerdtest.Docker.Check(data, helpers) - return !isDocker || test.IsRoot(), "docker cli needs to be run as root" + return !isDocker || os.Geteuid() == 0, "docker cli needs to be run as root" }, }) diff --git a/cmd/nerdctl/volume/volume_list_test.go b/cmd/nerdctl/volume/volume_list_test.go index 77954ee5b19..d48b35809c3 100644 --- a/cmd/nerdctl/volume/volume_list_test.go +++ b/cmd/nerdctl/volume/volume_list_test.go @@ -18,6 +18,7 @@ package volume import ( "fmt" + "os" "strings" "testing" @@ -94,7 +95,7 @@ func TestVolumeLsFilter(t *testing.T) { &test.Requirement{ Check: func(data test.Data, helpers test.Helpers) (bool, string) { isDocker, _ := nerdtest.Docker.Check(data, helpers) - return !isDocker || test.IsRoot(), "docker cli needs to be run as root" + return !isDocker || os.Geteuid() == 0, "docker cli needs to be run as root" }, }) diff --git a/pkg/testutil/nerdtest/requirements.go b/pkg/testutil/nerdtest/requirements.go index 32878ce1cda..e69b954f4be 100644 --- a/pkg/testutil/nerdtest/requirements.go +++ b/pkg/testutil/nerdtest/requirements.go @@ -32,7 +32,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -var BuildkitHost test.ConfigKey = "bkHost" +var BuildkitHost test.ConfigKey = "BuildkitHost" // These are used for ambient requirements var ipv6 test.ConfigKey = "IPv6Test" diff --git a/pkg/testutil/test/utilities.go b/pkg/testutil/test/utilities.go index b12715d7b82..26da36bdbaa 100644 --- a/pkg/testutil/test/utilities.go +++ b/pkg/testutil/test/utilities.go @@ -20,14 +20,8 @@ import ( "crypto/rand" "encoding/base64" "fmt" - "os" ) -// IsRoot returns true if we are root... simple -func IsRoot() bool { - return os.Geteuid() == 0 -} - // RandomStringBase64 generates a base64 encoded random string func RandomStringBase64(n int) string { b := make([]byte, n) diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 4287db9b305..8dd8a1edce6 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -562,7 +562,7 @@ func M(m *testing.M) { flag.BoolVar(&flagTestKillDaemon, "test.allow-kill-daemon", false, "enable tests that kill the daemon") flag.BoolVar(&flagTestIPv6, "test.only-ipv6", false, "enable tests on IPv6") flag.BoolVar(&flagTestKube, "test.only-kubernetes", false, "enable tests on Kubernetes") - flag.BoolVar(&flagTestFlaky, "test.only-flaky", false, "enable testing of flaky tests only") + flag.BoolVar(&flagTestFlaky, "test.only-flaky", false, "enable testing of flaky tests only (if false, flaky tests are ignored)") if flag.Lookup("test.v") != nil { flagVerbose = true } From 379e8ce692e21ca4860d8d7ccde5dc0efa3c6a59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:36:38 +0000 Subject: [PATCH 0819/1066] build(deps): bump github.com/klauspost/compress from 1.17.10 to 1.17.11 Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.17.10 to 1.17.11. - [Release notes](https://github.com/klauspost/compress/releases) - [Changelog](https://github.com/klauspost/compress/blob/master/.goreleaser.yml) - [Commits](https://github.com/klauspost/compress/compare/v1.17.10...v1.17.11) --- updated-dependencies: - dependency-name: github.com/klauspost/compress dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ddbdb939ca1..074c01acd8f 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/ipfs/go-cid v0.4.1 - github.com/klauspost/compress v1.17.10 + github.com/klauspost/compress v1.17.11 github.com/mattn/go-isatty v0.0.20 github.com/moby/sys/mount v0.3.4 github.com/moby/sys/mountinfo v0.7.2 diff --git a/go.sum b/go.sum index e3417eb32db..84d673230fa 100644 --- a/go.sum +++ b/go.sum @@ -174,8 +174,8 @@ github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCX github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= -github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= From 50ac0b6f932f938ece2dc8fba65e60018e185dc9 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 11 Oct 2024 19:04:49 -0700 Subject: [PATCH 0820/1066] Fix CNI concurrency issue Signed-off-by: apostasie --- pkg/netutil/netutil.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 81badc8edf1..43439c592ec 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -215,7 +215,15 @@ func NewCNIEnv(cniPath, cniConfPath string, opts ...CNIEnvOpt) (*CNIEnv, error) } func (e *CNIEnv) NetworkList() ([]*NetworkConfig, error) { - return e.networkConfigList() + var netConfigList []*NetworkConfig + var err error + fn := func() error { + netConfigList, err = e.networkConfigList() + return err + } + err = lockutil.WithDirLock(e.NetconfPath, fn) + + return netConfigList, err } func (e *CNIEnv) NetworkMap() (map[string]*NetworkConfig, error) { //nolint:revive From 2c6fb7722dd448159fb05a4ec759dcc6ec6b4e5f Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 11 Oct 2024 20:50:50 -0700 Subject: [PATCH 0821/1066] Alleviate image --filter missing digest issue Signed-off-by: apostasie --- pkg/imgutil/filtering.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index 473a382642f..0085cd943fb 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -28,6 +28,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) @@ -240,7 +241,10 @@ func FilterByLabel(ctx context.Context, client *containerd.Client, labels map[st clientImage := containerd.NewImage(client, i) imageCfg, _, err := ReadImageConfig(ctx, clientImage) if err != nil { - return false, err + // Stop-gap measure. Do not hard error if some images config cannot be read. + // See https://github.com/containerd/nerdctl/issues/3516 + log.G(ctx).WithError(err).Errorf("failed reading image config for %s (%s)", clientImage.Name(), clientImage.Platform()) + return false, nil } return matchesAllLabels(imageCfg.Config.Labels, labels), nil }) From c3c3f91f7ae6faf4ab10e9aaf925ebaf5991015f Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Thu, 10 Oct 2024 04:16:57 +0000 Subject: [PATCH 0822/1066] Add container run --security-opt systempaths=unconfined This change adds security option to turn off confinement for system paths (masked paths, read-only paths) for the container. Signed-off-by: Austin Vazquez --- cmd/nerdctl/container/container_run.go | 1 + .../container_run_security_linux_test.go | 55 +++++++++++++++++++ docs/command-reference.md | 1 + pkg/cmd/container/run_security_linux.go | 13 ++++- 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/container/container_run.go b/cmd/nerdctl/container/container_run.go index a514d3795af..b24cd7c3566 100644 --- a/cmd/nerdctl/container/container_run.go +++ b/cmd/nerdctl/container/container_run.go @@ -183,6 +183,7 @@ func setCreateFlags(cmd *cobra.Command) { "seccomp=", "seccomp=" + defaults.SeccompProfileName, "seccomp=unconfined", "apparmor=", "apparmor=" + defaults.AppArmorProfileName, "apparmor=unconfined", "no-new-privileges", + "systempaths=unconfined", "privileged-without-host-devices"}, cobra.ShellCompDirectiveNoFileComp }) // cap-add and cap-drop are defined as StringSlice, not StringArray, to allow specifying "--cap-add=CAP_SYS_ADMIN,CAP_NET_ADMIN" (compatible with Podman) diff --git a/cmd/nerdctl/container/container_run_security_linux_test.go b/cmd/nerdctl/container/container_run_security_linux_test.go index e5c6ec87b1e..6a4cc35bb4b 100644 --- a/cmd/nerdctl/container/container_run_security_linux_test.go +++ b/cmd/nerdctl/container/container_run_security_linux_test.go @@ -193,6 +193,61 @@ func TestRunSeccompCapSysPtrace(t *testing.T) { // Docker/Moby 's seccomp profile allows ptrace(2) by default, but containerd does not (yet): https://github.com/containerd/containerd/issues/6802 } +func TestRunSystemPathsUnconfined(t *testing.T) { + base := testutil.NewBase(t) + + const findmnt = "`apk add -q findmnt && findmnt -R /proc && findmnt -R /sys`" + result := base.Cmd("run", "--rm", testutil.AlpineImage, "sh", "-euxc", findmnt).Run() + defaultContainerOutput := result.Combined() + + var confined []string + + for _, path := range []string{ + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/sched_debug", + "/proc/scsi", + "/proc/timer_list", + "/proc/timer_stats", + "/sys/firmware", + "/sys/fs/selinux", + } { + // Not each distribution will support every masked path here. + if strings.Contains(defaultContainerOutput, path) { + confined = append(confined, path) + } + } + + assert.Check(t, len(confined) != 0, "Default container has no confined paths to validate") + + result = base.Cmd("run", "--rm", "--security-opt", "systempaths=unconfined", testutil.AlpineImage, "sh", "-euxc", findmnt).Run() + unconfinedContainerOutput := result.Combined() + + for _, path := range confined { + assert.Assert(t, !strings.Contains(unconfinedContainerOutput, path), fmt.Sprintf("%s should not be masked when unconfined", path)) + } + + for _, path := range []string{ + "/proc/acpi", + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sysrq-trigger", + "/proc/sys", + } { + findmntPath := fmt.Sprintf("`apk add -q findmnt && findmnt %s`", path) + + result := base.Cmd("run", "--rm", testutil.AlpineImage, "sh", "-euxc", findmntPath).Run() + + // Not each distribution will support every read-only path here. + if strings.Contains(result.Combined(), path) { + result = base.Cmd("run", "--rm", "--security-opt", "systempaths=unconfined", testutil.AlpineImage, "sh", "-euxc", findmntPath).Run() + assert.Assert(t, !strings.Contains(result.Combined(), "ro,"), fmt.Sprintf("%s should not be read-only when unconfined", path)) + } + } +} + func TestRunPrivileged(t *testing.T) { // docker does not support --privileged-without-host-devices testutil.DockerIncompatible(t) diff --git a/docs/command-reference.md b/docs/command-reference.md index 486872071fb..cba61fb1372 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -230,6 +230,7 @@ Security flags: - :whale: `--security-opt seccomp=`: specify custom seccomp profile - :whale: `--security-opt apparmor=`: specify custom AppArmor profile - :whale: `--security-opt no-new-privileges`: disallow privilege escalation, e.g., setuid and file capabilities +- :whale: `--security-opt systempaths=unconfined`: Turn off confinement for system paths (masked paths, read-only paths) for the container - :nerd_face: `--security-opt privileged-without-host-devices`: Don't pass host devices to privileged containers - :whale: `--cap-add=`: Add Linux capabilities - :whale: `--cap-drop=`: Drop Linux capabilities diff --git a/pkg/cmd/container/run_security_linux.go b/pkg/cmd/container/run_security_linux.go index 4b26d23f766..510310f265a 100644 --- a/pkg/cmd/container/run_security_linux.go +++ b/pkg/cmd/container/run_security_linux.go @@ -45,10 +45,14 @@ var privilegedWithoutDevicesOpts = []oci.SpecOpts{ oci.WithNewPrivileges, } +const ( + systemPathsUnconfined = "unconfined" +) + func generateSecurityOpts(privileged bool, securityOptsMap map[string]string) ([]oci.SpecOpts, error) { for k := range securityOptsMap { switch k { - case "seccomp", "apparmor", "no-new-privileges", "privileged-without-host-devices": + case "seccomp", "apparmor", "no-new-privileges", "systempaths", "privileged-without-host-devices": default: log.L.Warnf("unknown security-opt: %q", k) } @@ -99,6 +103,13 @@ func generateSecurityOpts(privileged bool, securityOptsMap map[string]string) ([ opts = append(opts, oci.WithNewPrivileges) } + if value, ok := securityOptsMap["systempaths"]; ok && value == systemPathsUnconfined { + opts = append(opts, oci.WithMaskedPaths(nil)) + opts = append(opts, oci.WithReadonlyPaths(nil)) + } else if ok && value != systemPathsUnconfined { + return nil, errors.New(`invalid security-opt "systempaths=unconfined"`) + } + privilegedWithoutHostDevices, err := maputil.MapBoolValueAsOpt(securityOptsMap, "privileged-without-host-devices") if err != nil { return nil, err From ddeae201bb13b4d7ada07b2c63fca6f528bd4a92 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Sat, 12 Oct 2024 05:53:12 +0000 Subject: [PATCH 0823/1066] removing ipfs binary from nerdctl-full Signed-off-by: Kay Yan --- Dockerfile | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7e7d8b8554c..a594358aee4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,8 +36,6 @@ ARG BYPASS4NETNS_VERSION=v0.4.1 # Extra deps: FUSE-OverlayFS ARG FUSE_OVERLAYFS_VERSION=v1.14 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 -# Extra deps: IPFS -ARG KUBO_VERSION=v0.29.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug @@ -50,6 +48,7 @@ ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.12.0 ARG NYDUS_VERSION=v2.2.5 ARG SOCI_SNAPSHOTTER_VERSION=0.7.0 +ARG KUBO_VERSION=v0.29.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0 AS xx @@ -213,9 +212,6 @@ RUN fname="containerd-fuse-overlayfs-${CONTAINERD_FUSE_OVERLAYFS_VERSION/v}-${TA tar xzf "${fname}" -C /out/bin && \ rm -f "${fname}" && \ echo "- containerd-fuse-overlayfs: ${CONTAINERD_FUSE_OVERLAYFS_VERSION}" >> /out/share/doc/nerdctl-full/README.md -ARG KUBO_VERSION -COPY --from=build-kubo /out/${TARGETARCH:-amd64}/* /out/bin/ -RUN echo "- Kubo (IPFS): ${KUBO_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG TINI_VERSION RUN fname="tini-static-${TARGETARCH:-amd64}" && \ curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/${fname}" && \ @@ -234,7 +230,6 @@ RUN echo "" >> /out/share/doc/nerdctl-full/README.md && \ echo "## License" >> /out/share/doc/nerdctl-full/README.md && \ echo "- bin/slirp4netns: [GNU GENERAL PUBLIC LICENSE, Version 2](https://github.com/rootless-containers/slirp4netns/blob/${SLIRP4NETNS_VERSION}/COPYING)" >> /out/share/doc/nerdctl-full/README.md && \ echo "- bin/fuse-overlayfs: [GNU GENERAL PUBLIC LICENSE, Version 2](https://github.com/containers/fuse-overlayfs/blob/${FUSE_OVERLAYFS_VERSION}/COPYING)" >> /out/share/doc/nerdctl-full/README.md && \ - echo "- bin/ipfs: [Combination of MIT-only license and dual MIT/Apache-2.0 license](https://github.com/ipfs/kubo/blob/${KUBO_VERSION}/LICENSE)" >> /out/share/doc/nerdctl-full/README.md && \ echo "- bin/{runc,bypass4netns,bypass4netnsd}: Apache License 2.0, statically linked with libseccomp ([LGPL 2.1](https://github.com/seccomp/libseccomp/blob/main/LICENSE), source code available at https://github.com/seccomp/libseccomp/)" >> /out/share/doc/nerdctl-full/README.md && \ echo "- bin/tini: [MIT License](https://github.com/krallin/tini/blob/${TINI_VERSION}/LICENSE)" >> /out/share/doc/nerdctl-full/README.md && \ echo "- Other files: [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0)" >> /out/share/doc/nerdctl-full/README.md && \ @@ -300,6 +295,7 @@ RUN fname="soci-snapshotter-${SOCI_SNAPSHOTTER_VERSION}-${TARGETOS:-linux}-${TAR curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/awslabs/soci-snapshotter/releases/download/v${SOCI_SNAPSHOTTER_VERSION}/${fname}" && \ tar -C /usr/local/bin -xvf "${fname}" soci soci-snapshotter-grpc # enable offline ipfs for integration test +COPY --from=build-kubo /out/${TARGETARCH:-amd64}/* /usr/local/bin/ COPY ./Dockerfile.d/test-integration-etc_containerd-stargz-grpc_config.toml /etc/containerd-stargz-grpc/config.toml COPY ./Dockerfile.d/test-integration-ipfs-offline.service /usr/local/lib/systemd/system/ COPY ./Dockerfile.d/test-integration-buildkit-nerdctl-test.service /usr/local/lib/systemd/system/ From 516ed82e9cecfcf90787e2cbefde77ad39a90cf7 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Mon, 14 Oct 2024 21:11:10 +0000 Subject: [PATCH 0824/1066] Update containerd (1.7.23) in CI Signed-off-by: Austin Vazquez --- .github/workflows/test-canary.yml | 2 +- .github/workflows/test.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 91b4cc06af4..dc07fe92de7 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -100,7 +100,7 @@ jobs: - uses: actions/checkout@v4.2.1 with: repository: containerd/containerd - ref: "v1.7.22" + ref: "v1.7.23" path: containerd fetch-depth: 1 - name: "Set up CNI" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2fae92dcbfa..4577a894cce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -66,7 +66,7 @@ jobs: containerd: v1.6.36 runner: "ubuntu-20.04" - ubuntu: 22.04 - containerd: v1.7.22 + containerd: v1.7.23 runner: "ubuntu-22.04" - ubuntu: 24.04 containerd: v2.0.0-rc.5 @@ -115,7 +115,7 @@ jobs: # ubuntu-20.04: cgroup v1, ubuntu-22.04 and later: cgroup v2 include: - ubuntu: 24.04 - containerd: v1.7.22 + containerd: v1.7.23 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -175,7 +175,7 @@ jobs: rootlesskit: v1.1.1 # Deprecated target: test-integration-rootless - ubuntu: 22.04 - containerd: v1.7.22 + containerd: v1.7.23 rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 24.04 @@ -183,7 +183,7 @@ jobs: rootlesskit: v2.3.1 target: test-integration-rootless - ubuntu: 24.04 - containerd: v1.7.22 + containerd: v1.7.23 rootlesskit: v2.3.1 target: test-integration-rootless-port-slirp4netns env: @@ -320,7 +320,7 @@ jobs: - uses: actions/checkout@v4.2.1 with: repository: containerd/containerd - ref: v1.7.22 + ref: v1.7.23 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -328,7 +328,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.22 + ctrdVersion: 1.7.23 run: powershell hack/configure-windows-ci.ps1 # TODO: Run unit tests - name: "Run integration tests" From ad64f4217d55835d22d0511587e7005eb88e32bb Mon Sep 17 00:00:00 2001 From: Cezar Rata Date: Mon, 26 Aug 2024 16:05:47 -0700 Subject: [PATCH 0825/1066] fix: nerdctl stats on a container without a memory limit returns host memory limit Signed-off-by: Cezar Rata Signed-off-by: Cezar Rata Signed-off-by: Cezar Rata Signed-off-by: Cezar Rata --- .../container/container_stats_linux_test.go | 28 +++++++++++++ pkg/statsutil/stats_linux.go | 40 +++++++++++++++++-- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/container/container_stats_linux_test.go b/cmd/nerdctl/container/container_stats_linux_test.go index 5ea2017d949..42b2861aec4 100644 --- a/cmd/nerdctl/container/container_stats_linux_test.go +++ b/cmd/nerdctl/container/container_stats_linux_test.go @@ -45,3 +45,31 @@ func TestStats(t *testing.T) { base.Cmd("container", "stats", "--no-stream").AssertOutContains(testContainerName) base.Cmd("container", "stats", "--no-stream", testContainerName).AssertOK() } + +func TestStatsMemoryLimitNotSet(t *testing.T) { + if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { + t.Skip("test skipped for rootless containers on cgroup v1") + } + testContainerName := testutil.Identifier(t)[:12] + + base := testutil.NewBase(t) + defer base.Cmd("rm", "-f", testContainerName).Run() + + base.Cmd("run", "-d", "--name", testContainerName, testutil.AlpineImage, "sleep", "10").AssertOK() + base.Cmd("stats", "--no-stream").AssertOutNotContains("16EiB") + base.Cmd("stats", "--no-stream", testContainerName).AssertOK() +} + +func TestStatsMemoryLimitSet(t *testing.T) { + if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { + t.Skip("test skipped for rootless containers on cgroup v1") + } + testContainerName := testutil.Identifier(t)[:12] + + base := testutil.NewBase(t) + defer base.Cmd("rm", "-f", testContainerName).Run() + + base.Cmd("run", "-d", "--name", testContainerName, "--memory", "1g", testutil.AlpineImage, "sleep", "10").AssertOK() + base.Cmd("stats", "--no-stream").AssertOutContains("1GiB") + base.Cmd("stats", "--no-stream", testContainerName).AssertOK() +} diff --git a/pkg/statsutil/stats_linux.go b/pkg/statsutil/stats_linux.go index 61afba099bb..4f1f53bc828 100644 --- a/pkg/statsutil/stats_linux.go +++ b/pkg/statsutil/stats_linux.go @@ -17,6 +17,10 @@ package statsutil import ( + "bufio" + "os" + "strconv" + "strings" "time" "github.com/vishvananda/netlink" @@ -35,11 +39,10 @@ func calculateMemPercent(limit float64, usedNo float64) float64 { } func SetCgroupStatsFields(previousStats *ContainerStats, data *v1.Metrics, links []netlink.Link) (StatsEntry, error) { - cpuPercent := calculateCgroupCPUPercent(previousStats, data) blkRead, blkWrite := calculateCgroupBlockIO(data) mem := calculateCgroupMemUsage(data) - memLimit := float64(data.Memory.Usage.Limit) + memLimit := getCgroupMemLimit(float64(data.Memory.Usage.Limit)) memPercent := calculateMemPercent(memLimit, mem) pidsStatsCurrent := data.Pids.Current netRx, netTx := calculateCgroupNetwork(links) @@ -59,11 +62,10 @@ func SetCgroupStatsFields(previousStats *ContainerStats, data *v1.Metrics, links } func SetCgroup2StatsFields(previousStats *ContainerStats, metrics *v2.Metrics, links []netlink.Link) (StatsEntry, error) { - cpuPercent := calculateCgroup2CPUPercent(previousStats, metrics) blkRead, blkWrite := calculateCgroup2IO(metrics) mem := calculateCgroup2MemUsage(metrics) - memLimit := float64(metrics.Memory.UsageLimit) + memLimit := getCgroupMemLimit(float64(metrics.Memory.UsageLimit)) memPercent := calculateMemPercent(memLimit, mem) pidsStatsCurrent := metrics.Pids.Current netRx, netTx := calculateCgroupNetwork(links) @@ -82,6 +84,36 @@ func SetCgroup2StatsFields(previousStats *ContainerStats, metrics *v2.Metrics, l } +func getCgroupMemLimit(memLimit float64) float64 { + if memLimit == float64(^uint64(0)) { + return getHostMemLimit() + } + return memLimit +} + +func getHostMemLimit() float64 { + file, err := os.Open("/proc/meminfo") + if err != nil { + return float64(^uint64(0)) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + if strings.HasPrefix(scanner.Text(), "MemTotal:") { + fields := strings.Fields(scanner.Text()) + if len(fields) >= 2 { + memKb, err := strconv.ParseUint(fields[1], 10, 64) + if err == nil { + return float64(memKb * 1024) // kB to bytes + } + } + break + } + } + return float64(^uint64(0)) +} + func calculateCgroupCPUPercent(previousStats *ContainerStats, metrics *v1.Metrics) float64 { var ( cpuPercent = 0.0 From bf39542967106752f750ffc91174d4cba9abb0c4 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 14 Oct 2024 14:54:49 -0700 Subject: [PATCH 0826/1066] Skip TestRunWithTtyAndDetached on Windows Signed-off-by: apostasie --- .../container/container_run_windows_test.go | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/cmd/nerdctl/container/container_run_windows_test.go b/cmd/nerdctl/container/container_run_windows_test.go index 2b63a4f215c..843a6eac702 100644 --- a/cmd/nerdctl/container/container_run_windows_test.go +++ b/cmd/nerdctl/container/container_run_windows_test.go @@ -25,6 +25,8 @@ import ( "gotest.tools/v3/assert" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestRunHostProcessContainer(t *testing.T) { @@ -119,16 +121,27 @@ func TestRunProcessContainerWithDevice(t *testing.T) { } func TestRunWithTtyAndDetached(t *testing.T) { - base := testutil.NewBase(t) - imageName := testutil.CommonImage - withTtyContainerName := "with-terminal-" + testutil.Identifier(t) + testCase := nerdtest.Setup() + + // This test is currently disabled, as it is failing most of the time. + testCase.Require = nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3437") + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + // with -t, success, the container should run with tty support. + helpers.Ensure("run", "-d", "-t", "--name", data.Identifier("with-terminal"), testutil.CommonImage, "cmd", "/c", "echo", "Hello, World with TTY!") + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("container", "rm", "-f", data.Identifier("with-terminal")) + } + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + withTtyContainer := nerdtest.InspectContainer(helpers, data.Identifier("with-terminal")) + assert.Equal(helpers.T(), 0, withTtyContainer.State.ExitCode) + return helpers.Command("logs", data.Identifier("with-terminal")) + } - // with -t, success, the container should run with tty support. - base.Cmd("run", "-d", "-t", "--name", withTtyContainerName, imageName, "cmd", "/c", "echo", "Hello, World with TTY!").AssertOK() - defer base.Cmd("container", "rm", "-f", withTtyContainerName).AssertOK() + testCase.Expected = test.Expects(0, nil, test.Contains("Hello, World with TTY!")) - // Check logs for successful command execution (with TTY specific behavior if any) - base.Cmd("logs", withTtyContainerName).AssertOutContains("Hello, World with TTY!") - withTtyContainer := base.InspectContainer(withTtyContainerName) - assert.Equal(base.T, 0, withTtyContainer.State.ExitCode) + testCase.Run(t) } From afba9710cfe7714b6fcee5b10365fb251d09590d Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 14 Oct 2024 15:57:52 -0700 Subject: [PATCH 0827/1066] Cleanup referenceutil Signed-off-by: apostasie --- pkg/referenceutil/referenceutil.go | 155 +++++++----- pkg/referenceutil/referenceutil_test.go | 302 +++++++++++++++++++++++- 2 files changed, 383 insertions(+), 74 deletions(-) diff --git a/pkg/referenceutil/referenceutil.go b/pkg/referenceutil/referenceutil.go index 928b3648923..33df62f2358 100644 --- a/pkg/referenceutil/referenceutil.go +++ b/pkg/referenceutil/referenceutil.go @@ -17,94 +17,121 @@ package referenceutil import ( - "fmt" "path" "strings" - distributionref "github.com/distribution/reference" + "github.com/distribution/reference" "github.com/ipfs/go-cid" + "github.com/opencontainers/go-digest" ) -// Reference is a reference to an image. -type Reference interface { +type Protocol string - // String returns the full reference which can be understood by containerd. - String() string +const IPFSProtocol Protocol = "ipfs" +const IPNSProtocol Protocol = "ipns" +const shortIDLength = 5 + +type ImageReference struct { + Protocol Protocol + Digest digest.Digest + Tag string + ExplicitTag string + Path string + Domain string + + nn reference.Reference } -// ParseAnyReference parses the passed reference as IPFS, CID, or a classic reference. -// Unlike ParseAny, it is not limited to the DockerRef limitations (being either tagged or digested) -// and should be used instead. -func ParseAnyReference(rawRef string) (Reference, error) { - if scheme, ref, err := ParseIPFSRefWithScheme(rawRef); err == nil { - return Reference(stringRef{scheme: scheme, s: ref}), nil +func (ir *ImageReference) Name() string { + ret := ir.Domain + if ret != "" { + ret += "/" } - if c, err := cid.Decode(rawRef); err == nil { - return c, nil - } - return distributionref.ParseAnyReference(rawRef) + ret += ir.Path + return ret } -// ParseAny parses the passed reference with allowing it to be non-docker reference. -// If the ref has IPFS scheme or can be parsed as CID, it's parsed as an IPFS reference. -// Otherwise it's parsed as a docker reference. -func ParseAny(rawRef string) (Reference, error) { - if scheme, ref, err := ParseIPFSRefWithScheme(rawRef); err == nil { - return stringRef{scheme: scheme, s: ref}, nil +func (ir *ImageReference) FamiliarName() string { + if ir.Protocol != "" && ir.Domain == "" { + return ir.Path } - if c, err := cid.Decode(rawRef); err == nil { - return c, nil + if ir.nn != nil { + return reference.FamiliarName(ir.nn.(reference.Named)) } - return ParseDockerRef(rawRef) + return "" } -// ParseDockerRef parses the passed reference with assuming it's a docker reference. -func ParseDockerRef(rawRef string) (distributionref.Named, error) { - return distributionref.ParseDockerRef(rawRef) +func (ir *ImageReference) FamiliarMatch(pattern string) (bool, error) { + return reference.FamiliarMatch(pattern, ir.nn) } -// ParseIPFSRefWithScheme parses the passed reference with assuming it's an IPFS reference with scheme prefix. -func ParseIPFSRefWithScheme(name string) (scheme, ref string, err error) { - if strings.HasPrefix(name, "ipfs://") || strings.HasPrefix(name, "ipns://") { - return name[:4], name[7:], nil +func (ir *ImageReference) String() string { + if ir.Protocol != "" && ir.Domain == "" { + return ir.Path + } + if ir.Path == "" && ir.Digest != "" { + return ir.Digest.String() } - return "", "", fmt.Errorf("reference is not an IPFS reference") + if ir.nn != nil { + return ir.nn.String() + } + return "" } -type stringRef struct { - scheme string - s string +func (ir *ImageReference) SuggestContainerName(suffix string) string { + name := "untitled" + if ir.Protocol != "" && ir.Domain == "" { + name = string(ir.Protocol) + "-" + ir.String()[:shortIDLength] + } else if ir.Path != "" { + name = path.Base(ir.Path) + } + return name + "-" + suffix[:5] } -func (s stringRef) String() string { - return s.s -} +func Parse(rawRef string) (*ImageReference, error) { + ir := &ImageReference{} + + if strings.HasPrefix(rawRef, "ipfs://") { + ir.Protocol = IPFSProtocol + rawRef = rawRef[7:] + } else if strings.HasPrefix(rawRef, "ipns://") { + ir.Protocol = IPNSProtocol + rawRef = rawRef[7:] + } + if decodedCID, err := cid.Decode(rawRef); err == nil { + ir.Protocol = IPFSProtocol + rawRef = decodedCID.String() + ir.Path = rawRef + return ir, nil + } + + if dgst, err := digest.Parse(rawRef); err == nil { + ir.Digest = dgst + return ir, nil + } else if dgst, err := digest.Parse("sha256:" + rawRef); err == nil { + ir.Digest = dgst + return ir, nil + } -// SuggestContainerName generates a container name from name. -// The result MUST NOT be parsed. -func SuggestContainerName(rawRef, containerID string) string { - const shortIDLength = 5 - if len(containerID) < shortIDLength { - panic(fmt.Errorf("got too short (< %d) container ID: %q", shortIDLength, containerID)) + var err error + ir.nn, err = reference.ParseNormalizedNamed(rawRef) + if err != nil { + return ir, err } - name := "untitled-" + containerID[:shortIDLength] - if rawRef != "" { - r, err := ParseAny(rawRef) - if err == nil { - switch rr := r.(type) { - case distributionref.Named: - if rrName := rr.Name(); rrName != "" { - imageNameBased := path.Base(rrName) - if imageNameBased != "" { - name = imageNameBased + "-" + containerID[:shortIDLength] - } - } - case cid.Cid: - name = "ipfs" + "-" + rr.String()[:shortIDLength] + "-" + containerID[:shortIDLength] - case stringRef: - name = rr.scheme + "-" + rr.s[:shortIDLength] + "-" + containerID[:shortIDLength] - } - } + if tg, ok := ir.nn.(reference.Tagged); ok { + ir.ExplicitTag = tg.Tag() } - return name + if tg, ok := ir.nn.(reference.Named); ok { + ir.nn = reference.TagNameOnly(tg) + ir.Domain = reference.Domain(tg) + ir.Path = reference.Path(tg) + } + if tg, ok := ir.nn.(reference.Tagged); ok { + ir.Tag = tg.Tag() + } + if tg, ok := ir.nn.(reference.Digested); ok { + ir.Digest = tg.Digest() + } + + return ir, nil } diff --git a/pkg/referenceutil/referenceutil_test.go b/pkg/referenceutil/referenceutil_test.go index 262a376d9a0..11d6441ca6c 100644 --- a/pkg/referenceutil/referenceutil_test.go +++ b/pkg/referenceutil/referenceutil_test.go @@ -19,17 +19,299 @@ package referenceutil import ( "testing" + "github.com/opencontainers/go-digest" "gotest.tools/v3/assert" ) -func TestSuggestContainerName(t *testing.T) { - const containerID = "16f6d167d4f4743e48affb86e7097222b7992b34a29dab5f8c10cd6a90cdd990" - assert.Equal(t, "alpine-16f6d", SuggestContainerName("alpine", containerID)) - assert.Equal(t, "alpine-16f6d", SuggestContainerName("alpine:3.15", containerID)) - assert.Equal(t, "alpine-16f6d", SuggestContainerName("docker.io/library/alpine:3.15", containerID)) - assert.Equal(t, "alpine-16f6d", SuggestContainerName("docker.io/library/alpine:latest", containerID)) - assert.Equal(t, "ipfs-bafkr-16f6d", SuggestContainerName("bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", containerID)) - assert.Equal(t, "ipfs-bafkr-16f6d", SuggestContainerName("ipfs://bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", containerID)) - assert.Equal(t, "untitled-16f6d", SuggestContainerName("invalid://alpine", containerID)) - assert.Equal(t, "untitled-16f6d", SuggestContainerName("", containerID)) +func TestReferenceUtil(t *testing.T) { + needles := map[string]struct { + Error string + String string + Normalized string + Suggested string + FamiliarName string + FamiliarMatch map[string]bool + Protocol Protocol + Digest digest.Digest + Path string + Domain string + Tag string + ExplicitTag string + }{ + "": { + Error: "invalid reference format", + }, + "∞": { + Error: "invalid reference format", + }, + "abcd:∞": { + Error: "invalid reference format", + }, + "abcd@sha256:∞": { + Error: "invalid reference format", + }, + "abcd@∞": { + Error: "invalid reference format", + }, + "abcd:foo@sha256:∞": { + Error: "invalid reference format", + }, + "abcd:foo@∞": { + Error: "invalid reference format", + }, + "sha256:whatever": { + Error: "", + String: "docker.io/library/sha256:whatever", + Suggested: "sha256-abcde", + FamiliarName: "sha256", + FamiliarMatch: map[string]bool{ + "*a*": true, + "?ha25?": true, + "[s-z]ha25[0-9]": true, + "[^a]ha25[^a-z]": true, + "*6:whatever": true, + "docker.io/library/sha256": false, + }, + Protocol: "", + Digest: "", + Path: "library/sha256", + Domain: "docker.io", + Tag: "whatever", + ExplicitTag: "whatever", + }, + "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50": { + Error: "", + String: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Normalized: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Suggested: "untitled-abcde", + FamiliarName: "", + Protocol: "", + Digest: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Path: "", + Domain: "", + Tag: "", + }, + "4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50": { + Error: "", + String: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Normalized: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Suggested: "untitled-abcde", + FamiliarName: "", + Protocol: "", + Digest: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Path: "", + Domain: "", + Tag: "", + }, + "image_name": { + Error: "", + String: "docker.io/library/image_name:latest", + Normalized: "docker.io/library/image_name:latest", + Suggested: "image_name-abcde", + FamiliarName: "image_name", + Protocol: "", + Digest: "", + Path: "library/image_name", + Domain: "docker.io", + Tag: "latest", + ExplicitTag: "", + }, + "library/image_name": { + Error: "", + String: "docker.io/library/image_name:latest", + Normalized: "docker.io/library/image_name:latest", + Suggested: "image_name-abcde", + FamiliarName: "image_name", + Protocol: "", + Digest: "", + Path: "library/image_name", + Domain: "docker.io", + Tag: "latest", + ExplicitTag: "", + }, + "something/image_name": { + Error: "", + String: "docker.io/something/image_name:latest", + Normalized: "docker.io/something/image_name:latest", + Suggested: "image_name-abcde", + FamiliarName: "something/image_name", + Protocol: "", + Digest: "", + Path: "something/image_name", + Domain: "docker.io", + Tag: "latest", + ExplicitTag: "", + }, + "docker.io/library/image_name": { + Error: "", + String: "docker.io/library/image_name:latest", + Normalized: "docker.io/library/image_name:latest", + Suggested: "image_name-abcde", + FamiliarName: "image_name", + Protocol: "", + Digest: "", + Path: "library/image_name", + Domain: "docker.io", + Tag: "latest", + ExplicitTag: "", + }, + "image_name:latest": { + Error: "", + String: "docker.io/library/image_name:latest", + Normalized: "docker.io/library/image_name:latest", + Suggested: "image_name-abcde", + FamiliarName: "image_name", + Protocol: "", + Digest: "", + Path: "library/image_name", + Domain: "docker.io", + Tag: "latest", + ExplicitTag: "latest", + }, + "image_name:foo": { + Error: "", + String: "docker.io/library/image_name:foo", + Normalized: "docker.io/library/image_name:foo", + Suggested: "image_name-abcde", + FamiliarName: "image_name", + Protocol: "", + Digest: "", + Path: "library/image_name", + Domain: "docker.io", + Tag: "foo", + ExplicitTag: "foo", + }, + "image_name@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50": { + Error: "", + String: "docker.io/library/image_name@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Normalized: "docker.io/library/image_name@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Suggested: "image_name-abcde", + FamiliarName: "image_name", + Protocol: "", + Digest: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Path: "library/image_name", + Domain: "docker.io", + Tag: "", + ExplicitTag: "", + }, + "image_name:latest@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50": { + Error: "", + String: "docker.io/library/image_name:latest@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Normalized: "docker.io/library/image_name:latest@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Suggested: "image_name-abcde", + FamiliarName: "image_name", + Protocol: "", + Digest: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", + Path: "library/image_name", + Domain: "docker.io", + Tag: "latest", + ExplicitTag: "latest", + }, + "ghcr.io:1234/image_name": { + Error: "", + String: "ghcr.io:1234/image_name:latest", + Normalized: "ghcr.io:1234/image_name:latest", + Suggested: "image_name-abcde", + FamiliarName: "ghcr.io:1234/image_name", + Protocol: "", + Digest: "", + Path: "image_name", + Domain: "ghcr.io:1234", + Tag: "latest", + ExplicitTag: "", + }, + "ghcr.io/sub_name/image_name": { + Error: "", + String: "ghcr.io/sub_name/image_name:latest", + Normalized: "ghcr.io/sub_name/image_name:latest", + Suggested: "image_name-abcde", + FamiliarName: "ghcr.io/sub_name/image_name", + Protocol: "", + Digest: "", + Path: "sub_name/image_name", + Domain: "ghcr.io", + Tag: "latest", + ExplicitTag: "", + }, + "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze": { + Error: "", + String: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", + Normalized: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", + Suggested: "ipfs-bafkr-abcde", + FamiliarName: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", + Protocol: "ipfs", + Digest: "", + Path: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", + Domain: "", + Tag: "", + ExplicitTag: "", + }, + "ipfs://bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze": { + Error: "", + String: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", + Normalized: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", + Suggested: "ipfs-bafkr-abcde", + FamiliarName: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", + Protocol: "ipfs", + Digest: "", + Path: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", + Domain: "", + Tag: "", + ExplicitTag: "", + }, + "ipfs://ghcr.io/stargz-containers/alpine:3.13-org": { + Error: "", + String: "ghcr.io/stargz-containers/alpine:3.13-org", + Normalized: "ghcr.io/stargz-containers/alpine:3.13-org", + Suggested: "alpine-abcde", + FamiliarName: "ghcr.io/stargz-containers/alpine", + FamiliarMatch: map[string]bool{ + "ghcr.io/stargz-containers/alpine": true, + "*/*/*": true, + "*/*/*:3.13-org": true, + }, + Protocol: "ipfs", + Digest: "", + Path: "stargz-containers/alpine", + Domain: "ghcr.io", + Tag: "3.13-org", + ExplicitTag: "3.13-org", + }, + "ipfs://alpine": { + Error: "", + String: "docker.io/library/alpine:latest", + Normalized: "docker.io/library/alpine:latest", + Suggested: "alpine-abcde", + FamiliarName: "alpine", + Protocol: "ipfs", + Digest: "", + Path: "library/alpine", + Domain: "docker.io", + Tag: "latest", + ExplicitTag: "", + }, + } + + for k, v := range needles { + parsed, err := Parse(k) + if v.Error != "" || err != nil { + assert.Error(t, err, v.Error) + continue + } + assert.Equal(t, parsed.String(), v.String, k) + assert.Equal(t, parsed.SuggestContainerName("abcdefghij"), v.Suggested, k) + assert.Equal(t, parsed.FamiliarName(), v.FamiliarName, k) + for needle, result := range v.FamiliarMatch { + res, err := parsed.FamiliarMatch(needle) + assert.NilError(t, err) + assert.Equal(t, res, result, k) + } + + assert.Equal(t, parsed.Protocol, v.Protocol, k) + assert.Equal(t, parsed.Digest, v.Digest, k) + assert.Equal(t, parsed.Path, v.Path, k) + assert.Equal(t, parsed.Domain, v.Domain, k) + assert.Equal(t, parsed.Tag, v.Tag, k) + assert.Equal(t, parsed.ExplicitTag, v.ExplicitTag, k) + } } From efb9a876b9c649d6837e2ebffb7aeca20fa2e9b7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 14 Oct 2024 16:23:28 -0700 Subject: [PATCH 0828/1066] Cleanup code to use simplified referenceutil package Signed-off-by: apostasie --- cmd/nerdctl/image/image_list.go | 26 +++++++--------- pkg/cmd/builder/build.go | 10 +++--- pkg/cmd/compose/compose.go | 14 ++++++--- pkg/cmd/container/commit.go | 4 +-- pkg/cmd/container/create.go | 7 ++++- pkg/cmd/image/convert.go | 8 ++--- pkg/cmd/image/crypt.go | 8 ++--- pkg/cmd/image/ensure.go | 16 +++++----- pkg/cmd/image/inspect.go | 44 ++++++++++++-------------- pkg/cmd/image/list.go | 4 +-- pkg/cmd/image/pull.go | 9 ++++-- pkg/cmd/image/push.go | 28 ++++++++--------- pkg/cmd/image/tag.go | 4 +-- pkg/idutil/imagewalker/imagewalker.go | 4 +-- pkg/imgutil/filtering.go | 14 ++++----- pkg/imgutil/imgutil.go | 45 ++++++++++----------------- 16 files changed, 119 insertions(+), 126 deletions(-) diff --git a/cmd/nerdctl/image/image_list.go b/cmd/nerdctl/image/image_list.go index d01fbbd13e2..06566f471fd 100644 --- a/cmd/nerdctl/image/image_list.go +++ b/cmd/nerdctl/image/image_list.go @@ -70,49 +70,47 @@ Properties: return imagesCommand } -func processImageListOptions(cmd *cobra.Command, args []string) (types.ImageListOptions, error) { +func processImageListOptions(cmd *cobra.Command, args []string) (*types.ImageListOptions, error) { globalOptions, err := helpers.ProcessRootCmdFlags(cmd) if err != nil { - return types.ImageListOptions{}, err + return nil, err } var filters []string - if len(args) > 0 { - canonicalRef, err := referenceutil.ParseAny(args[0]) + parsedReference, err := referenceutil.Parse(args[0]) if err != nil { - return types.ImageListOptions{}, err + return nil, err } - filters = append(filters, fmt.Sprintf("name==%s", canonicalRef.String())) - filters = append(filters, fmt.Sprintf("name==%s", args[0])) + filters = []string{fmt.Sprintf("name==%s", parsedReference)} } quiet, err := cmd.Flags().GetBool("quiet") if err != nil { - return types.ImageListOptions{}, err + return nil, err } noTrunc, err := cmd.Flags().GetBool("no-trunc") if err != nil { - return types.ImageListOptions{}, err + return nil, err } format, err := cmd.Flags().GetString("format") if err != nil { - return types.ImageListOptions{}, err + return nil, err } var inputFilters []string if cmd.Flags().Changed("filter") { inputFilters, err = cmd.Flags().GetStringSlice("filter") if err != nil { - return types.ImageListOptions{}, err + return nil, err } } digests, err := cmd.Flags().GetBool("digests") if err != nil { - return types.ImageListOptions{}, err + return nil, err } names, err := cmd.Flags().GetBool("names") if err != nil { - return types.ImageListOptions{}, err + return nil, err } - return types.ImageListOptions{ + return &types.ImageListOptions{ GOptions: globalOptions, Quiet: quiet, NoTrunc: noTrunc, diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index f0af327676d..9d1f0f7b05f 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -28,7 +28,6 @@ import ( "strconv" "strings" - distributionref "github.com/distribution/reference" ocispec "github.com/opencontainers/image-spec/specs-go/v1" containerd "github.com/containerd/containerd/v2/client" @@ -42,6 +41,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/nerdctl/v2/pkg/strutil" ) @@ -235,19 +235,19 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option } if tags = strutil.DedupeStrSlice(options.Tag); len(tags) > 0 { ref := tags[0] - named, err := distributionref.ParseNormalizedNamed(ref) + parsedReference, err := referenceutil.Parse(ref) if err != nil { return "", nil, false, "", nil, nil, err } - output += ",name=" + distributionref.TagNameOnly(named).String() + output += ",name=" + parsedReference.String() // pick the first tag and add it to output for idx, tag := range tags { - named, err := distributionref.ParseNormalizedNamed(tag) + parsedReference, err = referenceutil.Parse(tag) if err != nil { return "", nil, false, "", nil, nil, err } - tags[idx] = distributionref.TagNameOnly(named).String() + tags[idx] = parsedReference.String() } } else if len(tags) == 0 { output = output + ",dangling-name-prefix=" diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index a37013e2aff..2709efe2210 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -81,11 +81,11 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op options.VolumeExists = volStore.Exists options.ImageExists = func(ctx context.Context, rawRef string) (bool, error) { - refNamed, err := referenceutil.ParseAny(rawRef) + parsedReference, err := referenceutil.Parse(rawRef) if err != nil { return false, err } - ref := refNamed.String() + ref := parsedReference.String() if _, err := client.ImageService().Get(ctx, ref); err != nil { if errors.Is(err, errdefs.ErrNotFound) { return false, nil @@ -116,8 +116,12 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op Stderr: stderr, } - // IPFS reference - if scheme, ref, err := referenceutil.ParseIPFSRefWithScheme(imageName); err == nil { + parsedReference, err := referenceutil.Parse(imageName) + if err != nil { + return err + } + + if parsedReference.Protocol != "" { var ipfsPath string if ipfsAddress := options.IPFSAddress; ipfsAddress != "" { dir, err := os.MkdirTemp("", "apidirtmp") @@ -130,7 +134,7 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op } ipfsPath = dir } - _, err = ipfs.EnsureImage(ctx, client, scheme, ref, ipfsPath, imgPullOpts) + _, err = ipfs.EnsureImage(ctx, client, string(parsedReference.Protocol), parsedReference.String(), ipfsPath, imgPullOpts) return err } diff --git a/pkg/cmd/container/commit.go b/pkg/cmd/container/commit.go index 45a16ac0227..1e089c7e92c 100644 --- a/pkg/cmd/container/commit.go +++ b/pkg/cmd/container/commit.go @@ -33,7 +33,7 @@ import ( // Commit will commit a container’s file changes or settings into a new image. func Commit(ctx context.Context, client *containerd.Client, rawRef string, req string, options types.ContainerCommitOptions) error { - named, err := referenceutil.ParseDockerRef(rawRef) + parsedReference, err := referenceutil.Parse(rawRef) if err != nil { return err } @@ -46,7 +46,7 @@ func Commit(ctx context.Context, client *containerd.Client, rawRef string, req s opts := &commit.Opts{ Author: options.Author, Message: options.Message, - Ref: named.String(), + Ref: parsedReference.String(), Pause: options.Pause, Changes: changes, } diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index ec23038274a..a786813704b 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -272,7 +272,12 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa if ensuredImage != nil { imageRef = ensuredImage.Ref } - options.Name = referenceutil.SuggestContainerName(imageRef, id) + parsedReference, err := referenceutil.Parse(imageRef) + // Ignore cases where the imageRef is "" + if err != nil && imageRef != "" { + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err + } + options.Name = parsedReference.SuggestContainerName(id) } if options.Name != "" { containerNameStore, err = namestore.New(dataStore, options.GOptions.Namespace) diff --git a/pkg/cmd/image/convert.go b/pkg/cmd/image/convert.go index e320a421be2..fd6d86f1a52 100644 --- a/pkg/cmd/image/convert.go +++ b/pkg/cmd/image/convert.go @@ -57,17 +57,17 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa return errors.New("src and target image need to be specified") } - srcNamed, err := referenceutil.ParseAny(srcRawRef) + parsedReference, err := referenceutil.Parse(srcRawRef) if err != nil { return err } - srcRef := srcNamed.String() + srcRef := parsedReference.String() - targetNamed, err := referenceutil.ParseDockerRef(targetRawRef) + parsedReference, err = referenceutil.Parse(targetRawRef) if err != nil { return err } - targetRef := targetNamed.String() + targetRef := parsedReference.String() platMC, err := platformutil.NewMatchComparer(options.AllPlatforms, options.Platforms) if err != nil { diff --git a/pkg/cmd/image/crypt.go b/pkg/cmd/image/crypt.go index 105821eb22f..68a18b43117 100644 --- a/pkg/cmd/image/crypt.go +++ b/pkg/cmd/image/crypt.go @@ -40,17 +40,17 @@ func Crypt(ctx context.Context, client *containerd.Client, srcRawRef, targetRawR return errors.New("src and target image need to be specified") } - srcNamed, err := referenceutil.ParseAny(srcRawRef) + parsedRerefence, err := referenceutil.Parse(srcRawRef) if err != nil { return err } - srcRef := srcNamed.String() + srcRef := parsedRerefence.String() - targetNamed, err := referenceutil.ParseDockerRef(targetRawRef) + parsedRerefence, err = referenceutil.Parse(targetRawRef) if err != nil { return err } - targetRef := targetNamed.String() + targetRef := parsedRerefence.String() platMC, err := platformutil.NewMatchComparer(options.AllPlatforms, options.Platforms) if err != nil { diff --git a/pkg/cmd/image/ensure.go b/pkg/cmd/image/ensure.go index e622ba04e62..de2634871ea 100644 --- a/pkg/cmd/image/ensure.go +++ b/pkg/cmd/image/ensure.go @@ -22,7 +22,6 @@ import ( "net/http" "os" - distributionref "github.com/distribution/reference" ocispec "github.com/opencontainers/image-spec/specs-go/v1" containerd "github.com/containerd/containerd/v2/client" @@ -35,6 +34,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/v2/pkg/imgutil/fetch" "github.com/containerd/nerdctl/v2/pkg/platformutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) func EnsureAllContent(ctx context.Context, client *containerd.Client, srcName string, options types.GlobalCommandOptions) error { @@ -61,12 +61,10 @@ func EnsureAllContent(ctx context.Context, client *containerd.Client, srcName st } func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, target ocispec.Descriptor, platform ocispec.Platform, options types.GlobalCommandOptions) error { - - named, err := distributionref.ParseDockerRef(rawRef) + parsedReference, err := referenceutil.Parse(rawRef) if err != nil { return err } - refDomain := distributionref.Domain(named) // if platform == nil { // platform = platforms.DefaultSpec() //} @@ -82,11 +80,11 @@ func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, ta // Get a resolver var dOpts []dockerconfigresolver.Opt if options.InsecureRegistry { - log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain) + log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", parsedReference.Domain) dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) } dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(options.HostsDir)) - resolver, err := dockerconfigresolver.New(ctx, refDomain, dOpts...) + resolver, err := dockerconfigresolver.New(ctx, parsedReference.Domain, dOpts...) if err != nil { return err } @@ -105,16 +103,16 @@ func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, ta return err } if options.InsecureRegistry { - log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", refDomain) + log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", parsedReference.Domain) dOpts = append(dOpts, dockerconfigresolver.WithPlainHTTP(true)) - resolver, err = dockerconfigresolver.New(ctx, refDomain, dOpts...) + resolver, err = dockerconfigresolver.New(ctx, parsedReference.Domain, dOpts...) if err != nil { return err } config.Resolver = resolver return fetch.Fetch(ctx, client, rawRef, config) } - log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain) + log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", parsedReference.Domain) log.G(ctx).Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)") } diff --git a/pkg/cmd/image/inspect.go b/pkg/cmd/image/inspect.go index be8c1515080..1627cc4b14d 100644 --- a/pkg/cmd/image/inspect.go +++ b/pkg/cmd/image/inspect.go @@ -23,8 +23,6 @@ import ( "strings" "time" - "github.com/distribution/reference" - containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" @@ -39,22 +37,16 @@ import ( func inspectIdentifier(ctx context.Context, client *containerd.Client, identifier string) ([]images.Image, string, string, error) { // Figure out what we have here - digest, tag, name - parsedIdentifier, err := referenceutil.ParseAnyReference(identifier) + parsedReference, err := referenceutil.Parse(identifier) if err != nil { - return nil, "", "", fmt.Errorf("invalid identifier %s: %w", identifier, err) + return nil, "", "", err } digest := "" - if identifierDigest, hasDigest := parsedIdentifier.(reference.Digested); hasDigest { - digest = identifierDigest.Digest().String() - } - name := "" - if identifierName, hasName := parsedIdentifier.(reference.Named); hasName { - name = identifierName.Name() - } - tag := "latest" - if identifierTag, hasTag := parsedIdentifier.(reference.Tagged); hasTag && identifierTag.Tag() != "" { - tag = identifierTag.Tag() + if parsedReference.Digest != "" { + digest = parsedReference.Digest.String() } + name := parsedReference.Name() + tag := parsedReference.Tag // Initialize filters var filters []string @@ -136,26 +128,26 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin } // If dockercompat: does the candidate have a name? Get it if so - candidateRef, err := referenceutil.ParseAnyReference(candidateNativeImage.Image.Name) + parsedReference, err := referenceutil.Parse(candidateNativeImage.Image.Name) if err != nil { log.G(ctx).WithError(err).WithField("name", candidateNativeImage.Image.Name).Error("the found image has an unparsable name") continue } - parsedCandidateNameTag, candidateHasAName := candidateRef.(reference.NamedTagged) // If we were ALSO asked for a specific name on top of the digest, we need to make sure we keep only the image with that name if requestedName != "" { // If the candidate did not have a name, then we should ignore this one and continue - if !candidateHasAName { + if parsedReference.Name() == "" { continue } // Otherwise, the candidate has a name. If it is the one we want, store it and continue, otherwise, fall through - candidateTag := parsedCandidateNameTag.Tag() - if candidateTag == "" { - candidateTag = "latest" + candidateTag := parsedReference.Tag + // If the name had a digest, an empty tag is not normalized to latest, so, account for that here + if requestedTag == "" { + requestedTag = "latest" } - if parsedCandidateNameTag.Name() == requestedName && candidateTag == requestedTag { + if parsedReference.Name() == requestedName && candidateTag == requestedTag { validatedImage, err = dockercompat.ImageFromNative(candidateNativeImage) if err != nil { log.G(ctx).WithError(err).WithField("name", candidateNativeImage.Image.Name).Error("could not get a docker compat version of the native image") @@ -175,9 +167,13 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin // - we got a request by digest, but we already had the image stored // - we got a request by name, and the name of the candidate did not match the requested name // Now, check if the candidate has a name - if it does, populate repoTags and repoDigests - if candidateHasAName { - repoTags = append(repoTags, fmt.Sprintf("%s:%s", reference.FamiliarName(parsedCandidateNameTag), parsedCandidateNameTag.Tag())) - repoDigests = append(repoDigests, fmt.Sprintf("%s@%s", reference.FamiliarName(parsedCandidateNameTag), candidateImage.Target.Digest.String())) + if parsedReference.Name() != "" { + tag := parsedReference.Tag + if tag == "" { + tag = "latest" + } + repoTags = append(repoTags, fmt.Sprintf("%s:%s", parsedReference.FamiliarName(), tag)) + repoDigests = append(repoDigests, fmt.Sprintf("%s@%s", parsedReference.FamiliarName(), candidateImage.Target.Digest.String())) } } diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 2b10a63d54c..19905645c59 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -47,7 +47,7 @@ import ( ) // ListCommandHandler `List` and print images matching filters in `options`. -func ListCommandHandler(ctx context.Context, client *containerd.Client, options types.ImageListOptions) error { +func ListCommandHandler(ctx context.Context, client *containerd.Client, options *types.ImageListOptions) error { imageList, err := List(ctx, client, options.Filters, options.NameAndRefFilter) if err != nil { return err @@ -126,7 +126,7 @@ type imagePrintable struct { Platform string // nerdctl extension } -func printImages(ctx context.Context, client *containerd.Client, imageList []images.Image, options types.ImageListOptions) error { +func printImages(ctx context.Context, client *containerd.Client, imageList []images.Image, options *types.ImageListOptions) error { w := options.Stdout digestsFlag := options.Digests if options.Format == "wide" { diff --git a/pkg/cmd/image/pull.go b/pkg/cmd/image/pull.go index c714c47418d..1d943c9b62d 100644 --- a/pkg/cmd/image/pull.go +++ b/pkg/cmd/image/pull.go @@ -45,7 +45,12 @@ func Pull(ctx context.Context, client *containerd.Client, rawRef string, options func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, options types.ImagePullOptions) (*imgutil.EnsuredImage, error) { var ensured *imgutil.EnsuredImage - if scheme, ref, err := referenceutil.ParseIPFSRefWithScheme(rawRef); err == nil { + parsedReference, err := referenceutil.Parse(rawRef) + if err != nil { + return nil, err + } + + if parsedReference.Protocol != "" { if options.VerifyOptions.Provider != "none" { return nil, errors.New("--verify flag is not supported on IPFS as of now") } @@ -63,7 +68,7 @@ func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, ipfsPath = dir } - ensured, err = ipfs.EnsureImage(ctx, client, scheme, ref, ipfsPath, options) + ensured, err = ipfs.EnsureImage(ctx, client, string(parsedReference.Protocol), parsedReference.String(), ipfsPath, options) if err != nil { return nil, err } diff --git a/pkg/cmd/image/push.go b/pkg/cmd/image/push.go index 03966feec1b..a940f832f99 100644 --- a/pkg/cmd/image/push.go +++ b/pkg/cmd/image/push.go @@ -25,7 +25,6 @@ import ( "os" "path/filepath" - distributionref "github.com/distribution/reference" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -55,19 +54,20 @@ import ( // Push pushes an image specified by `rawRef`. func Push(ctx context.Context, client *containerd.Client, rawRef string, options types.ImagePushOptions) error { - if scheme, ref, err := referenceutil.ParseIPFSRefWithScheme(rawRef); err == nil { - if scheme != "ipfs" { - return fmt.Errorf("ipfs scheme is only supported but got %q", scheme) - } - log.G(ctx).Infof("pushing image %q to IPFS", ref) + parsedReference, err := referenceutil.Parse(rawRef) + if err != nil { + return err + } - parsedRef, err := distributionref.ParseDockerRef(ref) - if err != nil { - return err + if parsedReference.Protocol != "" { + if parsedReference.Protocol != referenceutil.IPFSProtocol { + return fmt.Errorf("ipfs scheme is only supported but got %q", parsedReference.Protocol) } + log.G(ctx).Infof("pushing image %q to IPFS", parsedReference) // Ensure all the layers are here: https://github.com/containerd/nerdctl/issues/3489 - err = EnsureAllContent(ctx, client, parsedRef.String(), options.GOptions) + // XXX what if the image is a CID, or only otherwise available on ipfs? + err = EnsureAllContent(ctx, client, parsedReference.String(), options.GOptions) if err != nil { return err } @@ -89,7 +89,7 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options if options.Estargz { layerConvert = eStargzConvertFunc() } - c, err := ipfs.Push(ctx, client, parsedRef.String(), layerConvert, options.AllPlatforms, options.Platforms, options.IpfsEnsureImage, ipfsPath) + c, err := ipfs.Push(ctx, client, parsedReference.String(), layerConvert, options.AllPlatforms, options.Platforms, options.IpfsEnsureImage, ipfsPath) if err != nil { log.G(ctx).WithError(err).Warnf("ipfs push failed") return err @@ -98,12 +98,12 @@ func Push(ctx context.Context, client *containerd.Client, rawRef string, options return nil } - named, err := distributionref.ParseDockerRef(rawRef) + parsedReference, err = referenceutil.Parse(rawRef) if err != nil { return err } - ref := named.String() - refDomain := distributionref.Domain(named) + ref := parsedReference.String() + refDomain := parsedReference.Domain platMC, err := platformutil.NewMatchComparer(options.AllPlatforms, options.Platforms) if err != nil { diff --git a/pkg/cmd/image/tag.go b/pkg/cmd/image/tag.go index 70f68acae84..5323080f745 100644 --- a/pkg/cmd/image/tag.go +++ b/pkg/cmd/image/tag.go @@ -49,7 +49,7 @@ func Tag(ctx context.Context, client *containerd.Client, options types.ImageTagO return fmt.Errorf("%s: not found", options.Source) } - target, err := referenceutil.ParseDockerRef(options.Target) + parsedReference, err := referenceutil.Parse(options.Target) if err != nil { return err } @@ -72,7 +72,7 @@ func Tag(ctx context.Context, client *containerd.Client, options types.ImageTagO return err } - img.Name = target.String() + img.Name = parsedReference.String() if _, err = imageService.Create(ctx, img); err != nil { if errdefs.IsAlreadyExists(err) { if err = imageService.Delete(ctx, img.Name); err != nil { diff --git a/pkg/idutil/imagewalker/imagewalker.go b/pkg/idutil/imagewalker/imagewalker.go index f6effd0fa0a..df948a48f01 100644 --- a/pkg/idutil/imagewalker/imagewalker.go +++ b/pkg/idutil/imagewalker/imagewalker.go @@ -50,8 +50,8 @@ type ImageWalker struct { // Returns the number of the found entries. func (w *ImageWalker) Walk(ctx context.Context, req string) (int, error) { var filters []string - if canonicalRef, err := referenceutil.ParseAny(req); err == nil { - filters = append(filters, fmt.Sprintf("name==%s", canonicalRef.String())) + if parsedReference, err := referenceutil.Parse(req); err == nil { + filters = append(filters, fmt.Sprintf("name==%s", parsedReference.String())) } filters = append(filters, fmt.Sprintf("name==%s", req), diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index 473a382642f..f1a5315a314 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -24,8 +24,6 @@ import ( "strings" "time" - distributionref "github.com/distribution/reference" - containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" @@ -80,19 +78,19 @@ func ParseFilters(filters []string) (*Filters, error) { } f.Dangling = &isDangling } else if tempFilterToken[0] == FilterBeforeType { - canonicalRef, err := referenceutil.ParseAny(tempFilterToken[1]) + parsedReference, err := referenceutil.Parse(tempFilterToken[1]) if err != nil { return nil, err } - f.Before = append(f.Before, fmt.Sprintf("name==%s", canonicalRef.String())) + f.Before = append(f.Before, fmt.Sprintf("name==%s", parsedReference.String())) f.Before = append(f.Before, fmt.Sprintf("name==%s", tempFilterToken[1])) } else if tempFilterToken[0] == FilterSinceType { - canonicalRef, err := referenceutil.ParseAny(tempFilterToken[1]) + parsedReference, err := referenceutil.Parse(tempFilterToken[1]) if err != nil { return nil, err } - f.Since = append(f.Since, fmt.Sprintf("name==%s", canonicalRef.String())) + f.Since = append(f.Since, fmt.Sprintf("name==%s", parsedReference.String())) f.Since = append(f.Since, fmt.Sprintf("name==%s", tempFilterToken[1])) } else if tempFilterToken[0] == FilterUntilType { if len(tempFilterToken[0]) == 0 { @@ -311,13 +309,13 @@ func matchesAllLabels(imageCfgLabels map[string]string, filterLabels map[string] func matchesReferences(image images.Image, referencePatterns []string) (bool, error) { var matches int - reference, err := distributionref.ParseAnyReference(image.Name) + parsedReference, err := referenceutil.Parse(image.Name) if err != nil { return false, err } for _, pattern := range referencePatterns { - familiarMatch, err := distributionref.FamiliarMatch(pattern, reference) + familiarMatch, err := parsedReference.FamiliarMatch(pattern) if err != nil { return false, err } diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 3b042c9fb63..7a6d01acb23 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -24,7 +24,6 @@ import ( "net/http" "reflect" - distributionref "github.com/distribution/reference" "github.com/opencontainers/image-spec/identity" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -44,6 +43,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/idutil/imagewalker" "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/v2/pkg/imgutil/pull" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) // EnsuredImage contains the image existed in containerd and its metadata. @@ -61,7 +61,7 @@ type PullMode = string // GetExistingImage returns the specified image if exists in containerd. Return errdefs.NotFound() if not exists. func GetExistingImage(ctx context.Context, client *containerd.Client, snapshotter, rawRef string, platform ocispec.Platform) (*EnsuredImage, error) { var res *EnsuredImage - imagewalker := &imagewalker.ImageWalker{ + imgwalker := &imagewalker.ImageWalker{ Client: client, OnFound: func(ctx context.Context, found imagewalker.Found) error { if res != nil { @@ -89,7 +89,7 @@ func GetExistingImage(ctx context.Context, client *containerd.Client, snapshotte return nil }, } - count, err := imagewalker.Walk(ctx, rawRef) + count, err := imgwalker.Walk(ctx, rawRef) if err != nil { return nil, err } @@ -126,40 +126,38 @@ func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, return nil, fmt.Errorf("image not available: %q", rawRef) } - named, err := distributionref.ParseDockerRef(rawRef) + parsedReference, err := referenceutil.Parse(rawRef) if err != nil { return nil, err } - ref := named.String() - refDomain := distributionref.Domain(named) var dOpts []dockerconfigresolver.Opt if options.GOptions.InsecureRegistry { - log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain) + log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", parsedReference.Domain) dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) } dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(options.GOptions.HostsDir)) - resolver, err := dockerconfigresolver.New(ctx, refDomain, dOpts...) + resolver, err := dockerconfigresolver.New(ctx, parsedReference.Domain, dOpts...) if err != nil { return nil, err } - img, err := PullImage(ctx, client, resolver, ref, options) + img, err := PullImage(ctx, client, resolver, parsedReference.String(), options) if err != nil { // In some circumstance (e.g. people just use 80 port to support pure http), the error will contain message like "dial tcp : connection refused". if !errors.Is(err, http.ErrSchemeMismatch) && !errutil.IsErrConnectionRefused(err) { return nil, err } if options.GOptions.InsecureRegistry { - log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", refDomain) + log.G(ctx).WithError(err).Warnf("server %q does not seem to support HTTPS, falling back to plain HTTP", parsedReference.Domain) dOpts = append(dOpts, dockerconfigresolver.WithPlainHTTP(true)) - resolver, err = dockerconfigresolver.New(ctx, refDomain, dOpts...) + resolver, err = dockerconfigresolver.New(ctx, parsedReference.Domain, dOpts...) if err != nil { return nil, err } - return PullImage(ctx, client, resolver, ref, options) + return PullImage(ctx, client, resolver, parsedReference.String(), options) } - log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", refDomain) + log.G(ctx).WithError(err).Errorf("server %q does not seem to support HTTPS", parsedReference.Domain) log.G(ctx).Info("Hint: you may want to try --insecure-registry to allow plain HTTP (if you are in a trusted network)") return nil, err @@ -169,25 +167,23 @@ func EnsureImage(ctx context.Context, client *containerd.Client, rawRef string, // ResolveDigest resolves `rawRef` and returns its descriptor digest. func ResolveDigest(ctx context.Context, rawRef string, insecure bool, hostsDirs []string) (string, error) { - named, err := distributionref.ParseDockerRef(rawRef) + parsedReference, err := referenceutil.Parse(rawRef) if err != nil { return "", err } - ref := named.String() - refDomain := distributionref.Domain(named) var dOpts []dockerconfigresolver.Opt if insecure { - log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", refDomain) + log.G(ctx).Warnf("skipping verifying HTTPS certs for %q", parsedReference.Domain) dOpts = append(dOpts, dockerconfigresolver.WithSkipVerifyCerts(true)) } dOpts = append(dOpts, dockerconfigresolver.WithHostsDirs(hostsDirs)) - resolver, err := dockerconfigresolver.New(ctx, refDomain, dOpts...) + resolver, err := dockerconfigresolver.New(ctx, parsedReference.Domain, dOpts...) if err != nil { return "", err } - _, desc, err := resolver.Resolve(ctx, ref) + _, desc, err := resolver.Resolve(ctx, parsedReference.String()) if err != nil { return "", err } @@ -362,20 +358,13 @@ func ReadImageConfig(ctx context.Context, img containerd.Image) (ocispec.Image, func ParseRepoTag(imgName string) (string, string) { log.L.Debugf("raw image name=%q", imgName) - ref, err := distributionref.ParseDockerRef(imgName) + parsedReference, err := referenceutil.Parse(imgName) if err != nil { log.L.WithError(err).Debugf("unparsable image name %q", imgName) return "", "" } - var tag string - - if tagged, ok := ref.(distributionref.Tagged); ok { - tag = tagged.Tag() - } - repository := distributionref.FamiliarName(ref) - - return repository, tag + return parsedReference.FamiliarName(), parsedReference.Tag } // ResourceUsage will return: From 496b2f05a0baf82f0eddcb11fb93837b407af016 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 14 Oct 2024 21:12:14 -0700 Subject: [PATCH 0829/1066] Consistently enforce rmi -f in tests cleanup Signed-off-by: apostasie --- cmd/nerdctl/image/image_convert_linux_test.go | 12 ++++++------ cmd/nerdctl/image/image_list_test.go | 6 +++--- cmd/nerdctl/image/image_load_test.go | 2 +- cmd/nerdctl/image/image_prune_test.go | 8 ++++---- cmd/nerdctl/image/image_pull_linux_test.go | 4 ++-- cmd/nerdctl/image/image_push_linux_test.go | 16 ++++++++-------- cmd/nerdctl/ipfs/ipfs_compose_linux_test.go | 10 +++++----- cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go | 4 ++-- cmd/nerdctl/ipfs/ipfs_registry_linux_test.go | 8 ++++---- cmd/nerdctl/ipfs/ipfs_simple_linux_test.go | 16 ++++++++-------- 10 files changed, 43 insertions(+), 43 deletions(-) diff --git a/cmd/nerdctl/image/image_convert_linux_test.go b/cmd/nerdctl/image/image_convert_linux_test.go index 1b16d079bde..5b21487ce81 100644 --- a/cmd/nerdctl/image/image_convert_linux_test.go +++ b/cmd/nerdctl/image/image_convert_linux_test.go @@ -42,7 +42,7 @@ func TestImageConvert(t *testing.T) { { Description: "esgz", Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier("converted-image")) + helpers.Anyhow("rmi", "-f", data.Identifier("converted-image")) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("image", "convert", "--oci", "--estargz", @@ -56,7 +56,7 @@ func TestImageConvert(t *testing.T) { test.Binary("nydus-image"), ), Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier("converted-image")) + helpers.Anyhow("rmi", "-f", data.Identifier("converted-image")) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("image", "convert", "--oci", "--nydus", @@ -67,7 +67,7 @@ func TestImageConvert(t *testing.T) { { Description: "zstd", Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier("converted-image")) + helpers.Anyhow("rmi", "-f", data.Identifier("converted-image")) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("image", "convert", "--oci", "--zstd", "--zstd-compression-level", "3", @@ -78,7 +78,7 @@ func TestImageConvert(t *testing.T) { { Description: "zstdchunked", Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier("converted-image")) + helpers.Anyhow("rmi", "-f", data.Identifier("converted-image")) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("image", "convert", "--oci", "--zstdchunked", "--zstdchunked-compression-level", "3", @@ -120,10 +120,10 @@ func TestImageConvertNydusVerify(t *testing.T) { helpers.Ensure("push", data.Get(remoteImageKey)) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier("converted-image")) + helpers.Anyhow("rmi", "-f", data.Identifier("converted-image")) if registry != nil { registry.Cleanup(nil) - helpers.Anyhow("rmi", data.Get(remoteImageKey)) + helpers.Anyhow("rmi", "-f", data.Get(remoteImageKey)) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index 76e1095a081..1badf3c617f 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -141,9 +141,9 @@ RUN echo "actually creating a layer so that docker sets the createdAt time" data.Set("buildCtx", buildCtx) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", "taggedimage:one-fragment-one") - helpers.Anyhow("rmi", "taggedimage:two-fragment-two") - helpers.Anyhow("rmi", data.Identifier()) + helpers.Anyhow("rmi", "-f", "taggedimage:one-fragment-one") + helpers.Anyhow("rmi", "-f", "taggedimage:two-fragment-two") + helpers.Anyhow("rmi", "-f", data.Identifier()) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { data.Set("builtImageID", data.Identifier()) diff --git a/cmd/nerdctl/image/image_load_test.go b/cmd/nerdctl/image/image_load_test.go index 97f31c04b6e..452a0e18729 100644 --- a/cmd/nerdctl/image/image_load_test.go +++ b/cmd/nerdctl/image/image_load_test.go @@ -43,7 +43,7 @@ func TestLoadStdinFromPipe(t *testing.T) { helpers.Ensure("rmi", "-f", data.Identifier()) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Identifier()) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { cmd := helpers.Command("load") diff --git a/cmd/nerdctl/image/image_prune_test.go b/cmd/nerdctl/image/image_prune_test.go index c6534253698..e3c66b8bf10 100644 --- a/cmd/nerdctl/image/image_prune_test.go +++ b/cmd/nerdctl/image/image_prune_test.go @@ -53,7 +53,7 @@ func TestImagePrune(t *testing.T) { nerdtest.Build, ), Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Identifier()) }, Setup: func(data test.Data, helpers test.Helpers) { dockerfile := fmt.Sprintf(`FROM %s @@ -95,7 +95,7 @@ func TestImagePrune(t *testing.T) { // Cannot use a custom namespace with buildkitd right now, so, no parallel it is NoParallel: true, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Identifier()) helpers.Anyhow("rm", "-f", data.Identifier()) }, Setup: func(data test.Data, helpers test.Helpers) { @@ -138,7 +138,7 @@ func TestImagePrune(t *testing.T) { // Cannot use a custom namespace with buildkitd right now, so, no parallel it is NoParallel: true, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Identifier()) }, Setup: func(data test.Data, helpers test.Helpers) { dockerfile := fmt.Sprintf(`FROM %s @@ -177,7 +177,7 @@ LABEL version=0.1`, testutil.CommonImage) // Cannot use a custom namespace with buildkitd right now, so, no parallel it is NoParallel: true, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Identifier()) }, Setup: func(data test.Data, helpers test.Helpers) { dockerfile := fmt.Sprintf(`FROM %s diff --git a/cmd/nerdctl/image/image_pull_linux_test.go b/cmd/nerdctl/image/image_pull_linux_test.go index ff9ee84fdd8..d2d624671fd 100644 --- a/cmd/nerdctl/image/image_pull_linux_test.go +++ b/cmd/nerdctl/image/image_pull_linux_test.go @@ -176,7 +176,7 @@ func TestImagePullSoci(t *testing.T) { helpers.Ensure("--snapshotter=soci", "pull", testutil.FfmpegSociImage) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", testutil.FfmpegSociImage) + helpers.Anyhow("rmi", "-f", testutil.FfmpegSociImage) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Custom("mount") @@ -210,7 +210,7 @@ func TestImagePullSoci(t *testing.T) { helpers.Ensure("--snapshotter=soci", "pull", testutil.FfmpegSociImage) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", testutil.FfmpegSociImage) + helpers.Anyhow("rmi", "-f", testutil.FfmpegSociImage) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Custom("mount") diff --git a/cmd/nerdctl/image/image_push_linux_test.go b/cmd/nerdctl/image/image_push_linux_test.go index 9d3ae4d8598..1cd38bba7fd 100644 --- a/cmd/nerdctl/image/image_push_linux_test.go +++ b/cmd/nerdctl/image/image_push_linux_test.go @@ -72,7 +72,7 @@ func TestPush(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get("testImageRef") != "" { - helpers.Anyhow("rmi", data.Get("testImageRef")) + helpers.Anyhow("rmi", "-f", data.Get("testImageRef")) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -92,7 +92,7 @@ func TestPush(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get("testImageRef") != "" { - helpers.Anyhow("rmi", data.Get("testImageRef")) + helpers.Anyhow("rmi", "-f", data.Get("testImageRef")) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -126,7 +126,7 @@ func TestPush(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get("testImageRef") != "" { - helpers.Anyhow("rmi", data.Get("testImageRef")) + helpers.Anyhow("rmi", "-f", data.Get("testImageRef")) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -149,7 +149,7 @@ func TestPush(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get("testImageRef") != "" { - helpers.Anyhow("rmi", data.Get("testImageRef")) + helpers.Anyhow("rmi", "-f", data.Get("testImageRef")) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -172,7 +172,7 @@ func TestPush(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get("testImageRef") != "" { - helpers.Anyhow("rmi", data.Get("testImageRef")) + helpers.Anyhow("rmi", "-f", data.Get("testImageRef")) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -192,7 +192,7 @@ func TestPush(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get("testImageRef") != "" { - helpers.Anyhow("rmi", data.Get("testImageRef")) + helpers.Anyhow("rmi", "-f", data.Get("testImageRef")) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -224,7 +224,7 @@ func TestPush(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get("testImageRef") != "" { - helpers.Anyhow("rmi", data.Get("testImageRef")) + helpers.Anyhow("rmi", "-f", data.Get("testImageRef")) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -259,7 +259,7 @@ func TestPush(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get("testImageRef") != "" { - helpers.Anyhow("rmi", data.Get("testImageRef")) + helpers.Anyhow("rmi", "-f", data.Get("testImageRef")) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { diff --git a/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go index 7619e0b0591..5c4cd76fd66 100644 --- a/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go @@ -72,8 +72,8 @@ func TestIPFSCompNoBuild(t *testing.T) { ipfsRegistry.Cleanup(data, helpers) } // Speeding up repeat tests... - helpers.Anyhow("rmi", testutil.WordpressImage) - helpers.Anyhow("rmi", testutil.MariaDBImage) + helpers.Anyhow("rmi", "-f", testutil.WordpressImage) + helpers.Anyhow("rmi", "-f", testutil.MariaDBImage) } testCase.Run(t) @@ -127,8 +127,8 @@ func subtestTestIPFSCompNoB(t *testing.T, stargz bool, byAddr bool) *test.Case { // Deliberately electing to not remove them here so that we can parallelize and cut down the running time /* if data.Get(mariaImageCIDKey) != "" { - helpers.Anyhow("rmi", data.Get(mariaImageCIDKey)) - helpers.Anyhow("rmi", data.Get(wordpressImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(mariaImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(wordpressImageCIDKey)) } */ } @@ -233,7 +233,7 @@ COPY index.html /usr/share/nginx/html/index.html testCase.Cleanup = func(data test.Data, helpers test.Helpers) { if ipfsServer != nil { // Close the server once done - helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(mainImageCIDKey)) ipfsServer.Run(nil) } if comp != nil { diff --git a/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go b/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go index 3738ceb4514..c65883e7681 100644 --- a/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go @@ -68,7 +68,7 @@ func TestIPFSAddrWithKubo(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get(mainImageCIDKey) != "" { - helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(mainImageCIDKey)) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -91,7 +91,7 @@ func TestIPFSAddrWithKubo(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get(mainImageCIDKey) != "" { - helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(mainImageCIDKey)) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { diff --git a/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go index 63a461361cc..b6b032dc965 100644 --- a/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go @@ -89,7 +89,7 @@ func TestIPFSNerdctlRegistry(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get(ipfsImageURLKey) != "" { - helpers.Anyhow("rmi", data.Get(ipfsImageURLKey)) + helpers.Anyhow("rmi", "-f", data.Get(ipfsImageURLKey)) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -107,7 +107,7 @@ func TestIPFSNerdctlRegistry(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get(ipfsImageURLKey) != "" { - helpers.Anyhow("rmi", data.Get(ipfsImageURLKey)) + helpers.Anyhow("rmi", "-f", data.Get(ipfsImageURLKey)) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -120,9 +120,9 @@ func TestIPFSNerdctlRegistry(t *testing.T) { NoParallel: true, Require: nerdtest.Build, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", data.Identifier("built-image")) + helpers.Anyhow("rmi", "-f", data.Identifier("built-image")) if data.Get(ipfsImageURLKey) != "" { - helpers.Anyhow("rmi", data.Get(ipfsImageURLKey)) + helpers.Anyhow("rmi", "-f", data.Get(ipfsImageURLKey)) } }, Setup: func(data test.Data, helpers test.Helpers) { diff --git a/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go b/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go index e18acc332ee..cddc1805d30 100644 --- a/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go @@ -55,7 +55,7 @@ func TestIPFSSimple(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get(mainImageCIDKey) != "" { - helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(mainImageCIDKey)) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -76,7 +76,7 @@ func TestIPFSSimple(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get(mainImageCIDKey) != "" { - helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(mainImageCIDKey)) } }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -105,10 +105,10 @@ func TestIPFSSimple(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", data.Identifier("commit-container")) - helpers.Anyhow("rmi", data.Identifier("commit-image")) + helpers.Anyhow("rmi", "-f", data.Identifier("commit-image")) if data.Get(mainImageCIDKey) != "" { - helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) - helpers.Anyhow("rmi", data.Get(transformedImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(mainImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(transformedImageCIDKey)) } }, @@ -143,10 +143,10 @@ func TestIPFSSimple(t *testing.T) { }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", data.Identifier("commit-container")) - helpers.Anyhow("rmi", data.Identifier("commit-image")) + helpers.Anyhow("rmi", "-f", data.Identifier("commit-image")) if data.Get(mainImageCIDKey) != "" { - helpers.Anyhow("rmi", data.Get(mainImageCIDKey)) - helpers.Anyhow("rmi", data.Get(transformedImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(mainImageCIDKey)) + helpers.Anyhow("rmi", "-f", data.Get(transformedImageCIDKey)) } }, From fa39963afbb73708fb4916e98d658577656795c5 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 14 Oct 2024 19:00:57 -0700 Subject: [PATCH 0830/1066] Global compose lock Signed-off-by: apostasie --- pkg/cmd/compose/compose.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index a37013e2aff..71c76c5d332 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -35,14 +35,31 @@ import ( "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/ipfs" + "github.com/containerd/nerdctl/v2/pkg/lockutil" "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/nerdctl/v2/pkg/signutil" "github.com/containerd/nerdctl/v2/pkg/strutil" ) +//nolint:unused +var locked *os.File + // New returns a new *composer.Composer. func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, options composer.Options, stdout, stderr io.Writer) (*composer.Composer, error) { + // Compose right now cannot be made safe to use concurrently, as we shell out to nerdctl for multiple operations, + // preventing us from using the lock mechanisms from the API. + // This here imposes a global lock, effectively preventing multiple compose commands from being run in parallel and + // preventing some of the problems with concurrent execution. + // This should be removed once we have better, in-depth solutions to make this concurrency safe. + // Note that we do not close the lock explicitly. Instead, the lock will get released when the `locked` global + // variable will get collected and the file descriptor closed (eg: when the binary exits). + var err error + locked, err = lockutil.Lock(globalOptions.DataRoot) + if err != nil { + return nil, err + } + cniEnv, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath, netutil.WithNamespace(globalOptions.Namespace), netutil.WithDefaultNetwork()) if err != nil { return nil, err From 7fab74c348fcd98ec8b73ea2d794475a4f3a5935 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 14 Oct 2024 21:07:24 -0700 Subject: [PATCH 0831/1066] Lint fixes Signed-off-by: apostasie --- pkg/mountutil/mountutil_test.go | 1 + pkg/netutil/netutil.go | 1 + pkg/testutil/testutil_freebsd.go | 1 + 3 files changed, 3 insertions(+) diff --git a/pkg/mountutil/mountutil_test.go b/pkg/mountutil/mountutil_test.go index 619f4269c66..85f5ee3bff9 100644 --- a/pkg/mountutil/mountutil_test.go +++ b/pkg/mountutil/mountutil_test.go @@ -34,4 +34,5 @@ func (mv *MockVolumeStore) CreateWithoutLock(name string, labels []string) (*nat return &native.Volume{Name: "test_volume", Mountpoint: "/test/volume"}, nil } +//nolint:unused var mockVolumeStore = &MockVolumeStore{} diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 43439c592ec..a53490fec9a 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -627,6 +627,7 @@ func structToMap(in interface{}) (map[string]interface{}, error) { } // ParseMTU parses the mtu option +// nolint:unused func parseMTU(mtu string) (int, error) { if mtu == "" { return 0, nil // default diff --git a/pkg/testutil/testutil_freebsd.go b/pkg/testutil/testutil_freebsd.go index 9cbded4e258..5c0fb9ba293 100644 --- a/pkg/testutil/testutil_freebsd.go +++ b/pkg/testutil/testutil_freebsd.go @@ -32,6 +32,7 @@ const ( var ( AlpineImage = mirrorOf("alpine:3.13") NginxAlpineImage = mirrorOf("nginx:1.19-alpine") + GolangImage = mirrorOf("golang:1.18") ) func mirrorOf(s string) string { From d7adf399c8941130a584e88e7b6b8be1a3cf2d03 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 15 Oct 2024 00:58:47 -0700 Subject: [PATCH 0832/1066] RootFul/RootLess > Rootful/Rootless Signed-off-by: apostasie --- cmd/nerdctl/image/image_convert_linux_test.go | 2 +- cmd/nerdctl/network/network_remove_linux_test.go | 2 +- docs/testing/tools.md | 2 +- pkg/testutil/nerdtest/requirements.go | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/nerdctl/image/image_convert_linux_test.go b/cmd/nerdctl/image/image_convert_linux_test.go index 5b21487ce81..f897385841c 100644 --- a/cmd/nerdctl/image/image_convert_linux_test.go +++ b/cmd/nerdctl/image/image_convert_linux_test.go @@ -108,7 +108,7 @@ func TestImageConvertNydusVerify(t *testing.T) { test.Binary("nydusify"), test.Binary("nydusd"), test.Not(nerdtest.Docker), - nerdtest.RootFul, + nerdtest.Rootful, ), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("pull", testutil.CommonImage) diff --git a/cmd/nerdctl/network/network_remove_linux_test.go b/cmd/nerdctl/network/network_remove_linux_test.go index b8804772f4b..f890cf13ddb 100644 --- a/cmd/nerdctl/network/network_remove_linux_test.go +++ b/cmd/nerdctl/network/network_remove_linux_test.go @@ -31,7 +31,7 @@ import ( func TestNetworkRemove(t *testing.T) { testCase := nerdtest.Setup() - testCase.Require = nerdtest.RootFul + testCase.Require = nerdtest.Rootful testCase.SubTests = []*test.Case{ { diff --git a/docs/testing/tools.md b/docs/testing/tools.md index 66d416d25d6..d1f64cd4c80 100644 --- a/docs/testing/tools.md +++ b/docs/testing/tools.md @@ -385,7 +385,7 @@ nerdtest.Docker // a test only run on Docker - normally used with test.Not(nerdt nerdtest.Soci // a test requires the soci snapshotter nerdtest.Stargz // a test requires the stargz snapshotter nerdtest.Rootless // a test requires Rootless -nerdtest.RootFul // a test requires Rootful +nerdtest.Rootful // a test requires Rootful nerdtest.Build // a test requires buildkit nerdtest.CGroup // a test requires cgroup nerdtest.NerdctlNeedsFixing // indicates that a test cannot be run on nerdctl yet as a fix is required diff --git a/pkg/testutil/nerdtest/requirements.go b/pkg/testutil/nerdtest/requirements.go index e69b954f4be..0ab60d382d8 100644 --- a/pkg/testutil/nerdtest/requirements.go +++ b/pkg/testutil/nerdtest/requirements.go @@ -131,8 +131,8 @@ var BrokenTest = func(message string, req *test.Requirement) *test.Requirement { } } -// RootLess marks a test as suitable only for the rootless environment -var RootLess = &test.Requirement{ +// Rootless marks a test as suitable only for the rootless environment +var Rootless = &test.Requirement{ Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { // Make sure we DO not return "IsRootless true" for docker ret = getTarget() == targetNerdctl && rootlessutil.IsRootless() @@ -145,8 +145,8 @@ var RootLess = &test.Requirement{ }, } -// RootFul marks a test as suitable only for rootful env -var RootFul = test.Not(RootLess) +// Rootful marks a test as suitable only for rootful env +var Rootful = test.Not(Rootless) // CGroup requires that cgroup is enabled var CGroup = &test.Requirement{ From 320d5c38e7ffe0cf0b0c8a69c402443deb4712ad Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 15 Oct 2024 01:02:52 -0700 Subject: [PATCH 0833/1066] Minor debugging / cleanup chores Signed-off-by: apostasie --- cmd/nerdctl/image/image_inspect_test.go | 1 - cmd/nerdctl/ipfs/ipfs_compose_linux_test.go | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/nerdctl/image/image_inspect_test.go b/cmd/nerdctl/image/image_inspect_test.go index 93278de9294..866f6a595c9 100644 --- a/cmd/nerdctl/image/image_inspect_test.go +++ b/cmd/nerdctl/image/image_inspect_test.go @@ -33,7 +33,6 @@ func TestImageInspectSimpleCases(t *testing.T) { nerdtest.Setup() testCase := &test.Case{ - Description: "TestImageInspect", Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("pull", testutil.CommonImage) }, diff --git a/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go index 5c4cd76fd66..a8c597de950 100644 --- a/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go @@ -71,7 +71,6 @@ func TestIPFSCompNoBuild(t *testing.T) { if ipfsRegistry != nil { ipfsRegistry.Cleanup(data, helpers) } - // Speeding up repeat tests... helpers.Anyhow("rmi", "-f", testutil.WordpressImage) helpers.Anyhow("rmi", "-f", testutil.MariaDBImage) } @@ -91,13 +90,15 @@ func subtestTestIPFSCompNoB(t *testing.T, stargz bool, byAddr bool) *test.Case { testCase.Description += "with" - if stargz { - testCase.Description += "-stargz" + if !stargz { + testCase.Description += "-no" } + testCase.Description += "-stargz" - if byAddr { - testCase.Description += "-byAddr" + if !byAddr { + testCase.Description += "-no" } + testCase.Description += "-byAddr" if stargz { testCase.Require = nerdtest.Stargz From e7101674c1af44e4a6cfa0dfd49c2f2c6e43f112 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 15 Oct 2024 01:03:39 -0700 Subject: [PATCH 0834/1066] Quiet ancillary image pulls Signed-off-by: apostasie --- .../completion/completion_linux_test.go | 2 +- cmd/nerdctl/image/image_convert_linux_test.go | 4 ++-- cmd/nerdctl/image/image_encrypt_linux_test.go | 4 ++-- cmd/nerdctl/image/image_history_test.go | 2 +- cmd/nerdctl/image/image_inspect_test.go | 6 +++--- cmd/nerdctl/image/image_list_test.go | 6 +++--- cmd/nerdctl/image/image_load_test.go | 2 +- cmd/nerdctl/image/image_push_linux_test.go | 18 +++++++++--------- cmd/nerdctl/image/image_remove_test.go | 2 +- cmd/nerdctl/ipfs/ipfs_registry_linux_test.go | 4 ++-- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/cmd/nerdctl/completion/completion_linux_test.go b/cmd/nerdctl/completion/completion_linux_test.go index 81156e15b16..8fee86e9ad5 100644 --- a/cmd/nerdctl/completion/completion_linux_test.go +++ b/cmd/nerdctl/completion/completion_linux_test.go @@ -30,7 +30,7 @@ func TestCompletion(t *testing.T) { testCase := &test.Case{ Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.AlpineImage) + helpers.Ensure("pull", "--quiet", testutil.AlpineImage) helpers.Ensure("network", "create", data.Identifier()) helpers.Ensure("volume", "create", data.Identifier()) data.Set("identifier", data.Identifier()) diff --git a/cmd/nerdctl/image/image_convert_linux_test.go b/cmd/nerdctl/image/image_convert_linux_test.go index f897385841c..85f0e243eaa 100644 --- a/cmd/nerdctl/image/image_convert_linux_test.go +++ b/cmd/nerdctl/image/image_convert_linux_test.go @@ -36,7 +36,7 @@ func TestImageConvert(t *testing.T) { test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) }, SubTests: []*test.Case{ { @@ -111,7 +111,7 @@ func TestImageConvertNydusVerify(t *testing.T) { nerdtest.Rootful, ), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) base := testutil.NewBase(t) registry = testregistry.NewWithNoAuth(base, 0, false) data.Set(remoteImageKey, fmt.Sprintf("%s:%d/nydusd-image:test", "localhost", registry.Port)) diff --git a/cmd/nerdctl/image/image_encrypt_linux_test.go b/cmd/nerdctl/image/image_encrypt_linux_test.go index 136e03cdd95..3e2e93ac29e 100644 --- a/cmd/nerdctl/image/image_encrypt_linux_test.go +++ b/cmd/nerdctl/image/image_encrypt_linux_test.go @@ -57,7 +57,7 @@ func TestImageEncryptJWE(t *testing.T) { base := testutil.NewBase(t) registry = testregistry.NewWithNoAuth(base, 0, false) keyPair = testhelpers.NewJWEKeyPair(t) - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) encryptImageRef := fmt.Sprintf("127.0.0.1:%d/%s:encrypted", registry.Port, data.Identifier()) helpers.Ensure("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, testutil.CommonImage, encryptImageRef) inspector := helpers.Capture("image", "inspect", "--mode=native", "--format={{len .Index.Manifests}}", encryptImageRef) @@ -71,7 +71,7 @@ func TestImageEncryptJWE(t *testing.T) { }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { helpers.Fail("pull", data.Get(remoteImageKey)) - helpers.Ensure("pull", "--unpack=false", data.Get(remoteImageKey)) + helpers.Ensure("pull", "--quiet", "--unpack=false", data.Get(remoteImageKey)) helpers.Fail("image", "decrypt", "--key="+keyPair.Pub, data.Get(remoteImageKey), data.Identifier("decrypted")) // decryption needs prv key, not pub key return helpers.Command("image", "decrypt", "--key="+keyPair.Prv, data.Get(remoteImageKey), data.Identifier("decrypted")) }, diff --git a/cmd/nerdctl/image/image_history_test.go b/cmd/nerdctl/image/image_history_test.go index 9f05785291c..9520e72535b 100644 --- a/cmd/nerdctl/image/image_history_test.go +++ b/cmd/nerdctl/image/image_history_test.go @@ -81,7 +81,7 @@ func TestImageHistory(t *testing.T) { // https://github.com/containerd/nerdctl/issues/3512 // Isolating it into a completely different root is the last ditched attempt at avoiding the issue helpers.Write(nerdtest.DataRoot, test.ConfigValue(data.TempDir())) - helpers.Ensure("pull", "--platform", "linux/arm64", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", "--platform", "linux/arm64", testutil.CommonImage) }, SubTests: []*test.Case{ { diff --git a/cmd/nerdctl/image/image_inspect_test.go b/cmd/nerdctl/image/image_inspect_test.go index 866f6a595c9..792c3ddc81e 100644 --- a/cmd/nerdctl/image/image_inspect_test.go +++ b/cmd/nerdctl/image/image_inspect_test.go @@ -87,9 +87,9 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { nerdtest.Private, ), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", "alpine") - helpers.Ensure("pull", "busybox") - helpers.Ensure("pull", "registry-1.docker.io/library/busybox") + helpers.Ensure("pull", "--quiet", "alpine") + helpers.Ensure("pull", "--quiet", "busybox") + helpers.Ensure("pull", "--quiet", "registry-1.docker.io/library/busybox") }, SubTests: []*test.Case{ { diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index 1badf3c617f..01acaf29a02 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -38,8 +38,8 @@ func TestImages(t *testing.T) { Description: "TestImages", Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) - helpers.Ensure("pull", testutil.NginxAlpineImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.NginxAlpineImage) }, SubTests: []*test.Case{ { @@ -127,7 +127,7 @@ func TestImagesFilter(t *testing.T) { Description: "TestImagesFilter", Require: nerdtest.Build, Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) helpers.Ensure("tag", testutil.CommonImage, "taggedimage:one-fragment-one") helpers.Ensure("tag", testutil.CommonImage, "taggedimage:two-fragment-two") diff --git a/cmd/nerdctl/image/image_load_test.go b/cmd/nerdctl/image/image_load_test.go index 452a0e18729..7d8e98c3624 100644 --- a/cmd/nerdctl/image/image_load_test.go +++ b/cmd/nerdctl/image/image_load_test.go @@ -37,7 +37,7 @@ func TestLoadStdinFromPipe(t *testing.T) { Description: "TestLoadStdinFromPipe", Require: test.Linux, Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) helpers.Ensure("tag", testutil.CommonImage, data.Identifier()) helpers.Ensure("save", data.Identifier(), "-o", filepath.Join(data.TempDir(), "common.tar")) helpers.Ensure("rmi", "-f", data.Identifier()) diff --git a/cmd/nerdctl/image/image_push_linux_test.go b/cmd/nerdctl/image/image_push_linux_test.go index 1cd38bba7fd..11dac1f8b3d 100644 --- a/cmd/nerdctl/image/image_push_linux_test.go +++ b/cmd/nerdctl/image/image_push_linux_test.go @@ -64,7 +64,7 @@ func TestPush(t *testing.T) { { Description: "plain http", Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) testImageRef := fmt.Sprintf("%s:%d/%s:%s", registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) data.Set("testImageRef", testImageRef) @@ -84,7 +84,7 @@ func TestPush(t *testing.T) { Description: "plain http with insecure", Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) testImageRef := fmt.Sprintf("%s:%d/%s:%s", registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) data.Set("testImageRef", testImageRef) @@ -103,7 +103,7 @@ func TestPush(t *testing.T) { { Description: "plain http with localhost", Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) testImageRef := fmt.Sprintf("%s:%d/%s:%s", "127.0.0.1", registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) data.Set("testImageRef", testImageRef) @@ -118,7 +118,7 @@ func TestPush(t *testing.T) { Description: "plain http with insecure, default port", Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) testImageRef := fmt.Sprintf("%s/%s:%s", registryNoAuthHTTPDefault.IP.String(), data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) data.Set("testImageRef", testImageRef) @@ -138,7 +138,7 @@ func TestPush(t *testing.T) { Description: "with insecure, with login", Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) testImageRef := fmt.Sprintf("%s:%d/%s:%s", registryTokenAuthHTTPSRandom.IP.String(), registryTokenAuthHTTPSRandom.Port, data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) data.Set("testImageRef", testImageRef) @@ -161,7 +161,7 @@ func TestPush(t *testing.T) { Description: "with hosts dir, with login", Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) testImageRef := fmt.Sprintf("%s:%d/%s:%s", registryTokenAuthHTTPSRandom.IP.String(), registryTokenAuthHTTPSRandom.Port, data.Identifier(), strings.Split(testutil.CommonImage, ":")[1]) data.Set("testImageRef", testImageRef) @@ -184,7 +184,7 @@ func TestPush(t *testing.T) { Description: "non distributable artifacts", Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.NonDistBlobImage) + helpers.Ensure("pull", "--quiet", testutil.NonDistBlobImage) testImageRef := fmt.Sprintf("%s:%d/%s:%s", registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.NonDistBlobImage, ":")[1]) data.Set("testImageRef", testImageRef) @@ -216,7 +216,7 @@ func TestPush(t *testing.T) { Description: "non distributable artifacts (with)", Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.NonDistBlobImage) + helpers.Ensure("pull", "--quiet", testutil.NonDistBlobImage) testImageRef := fmt.Sprintf("%s:%d/%s:%s", registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.NonDistBlobImage, ":")[1]) data.Set("testImageRef", testImageRef) @@ -251,7 +251,7 @@ func TestPush(t *testing.T) { test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.UbuntuImage) + helpers.Ensure("pull", "--quiet", testutil.UbuntuImage) testImageRef := fmt.Sprintf("%s:%d/%s:%s", registryNoAuthHTTPRandom.IP.String(), registryNoAuthHTTPRandom.Port, data.Identifier(), strings.Split(testutil.UbuntuImage, ":")[1]) data.Set("testImageRef", testImageRef) diff --git a/cmd/nerdctl/image/image_remove_test.go b/cmd/nerdctl/image/image_remove_test.go index 1d897dccbb9..85b665f350f 100644 --- a/cmd/nerdctl/image/image_remove_test.go +++ b/cmd/nerdctl/image/image_remove_test.go @@ -166,7 +166,7 @@ func TestRemove(t *testing.T) { NoParallel: true, Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", testutil.NginxAlpineImage) + helpers.Ensure("pull", "--quiet", testutil.NginxAlpineImage) helpers.Ensure("create", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") helpers.Ensure("rmi", testutil.NginxAlpineImage) }, diff --git a/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go index b6b032dc965..72b9b135d38 100644 --- a/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go @@ -85,7 +85,7 @@ func TestIPFSNerdctlRegistry(t *testing.T) { NoParallel: true, Setup: func(data test.Data, helpers test.Helpers) { data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.AlpineImage)) - helpers.Ensure("pull", data.Get(ipfsImageURLKey)) + helpers.Ensure("pull", "--quiet", data.Get(ipfsImageURLKey)) }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get(ipfsImageURLKey) != "" { @@ -103,7 +103,7 @@ func TestIPFSNerdctlRegistry(t *testing.T) { Require: nerdtest.Stargz, Setup: func(data test.Data, helpers test.Helpers) { data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.AlpineImage, "--estargz")) - helpers.Ensure("pull", data.Get(ipfsImageURLKey)) + helpers.Ensure("pull", "--quiet", data.Get(ipfsImageURLKey)) }, Cleanup: func(data test.Data, helpers test.Helpers) { if data.Get(ipfsImageURLKey) != "" { From 90b963545e04fede86422ddb0f3c785fdfd27241 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Mon, 14 Oct 2024 14:20:30 +0000 Subject: [PATCH 0835/1066] Add image load quiet mode Signed-off-by: Austin Vazquez --- cmd/nerdctl/container/container_create.go | 5 ++++ cmd/nerdctl/container/container_run.go | 1 + cmd/nerdctl/container/container_run_test.go | 27 +++++++++++++++++++ cmd/nerdctl/image/image_load.go | 6 +++++ cmd/nerdctl/image/image_load_test.go | 30 +++++++++++++++++++++ docs/command-reference.md | 4 +-- pkg/api/types/load_types.go | 2 ++ pkg/cmd/container/create.go | 1 - pkg/cmd/image/load.go | 16 +++++------ 9 files changed, 80 insertions(+), 12 deletions(-) diff --git a/cmd/nerdctl/container/container_create.go b/cmd/nerdctl/container/container_create.go index bb1c9e88256..45726e7f323 100644 --- a/cmd/nerdctl/container/container_create.go +++ b/cmd/nerdctl/container/container_create.go @@ -409,12 +409,17 @@ func processContainerCreateOptions(cmd *cobra.Command) (types.ContainerCreateOpt if err != nil { return opt, err } + quiet, err := cmd.Flags().GetBool("quiet") + if err != nil { + return opt, err + } opt.ImagePullOpt = types.ImagePullOptions{ GOptions: opt.GOptions, VerifyOptions: imageVerifyOpt, IPFSAddress: opt.IPFSAddress, Stdout: opt.Stdout, Stderr: opt.Stderr, + Quiet: quiet, } // #endregion diff --git a/cmd/nerdctl/container/container_run.go b/cmd/nerdctl/container/container_run.go index b24cd7c3566..f3efa0bf286 100644 --- a/cmd/nerdctl/container/container_run.go +++ b/cmd/nerdctl/container/container_run.go @@ -92,6 +92,7 @@ func setCreateFlags(cmd *cobra.Command) { }) cmd.Flags().Bool("rm", false, "Automatically remove the container when it exits") cmd.Flags().String("pull", "missing", `Pull image before running ("always"|"missing"|"never")`) + cmd.Flags().BoolP("quiet", "q", false, "Suppress the pull output") cmd.RegisterFlagCompletionFunc("pull", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"always", "missing", "never"}, cobra.ShellCompDirectiveNoFileComp }) diff --git a/cmd/nerdctl/container/container_run_test.go b/cmd/nerdctl/container/container_run_test.go index d2e7ef79011..4d796fa750e 100644 --- a/cmd/nerdctl/container/container_run_test.go +++ b/cmd/nerdctl/container/container_run_test.go @@ -631,3 +631,30 @@ func TestRunAttachFlag(t *testing.T) { }) } } + +func TestRunQuiet(t *testing.T) { + base := testutil.NewBase(t) + + teardown := func() { + base.Cmd("rmi", "-f", testutil.CommonImage).Run() + } + defer teardown() + teardown() + + sentinel := "test run quiet" + result := base.Cmd("run", "--rm", "--quiet", testutil.CommonImage, fmt.Sprintf(`echo "%s"`, sentinel)).Run() + assert.Assert(t, strings.Contains(result.Combined(), sentinel)) + + wasQuiet := func(output, sentinel string) bool { + return !strings.Contains(output, sentinel) + } + + // Docker and nerdctl image pulls are not 1:1. + if testutil.GetTarget() == testutil.Docker { + sentinel = "Pull complete" + } else { + sentinel = "resolved" + } + + assert.Assert(t, wasQuiet(result.Combined(), sentinel), "Found %s in container run output", sentinel) +} diff --git a/cmd/nerdctl/image/image_load.go b/cmd/nerdctl/image/image_load.go index b56a905a0ab..cd0698a3270 100644 --- a/cmd/nerdctl/image/image_load.go +++ b/cmd/nerdctl/image/image_load.go @@ -38,6 +38,7 @@ func NewLoadCommand() *cobra.Command { } loadCommand.Flags().StringP("input", "i", "", "Read from tar archive file, instead of STDIN") + loadCommand.Flags().BoolP("quiet", "q", false, "Suppress the load output") // #region platform flags // platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64" @@ -66,6 +67,10 @@ func processLoadCommandFlags(cmd *cobra.Command) (types.ImageLoadOptions, error) if err != nil { return types.ImageLoadOptions{}, err } + quiet, err := cmd.Flags().GetBool("quiet") + if err != nil { + return types.ImageLoadOptions{}, err + } return types.ImageLoadOptions{ GOptions: globalOptions, Input: input, @@ -73,6 +78,7 @@ func processLoadCommandFlags(cmd *cobra.Command) (types.ImageLoadOptions, error) AllPlatforms: allPlatforms, Stdout: cmd.OutOrStdout(), Stdin: cmd.InOrStdin(), + Quiet: quiet, }, nil } diff --git a/cmd/nerdctl/image/image_load_test.go b/cmd/nerdctl/image/image_load_test.go index 452a0e18729..31edfa99a5c 100644 --- a/cmd/nerdctl/image/image_load_test.go +++ b/cmd/nerdctl/image/image_load_test.go @@ -79,3 +79,33 @@ func TestLoadStdinEmpty(t *testing.T) { testCase.Run(t) } + +func TestLoadQuiet(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Description: "TestLoadQuiet", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("tag", testutil.CommonImage, data.Identifier()) + helpers.Ensure("save", data.Identifier(), "-o", filepath.Join(data.TempDir(), "common.tar")) + helpers.Ensure("rmi", "-f", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("load", "--quiet", "--input", filepath.Join(data.TempDir(), "common.tar")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains(fmt.Sprintf("Loaded image: %s:latest", data.Identifier())), + test.DoesNotContain("Loading layer"), + ), + } + }, + } + + testCase.Run(t) +} diff --git a/docs/command-reference.md b/docs/command-reference.md index cba61fb1372..2fbd0dc6479 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -151,6 +151,7 @@ Basic flags: - :whale: `--rm`: Automatically remove the container when it exits - :whale: `--pull=(always|missing|never)`: Pull image before running - Default: "missing" +- :whale: `-q, --quiet`: Suppress the pull output - :whale: `--pid=(host|container:)`: PID namespace to use - :whale: `--uts=(host)` : UTS namespace to use - :whale: `--stop-signal`: Signal to stop a container (default "SIGTERM") @@ -815,11 +816,10 @@ Usage: `nerdctl load [OPTIONS]` Flags: - :whale: `-i, --input`: Read from tar archive file, instead of STDIN +- :whale: `-q, --quiet`: Suppress the load output - :nerd_face: `--platform=(amd64|arm64|...)`: Import content for a specific platform - :nerd_face: `--all-platforms`: Import content for all platforms -Unimplemented `docker load` flags: `--quiet` - ### :whale: nerdctl save Save one or more images to a tar archive (streamed to STDOUT by default) diff --git a/pkg/api/types/load_types.go b/pkg/api/types/load_types.go index df115234cdd..d3ceaf350b1 100644 --- a/pkg/api/types/load_types.go +++ b/pkg/api/types/load_types.go @@ -29,4 +29,6 @@ type ImageLoadOptions struct { Platform []string // AllPlatforms import content for all platforms AllPlatforms bool + // Quiet suppresses the load output. + Quiet bool } diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index ec23038274a..6bf6022f70b 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -138,7 +138,6 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa options.ImagePullOpt.Mode = options.Pull options.ImagePullOpt.OCISpecPlatform = ocispecPlatforms options.ImagePullOpt.Unpack = nil - options.ImagePullOpt.Quiet = false ensuredImage, err = image.EnsureImage(ctx, client, rawRef, options.ImagePullOpt) if err != nil { diff --git a/pkg/cmd/image/load.go b/pkg/cmd/image/load.go index 996feda5d04..649a37102b9 100644 --- a/pkg/cmd/image/load.go +++ b/pkg/cmd/image/load.go @@ -73,10 +73,10 @@ func Load(ctx context.Context, client *containerd.Client, options types.ImageLoa if err != nil { return err } - return loadImage(ctx, client, decompressor, platMC, false, options) + return loadImage(ctx, client, decompressor, platMC, options) } -func loadImage(ctx context.Context, client *containerd.Client, in io.Reader, platMC platforms.MatchComparer, quiet bool, options types.ImageLoadOptions) error { +func loadImage(ctx context.Context, client *containerd.Client, in io.Reader, platMC platforms.MatchComparer, options types.ImageLoadOptions) error { // In addition to passing WithImagePlatform() to client.Import(), we also need to pass WithDefaultPlatform() to NewClient(). // Otherwise unpacking may fail. r := &readCounter{Reader: in} @@ -95,19 +95,17 @@ func loadImage(ctx context.Context, client *containerd.Client, in io.Reader, pla image := containerd.NewImageWithPlatform(client, img, platMC) // TODO: Show unpack status - if !quiet { + if !options.Quiet { fmt.Fprintf(options.Stdout, "unpacking %s (%s)...\n", img.Name, img.Target.Digest) } err = image.Unpack(ctx, options.GOptions.Snapshotter) if err != nil { return err } - if quiet { - fmt.Fprintln(options.Stdout, img.Target.Digest) - } else { - repo, tag := imgutil.ParseRepoTag(img.Name) - fmt.Fprintf(options.Stdout, "Loaded image: %s:%s\n", repo, tag) - } + + // Loaded message is shown even when quiet. + repo, tag := imgutil.ParseRepoTag(img.Name) + fmt.Fprintf(options.Stdout, "Loaded image: %s:%s\n", repo, tag) } return nil From 24cbe2524cb304ce02fc7d9742064100937dea4c Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 15 Oct 2024 18:27:27 -0700 Subject: [PATCH 0836/1066] Fix over-eager windows path restrictions Current regexp will match anything starting with forbidden patterns. This changes properly reduces that to paths that exactly match the forbidden patterns. Signed-off-by: apostasie --- pkg/store/filestore_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/store/filestore_windows.go b/pkg/store/filestore_windows.go index 9fbfe3e575a..75b18eb42e4 100644 --- a/pkg/store/filestore_windows.go +++ b/pkg/store/filestore_windows.go @@ -24,7 +24,7 @@ import ( // See https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file // https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names var ( - disallowedKeywords = regexp.MustCompile(`(?i)^(con|prn|nul|aux|com[1-9¹²³]|lpt[1-9¹²³])([.].*)?`) + disallowedKeywords = regexp.MustCompile(`(?i)^(con|prn|nul|aux|com[1-9¹²³]|lpt[1-9¹²³])([.].*)?$`) reservedCharacters = regexp.MustCompile(`[\x{0}-\x{1f}<>:"/\\|?*]`) ) From fc1848b54b398486426f03ec08a993ce2400f180 Mon Sep 17 00:00:00 2001 From: Dan Cavallaro Date: Fri, 11 Oct 2024 15:23:00 -0400 Subject: [PATCH 0837/1066] "ns:" network mode to use existing network namespace Signed-off-by: Dan Cavallaro --- cmd/nerdctl/container/container_run.go | 4 +- .../container_run_network_linux_test.go | 40 +++++++++++++++++++ docs/command-reference.md | 5 ++- pkg/cmd/container/kill.go | 2 +- pkg/composer/serviceparser/serviceparser.go | 2 +- .../container_network_manager.go | 31 +++++++++++++- pkg/netutil/nettype/nettype.go | 4 ++ pkg/ocihook/ocihook.go | 2 +- 8 files changed, 82 insertions(+), 8 deletions(-) diff --git a/cmd/nerdctl/container/container_run.go b/cmd/nerdctl/container/container_run.go index f3efa0bf286..df41bbc1273 100644 --- a/cmd/nerdctl/container/container_run.go +++ b/cmd/nerdctl/container/container_run.go @@ -112,11 +112,11 @@ func setCreateFlags(cmd *cobra.Command) { // #region network flags // network (net) is defined as StringSlice, not StringArray, to allow specifying "--network=cni1,cni2" - cmd.Flags().StringSlice("network", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|"container:"|)`) + cmd.Flags().StringSlice("network", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|"container:"|"ns:"|)`) cmd.RegisterFlagCompletionFunc("network", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return completion.NetworkNames(cmd, []string{}) }) - cmd.Flags().StringSlice("net", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|)`) + cmd.Flags().StringSlice("net", []string{netutil.DefaultNetworkName}, `Connect a container to a network ("bridge"|"host"|"none"|"container:"|"ns:"|)`) cmd.RegisterFlagCompletionFunc("net", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return completion.NetworkNames(cmd, []string{}) }) diff --git a/cmd/nerdctl/container/container_run_network_linux_test.go b/cmd/nerdctl/container/container_run_network_linux_test.go index 4c3c7d572a5..15c92e7c03b 100644 --- a/cmd/nerdctl/container/container_run_network_linux_test.go +++ b/cmd/nerdctl/container/container_run_network_linux_test.go @@ -21,14 +21,19 @@ import ( "io" "net" "os" + "os/exec" "regexp" "runtime" "strings" "testing" + "time" + "github.com/containernetworking/plugins/pkg/ns" + "github.com/vishvananda/netlink" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" + "github.com/containerd/containerd/v2/pkg/netns" "github.com/containerd/errdefs" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" @@ -499,6 +504,41 @@ func TestSharedNetworkStack(t *testing.T) { AssertOutContains(testutil.NginxAlpineIndexHTMLSnippet) } +func TestRunContainerInExistingNetNS(t *testing.T) { + if rootlessutil.IsRootless() { + t.Skip("Can't create new netns in rootless mode") + } + testutil.DockerIncompatible(t) + base := testutil.NewBase(t) + + netNS, err := netns.NewNetNS(t.TempDir() + "/netns") + assert.NilError(t, err) + err = netNS.Do(func(netns ns.NetNS) error { + loopback, err := netlink.LinkByName("lo") + assert.NilError(t, err) + err = netlink.LinkSetUp(loopback) + assert.NilError(t, err) + return nil + }) + assert.NilError(t, err) + defer netNS.Remove() + + containerName := testutil.Identifier(t) + defer base.Cmd("rm", "-f", containerName).AssertOK() + base.Cmd("run", "-d", "--name", containerName, + "--network=ns:"+netNS.GetPath(), testutil.NginxAlpineImage).AssertOK() + base.EnsureContainerStarted(containerName) + time.Sleep(3 * time.Second) + + err = netNS.Do(func(netns ns.NetNS) error { + stdout, err := exec.Command("curl", "-s", "http://127.0.0.1:80").Output() + assert.NilError(t, err) + assert.Assert(t, strings.Contains(string(stdout), testutil.NginxAlpineIndexHTMLSnippet)) + return nil + }) + assert.NilError(t, err) +} + func TestRunContainerWithMACAddress(t *testing.T) { base := testutil.NewBase(t) tID := testutil.Identifier(t) diff --git a/docs/command-reference.md b/docs/command-reference.md index 2fbd0dc6479..070c7db395e 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -175,9 +175,10 @@ Isolation flags: Network flags: -- :whale: `--net, --network=(bridge|host|none|container:|)`: Connect a container to a network. +- :whale: `--net, --network=(bridge|host|none|container:|ns:|)`: Connect a container to a network. - Default: "bridge" - - 'container:': reuse another container's network stack, container has to be precreated. + - `container:`: reuse another container's network stack, container has to be precreated. + - :nerd_face: `ns:`: run inside an existing network namespace - :nerd_face: Unlike Docker, this flag can be specified multiple times (`--net foo --net bar`) - :whale: `-p, --publish`: Publish a container's port(s) to the host - :whale: `--dns`: Set custom DNS servers diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index 4e53b4f9e3b..b077589473d 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -151,7 +151,7 @@ func cleanupNetwork(ctx context.Context, container containerd.Container, globalO } switch netType { - case nettype.Host, nettype.None, nettype.Container: + case nettype.Host, nettype.None, nettype.Container, nettype.Namespace: // NOP case nettype.CNI: e, err := netutil.NewCNIEnv(globalOpts.CNIPath, globalOpts.CNINetConfPath, netutil.WithNamespace(globalOpts.Namespace), netutil.WithDefaultNetwork()) diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index e59f7cc4368..635b93594b4 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -385,7 +385,7 @@ func getNetworks(project *types.Project, svc types.ServiceConfig) ([]networkName return nil, errors.New("net and network_mode must not be set together") } if strings.Contains(svc.NetworkMode, ":") { - if !strings.HasPrefix(svc.NetworkMode, "container:") { + if !strings.HasPrefix(svc.NetworkMode, "container:") && !strings.HasPrefix(svc.NetworkMode, "ns:") { return nil, fmt.Errorf("unsupported network_mode: %q", svc.NetworkMode) } } diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 7f7b97b13e4..5bc34e1e921 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -132,6 +132,10 @@ func NewNetworkingOptionsManager(globalOptions types.GlobalCommandOptions, netOp manager = &containerNetworkManager{globalOptions, netOpts, client} case nettype.CNI: manager = &cniNetworkManager{globalOptions, netOpts, client, cniNetworkManagerPlatform{}} + case nettype.Namespace: + // We'll handle Namespace networking identically to Host-mode networking, but + // put the container in the specified network namespace instead of the root. + manager = &hostNetworkManager{globalOptions, netOpts, client} default: return nil, fmt.Errorf("unexpected container networking type: %q", netType) } @@ -491,6 +495,26 @@ func copyFileContent(src string, dst string) error { return nil } +// getHostNetworkingNamespace Returns an oci.SpecOpts representing the network namespace to +// be used by the hostNetworkManager. When running with `--network=host` this would be the host's +// root namespace, but `--network=ns:` can be used to run a container in an existing netns. +func getHostNetworkingNamespace(netModeArg string) (oci.SpecOpts, error) { + if !strings.Contains(netModeArg, ":") { + // Use the host root namespace by default + return oci.WithHostNamespace(specs.NetworkNamespace), nil + } + + netItems := strings.Split(netModeArg, ":") + if len(netItems) < 2 { + return nil, fmt.Errorf("namespace networking argument format must be 'ns:', got: %q", netModeArg) + } + netnsPath := netItems[1] + return oci.WithLinuxNamespace(specs.LinuxNamespace{ + Type: specs.NetworkNamespace, + Path: netnsPath, + }), nil +} + // ContainerNetworkingOpts Returns a slice of `oci.SpecOpts` and `containerd.NewContainerOpts` which represent // the network specs which need to be applied to the container with the given ID. func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containerID string) ([]oci.SpecOpts, []containerd.NewContainerOpts, error) { @@ -525,8 +549,13 @@ func (m *hostNetworkManager) ContainerNetworkingOpts(_ context.Context, containe return nil, nil, err } + netModeArg := m.netOpts.NetworkSlice[0] + netNamespace, err := getHostNetworkingNamespace(netModeArg) + if err != nil { + return nil, nil, err + } specs := []oci.SpecOpts{ - oci.WithHostNamespace(specs.NetworkNamespace), + netNamespace, withDedupMounts("/etc/hosts", withCustomHosts(etcHostsPath)), withDedupMounts("/etc/resolv.conf", withCustomResolvConf(resolvConfPath)), } diff --git a/pkg/netutil/nettype/nettype.go b/pkg/netutil/nettype/nettype.go index 721167037c7..d319254260d 100644 --- a/pkg/netutil/nettype/nettype.go +++ b/pkg/netutil/nettype/nettype.go @@ -29,6 +29,7 @@ const ( Host CNI Container + Namespace ) var netTypeToName = map[interface{}]string{ @@ -37,6 +38,7 @@ var netTypeToName = map[interface{}]string{ Host: "host", CNI: "cni", Container: "container", + Namespace: "ns", } func Detect(names []string) (Type, error) { @@ -54,6 +56,8 @@ func Detect(names []string) (Type, error) { tmp = Host case "container": tmp = Container + case "ns": + tmp = Namespace default: tmp = CNI } diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index a98c84d1d37..b1b1068c1bb 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -170,7 +170,7 @@ func newHandlerOpts(state *specs.State, dataStore, cniPath, cniNetconfPath strin } switch netType { - case nettype.Host, nettype.None, nettype.Container: + case nettype.Host, nettype.None, nettype.Container, nettype.Namespace: // NOP case nettype.CNI: e, err := netutil.NewCNIEnv(cniPath, cniNetconfPath, netutil.WithNamespace(namespace), netutil.WithDefaultNetwork()) From 645988e8a04904db822d00679787fca95980a5c0 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 16 Oct 2024 16:00:01 -0700 Subject: [PATCH 0838/1066] Add delay to tentatively fix flakyness with Docker Signed-off-by: apostasie --- cmd/nerdctl/container/container_logs_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/nerdctl/container/container_logs_test.go b/cmd/nerdctl/container/container_logs_test.go index ec9fbd2ce70..085c5f840c6 100644 --- a/cmd/nerdctl/container/container_logs_test.go +++ b/cmd/nerdctl/container/container_logs_test.go @@ -95,6 +95,9 @@ func TestLogsWithInheritedFlags(t *testing.T) { base.Cmd("run", "-d", "--name", containerName, testutil.CommonImage, "sh", "-euxc", "echo foo; echo bar").AssertOK() + // It appears this test flakes out with Docker seeing only "foo\n" + // Tentatively adding a pause in case this is just slow + time.Sleep(time.Second) // test rootCmd alias `-n` already used in logs subcommand base.Cmd("logs", "-n", "1", containerName).AssertOutWithFunc(func(stdout string) error { if !(stdout == "bar\n" || stdout == "") { From 95fe8c0aceb7b712221e305fb6fae3da3455588d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 23:17:58 +0000 Subject: [PATCH 0839/1066] build(deps): bump github.com/containerd/accelerated-container-image Bumps [github.com/containerd/accelerated-container-image](https://github.com/containerd/accelerated-container-image) from 1.2.2 to 1.2.3. - [Release notes](https://github.com/containerd/accelerated-container-image/releases) - [Commits](https://github.com/containerd/accelerated-container-image/compare/v1.2.2...v1.2.3) --- updated-dependencies: - dependency-name: github.com/containerd/accelerated-container-image dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 074c01acd8f..68eb2153826 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.7 github.com/compose-spec/compose-go/v2 v2.3.0 - github.com/containerd/accelerated-container-image v1.2.2 + github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0-rc.3 diff --git a/go.sum b/go.sum index 84d673230fa..34ebae7dcb5 100644 --- a/go.sum +++ b/go.sum @@ -25,8 +25,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/v2 v2.3.0 h1:5eomqgNcs/GqVknPtXF68V3muc67cOdXD35zCXn1aes= github.com/compose-spec/compose-go/v2 v2.3.0/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= -github.com/containerd/accelerated-container-image v1.2.2 h1:GzBaFYyA3JFJGor9de1tX2aLSIG1vIewdNzJrcP3dco= -github.com/containerd/accelerated-container-image v1.2.2/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= +github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= +github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= From 76b265af9eeba1476731c81078dec9edb9e4683b Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 16 Oct 2024 16:10:04 -0700 Subject: [PATCH 0840/1066] Skip TestAttach until we fix it Signed-off-by: apostasie --- cmd/nerdctl/container/container_attach_linux_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/nerdctl/container/container_attach_linux_test.go b/cmd/nerdctl/container/container_attach_linux_test.go index 71a74eae59e..cdd4e689981 100644 --- a/cmd/nerdctl/container/container_attach_linux_test.go +++ b/cmd/nerdctl/container/container_attach_linux_test.go @@ -63,6 +63,8 @@ func prepareContainerToAttach(base *testutil.Base, containerName string) { func TestAttach(t *testing.T) { t.Parallel() + t.Skip("This test is very unstable and currently skipped. See https://github.com/containerd/nerdctl/issues/3558") + skipAttachForDocker(t) base := testutil.NewBase(t) From 7a0eaecb5efe4c643c3ba49fdd08c4d6d1a1e132 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 16 Oct 2024 19:55:59 -0700 Subject: [PATCH 0841/1066] Add pseudo tty support for tests Signed-off-by: apostasie --- pkg/testutil/test/command.go | 16 ++++++++ pkg/testutil/test/pty.go | 74 ++++++++++++++++++++++++++++++++++++ pkg/testutil/test/test.go | 2 + 3 files changed, 92 insertions(+) create mode 100644 pkg/testutil/test/pty.go diff --git a/pkg/testutil/test/command.go b/pkg/testutil/test/command.go index fd7c4fa3b6a..a5b1de747d0 100644 --- a/pkg/testutil/test/command.go +++ b/pkg/testutil/test/command.go @@ -45,6 +45,7 @@ type GenericCommand struct { envBlackList []string stdin io.Reader async bool + pty bool timeout time.Duration workingDir string @@ -65,6 +66,10 @@ func (gc *GenericCommand) WithWrapper(binary string, args ...string) { gc.helperArgs = args } +func (gc *GenericCommand) WithPseudoTTY() { + gc.pty = true +} + func (gc *GenericCommand) WithStdin(r io.Reader) { gc.stdin = r } @@ -77,6 +82,7 @@ func (gc *GenericCommand) WithCwd(path string) { // Primitives (gc.timeout) is here, it is just a matter of exposing a WithTimeout method // - UX to be decided // - validate use case: would we ever need this? + func (gc *GenericCommand) Run(expect *Expected) { if gc.t != nil { gc.t.Helper() @@ -90,6 +96,16 @@ func (gc *GenericCommand) Run(expect *Expected) { } else { iCmdCmd := gc.boot() env = iCmdCmd.Env + + if gc.pty { + pty, tty, _ := Open() + iCmdCmd.Stdin = tty + iCmdCmd.Stdout = tty + iCmdCmd.Stderr = tty + defer pty.Close() + defer tty.Close() + } + // Run it result = icmd.RunCmd(iCmdCmd) } diff --git a/pkg/testutil/test/pty.go b/pkg/testutil/test/pty.go new file mode 100644 index 00000000000..f72d057260b --- /dev/null +++ b/pkg/testutil/test/pty.go @@ -0,0 +1,74 @@ +/* + 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 test + +import ( + "errors" + "os" + "strconv" + "syscall" + "unsafe" +) + +// Inspiration from https://github.com/creack/pty/tree/2cde18bfb702199728dd43bf10a6c15c7336da0a + +var ErrPTY = errors.New("pty failure") + +func Open() (pty, tty *os.File, err error) { + defer func() { + if err != nil && pty != nil { + err = errors.Join(pty.Close(), err) + } + if err != nil { + err = errors.Join(ErrPTY, err) + } + }() + + pty, err = os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + + var n uint32 + err = ioctl(pty, syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) + if err != nil { + return nil, nil, err + } + + sname := "/dev/pts/" + strconv.Itoa(int(n)) + + var u int32 + err = ioctl(pty, syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) + if err != nil { + return nil, nil, err + } + + tty, err = os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) + if err != nil { + return nil, nil, err + } + + return pty, tty, nil +} + +func ioctl(f *os.File, cmd, ptr uintptr) error { + _, _, e := syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), cmd, ptr) + if e != 0 { + return e + } + return nil +} diff --git a/pkg/testutil/test/test.go b/pkg/testutil/test/test.go index e8f3a9dfe4f..07a7e3b1c60 100644 --- a/pkg/testutil/test/test.go +++ b/pkg/testutil/test/test.go @@ -97,6 +97,8 @@ type TestableCommand interface { WithArgs(args ...string) // WithWrapper allows wrapping a command with another command (for example: `time`, `unbuffer`) WithWrapper(binary string, args ...string) + // WithPseudoTTY + WithPseudoTTY() // WithStdin allows passing a reader to be used for stdin for the command WithStdin(r io.Reader) // WithCwd allows specifying the working directory for the command From 97919c2547e4fbf1cde0166dddaf6064964b7c49 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 16 Oct 2024 19:56:34 -0700 Subject: [PATCH 0842/1066] Remove unbuffer from test Signed-off-by: apostasie --- cmd/nerdctl/issues/main_linux_test.go | 20 +++----- pkg/testutil/test/pty.go | 58 ++------------------- pkg/testutil/test/pty_freebsd.go | 25 ++++++++++ pkg/testutil/test/pty_linux.go | 72 +++++++++++++++++++++++++++ pkg/testutil/test/pty_windows.go | 25 ++++++++++ 5 files changed, 133 insertions(+), 67 deletions(-) create mode 100644 pkg/testutil/test/pty_freebsd.go create mode 100644 pkg/testutil/test/pty_linux.go create mode 100644 pkg/testutil/test/pty_windows.go diff --git a/cmd/nerdctl/issues/main_linux_test.go b/cmd/nerdctl/issues/main_linux_test.go index 64ca72e2da4..e6735f02c14 100644 --- a/cmd/nerdctl/issues/main_linux_test.go +++ b/cmd/nerdctl/issues/main_linux_test.go @@ -33,30 +33,26 @@ func TestMain(m *testing.M) { func TestIssue108(t *testing.T) { testCase := nerdtest.Setup() + testCase.Require = test.Linux + testCase.SubTests = []*test.Case{ { Description: "-it --net=host", - Require: test.Binary("unbuffer"), Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - cmd := helpers. - Command("run", "-it", "--rm", "--net=host", testutil.AlpineImage, "echo", "this was always working") - cmd.WithWrapper("unbuffer") + cmd := helpers.Command("run", "-it", "--rm", "--net=host", testutil.AlpineImage, "echo", "this was always working") + cmd.WithPseudoTTY() return cmd }, - // Note: unbuffer will merge stdout and stderr, preventing exact match here - Expected: test.Expects(0, nil, test.Contains("this was always working")), + Expected: test.Expects(0, nil, test.Equals("this was always working\r\n")), }, { Description: "--net=host -it", - Require: test.Binary("unbuffer"), Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - cmd := helpers. - Command("run", "--rm", "--net=host", "-it", testutil.AlpineImage, "echo", "this was not working due to issue #108") - cmd.WithWrapper("unbuffer") + cmd := helpers.Command("run", "--rm", "--net=host", "-it", testutil.AlpineImage, "echo", "this was not working due to issue #108") + cmd.WithPseudoTTY() return cmd }, - // Note: unbuffer will merge stdout and stderr, preventing exact match here - Expected: test.Expects(0, nil, test.Contains("this was not working due to issue #108")), + Expected: test.Expects(0, nil, test.Equals("this was not working due to issue #108\r\n")), }, } diff --git a/pkg/testutil/test/pty.go b/pkg/testutil/test/pty.go index f72d057260b..97a73910c16 100644 --- a/pkg/testutil/test/pty.go +++ b/pkg/testutil/test/pty.go @@ -16,59 +16,7 @@ package test -import ( - "errors" - "os" - "strconv" - "syscall" - "unsafe" -) +import "errors" -// Inspiration from https://github.com/creack/pty/tree/2cde18bfb702199728dd43bf10a6c15c7336da0a - -var ErrPTY = errors.New("pty failure") - -func Open() (pty, tty *os.File, err error) { - defer func() { - if err != nil && pty != nil { - err = errors.Join(pty.Close(), err) - } - if err != nil { - err = errors.Join(ErrPTY, err) - } - }() - - pty, err = os.OpenFile("/dev/ptmx", os.O_RDWR, 0) - if err != nil { - return nil, nil, err - } - - var n uint32 - err = ioctl(pty, syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) - if err != nil { - return nil, nil, err - } - - sname := "/dev/pts/" + strconv.Itoa(int(n)) - - var u int32 - err = ioctl(pty, syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) - if err != nil { - return nil, nil, err - } - - tty, err = os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) - if err != nil { - return nil, nil, err - } - - return pty, tty, nil -} - -func ioctl(f *os.File, cmd, ptr uintptr) error { - _, _, e := syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), cmd, ptr) - if e != 0 { - return e - } - return nil -} +var ErrPTYFailure = errors.New("pty failure") +var ErrPTYUnsupportedPlatform = errors.New("pty not supported on this platform") diff --git a/pkg/testutil/test/pty_freebsd.go b/pkg/testutil/test/pty_freebsd.go new file mode 100644 index 00000000000..dda64ae6c8c --- /dev/null +++ b/pkg/testutil/test/pty_freebsd.go @@ -0,0 +1,25 @@ +/* + 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 test + +import ( + "os" +) + +func Open() (pty, tty *os.File, err error) { + return nil, nil, ErrPTYUnsupportedPlatform +} diff --git a/pkg/testutil/test/pty_linux.go b/pkg/testutil/test/pty_linux.go new file mode 100644 index 00000000000..37226938ee1 --- /dev/null +++ b/pkg/testutil/test/pty_linux.go @@ -0,0 +1,72 @@ +/* + 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 test + +import ( + "errors" + "os" + "strconv" + "syscall" + "unsafe" +) + +// Inspiration from https://github.com/creack/pty/tree/2cde18bfb702199728dd43bf10a6c15c7336da0a + +func Open() (pty, tty *os.File, err error) { + defer func() { + if err != nil && pty != nil { + err = errors.Join(pty.Close(), err) + } + if err != nil { + err = errors.Join(ErrPTYFailure, err) + } + }() + + pty, err = os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + + var n uint32 + err = ioctl(pty, syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))) + if err != nil { + return nil, nil, err + } + + sname := "/dev/pts/" + strconv.Itoa(int(n)) + + var u int32 + err = ioctl(pty, syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) + if err != nil { + return nil, nil, err + } + + tty, err = os.OpenFile(sname, os.O_RDWR|syscall.O_NOCTTY, 0) + if err != nil { + return nil, nil, err + } + + return pty, tty, nil +} + +func ioctl(f *os.File, cmd, ptr uintptr) error { + _, _, e := syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), cmd, ptr) + if e != 0 { + return e + } + return nil +} diff --git a/pkg/testutil/test/pty_windows.go b/pkg/testutil/test/pty_windows.go new file mode 100644 index 00000000000..dda64ae6c8c --- /dev/null +++ b/pkg/testutil/test/pty_windows.go @@ -0,0 +1,25 @@ +/* + 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 test + +import ( + "os" +) + +func Open() (pty, tty *os.File, err error) { + return nil, nil, ErrPTYUnsupportedPlatform +} From d2b2637ecb63ac4a9321d6fbcb412850d2536fe4 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 16 Oct 2024 22:09:35 -0700 Subject: [PATCH 0843/1066] Enable image completion on all platforms Signed-off-by: apostasie --- .../completion/completion_linux_test.go | 201 ------------------ cmd/nerdctl/completion/completion_test.go | 187 ++++++++++++++++ cmd/nerdctl/container/container_run.go | 7 + .../container/container_run_freebsd.go | 4 - cmd/nerdctl/container/container_run_linux.go | 9 - .../container/container_run_windows.go | 4 - 6 files changed, 194 insertions(+), 218 deletions(-) delete mode 100644 cmd/nerdctl/completion/completion_linux_test.go diff --git a/cmd/nerdctl/completion/completion_linux_test.go b/cmd/nerdctl/completion/completion_linux_test.go deleted file mode 100644 index 8fee86e9ad5..00000000000 --- a/cmd/nerdctl/completion/completion_linux_test.go +++ /dev/null @@ -1,201 +0,0 @@ -/* - 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 completion - -import ( - "testing" - - "github.com/containerd/nerdctl/v2/pkg/testutil" - "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" - "github.com/containerd/nerdctl/v2/pkg/testutil/test" -) - -func TestCompletion(t *testing.T) { - nerdtest.Setup() - - testCase := &test.Case{ - Require: test.Not(nerdtest.Docker), - Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", "--quiet", testutil.AlpineImage) - helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("volume", "create", data.Identifier()) - data.Set("identifier", data.Identifier()) - }, - Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("network", "rm", data.Identifier()) - helpers.Anyhow("volume", "rm", data.Identifier()) - }, - SubTests: []*test.Case{ - { - Description: "--cgroup-manager", - Command: test.Command("__complete", "--cgroup-manager", ""), - Expected: test.Expects(0, nil, test.Contains("cgroupfs\n")), - }, - { - Description: "--snapshotter", - Command: test.Command("__complete", "--snapshotter", ""), - Expected: test.Expects(0, nil, test.Contains("native\n")), - }, - { - Description: "empty", - Command: test.Command("__complete", ""), - Expected: test.Expects(0, nil, test.Contains("run\t")), - }, - { - Description: "run -", - Command: test.Command("__complete", "run", "-"), - Expected: test.Expects(0, nil, test.Contains("--network\t")), - }, - { - Description: "run --n", - Command: test.Command("__complete", "run", "--n"), - Expected: test.Expects(0, nil, test.Contains("--network\t")), - }, - { - Description: "run --ne", - Command: test.Command("__complete", "run", "--ne"), - Expected: test.Expects(0, nil, test.Contains("--network\t")), - }, - { - Description: "run --net", - Command: test.Command("__complete", "run", "--net", ""), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.Contains("host\n"), - test.Contains(data.Get("identifier")+"\n"), - ), - } - }, - }, - { - Description: "run -it --net", - Command: test.Command("__complete", "run", "-it", "--net", ""), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.Contains("host\n"), - test.Contains(data.Get("identifier")+"\n"), - ), - } - }, - }, - { - Description: "run -ti --rm --net", - Command: test.Command("__complete", "run", "-it", "--rm", "--net", ""), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.Contains("host\n"), - test.Contains(data.Get("identifier")+"\n"), - ), - } - }, - }, - { - Description: "run --restart", - Command: test.Command("__complete", "run", "--restart", ""), - Expected: test.Expects(0, nil, test.Contains("always\n")), - }, - { - Description: "network --rm", - Command: test.Command("__complete", "network", "rm", ""), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.All( - test.DoesNotContain("host\n"), - test.Contains(data.Get("identifier")+"\n"), - ), - } - }, - }, - { - Description: "run --cap-add", - Command: test.Command("__complete", "run", "--cap-add", ""), - Expected: test.Expects(0, nil, test.All( - test.Contains("sys_admin\n"), - test.DoesNotContain("CAP_SYS_ADMIN\n"), - )), - }, - { - Description: "volume inspect", - Command: test.Command("__complete", "volume", "inspect", ""), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.Contains(data.Get("identifier") + "\n"), - } - }, - }, - { - Description: "volume rm", - Command: test.Command("__complete", "volume", "rm", ""), - Expected: func(data test.Data, helpers test.Helpers) *test.Expected { - return &test.Expected{ - Output: test.Contains(data.Get("identifier") + "\n"), - } - }, - }, - { - Description: "no namespace --cgroup-manager", - Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - return helpers.Custom("nerdctl", "__complete", "--cgroup-manager", "") - }, - Expected: test.Expects(0, nil, test.Contains("cgroupfs\n")), - }, - { - Description: "no namespace empty", - Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - return helpers.Custom("nerdctl", "__complete", "") - }, - Expected: test.Expects(0, nil, test.Contains("run\t")), - }, - { - Description: "namespace space empty", - Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - // mind {"--namespace=nerdctl-test"} vs {"--namespace", "nerdctl-test"} - return helpers.Custom("nerdctl", "__complete", "--namespace", string(helpers.Read(nerdtest.Namespace)), "") - }, - Expected: test.Expects(0, nil, test.Contains("run\t")), - }, - { - Description: "run -i", - Command: test.Command("__complete", "run", "-i", ""), - Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage)), - }, - { - Description: "run -it", - Command: test.Command("__complete", "run", "-it", ""), - Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage)), - }, - { - Description: "run -it --rm", - Command: test.Command("__complete", "run", "-it", "--rm", ""), - Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage)), - }, - { - Description: "namespace run -i", - Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - // mind {"--namespace=nerdctl-test"} vs {"--namespace", "nerdctl-test"} - return helpers.Custom("nerdctl", "__complete", "--namespace", string(helpers.Read(nerdtest.Namespace)), "run", "-i", "") - }, - Expected: test.Expects(0, nil, test.Contains(testutil.AlpineImage+"\n")), - }, - }, - } - - testCase.Run(t) -} diff --git a/cmd/nerdctl/completion/completion_test.go b/cmd/nerdctl/completion/completion_test.go index f37df496baf..8b2626ee38c 100644 --- a/cmd/nerdctl/completion/completion_test.go +++ b/cmd/nerdctl/completion/completion_test.go @@ -20,8 +20,195 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestMain(m *testing.M) { testutil.M(m) } + +func TestCompletion(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Require: test.Not(nerdtest.Docker), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "--quiet", testutil.CommonImage) + helpers.Ensure("network", "create", data.Identifier()) + helpers.Ensure("volume", "create", data.Identifier()) + data.Set("identifier", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier()) + helpers.Anyhow("volume", "rm", data.Identifier()) + }, + SubTests: []*test.Case{ + { + Description: "--cgroup-manager", + Require: test.Not(test.Windows), + Command: test.Command("__complete", "--cgroup-manager", ""), + Expected: test.Expects(0, nil, test.Contains("cgroupfs\n")), + }, + { + Description: "--snapshotter", + Require: test.Not(test.Windows), + Command: test.Command("__complete", "--snapshotter", ""), + Expected: test.Expects(0, nil, test.Contains("native\n")), + }, + { + Description: "empty", + Command: test.Command("__complete", ""), + Expected: test.Expects(0, nil, test.Contains("run\t")), + }, + { + Description: "build --network", + Command: test.Command("__complete", "build", "--network", ""), + Expected: test.Expects(0, nil, test.Contains("default\n")), + }, + { + Description: "run -", + Command: test.Command("__complete", "run", "-"), + Expected: test.Expects(0, nil, test.Contains("--network\t")), + }, + { + Description: "run --n", + Command: test.Command("__complete", "run", "--n"), + Expected: test.Expects(0, nil, test.Contains("--network\t")), + }, + { + Description: "run --ne", + Command: test.Command("__complete", "run", "--ne"), + Expected: test.Expects(0, nil, test.Contains("--network\t")), + }, + { + Description: "run --net", + Command: test.Command("__complete", "run", "--net", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains("host\n"), + test.Contains(data.Get("identifier")+"\n"), + ), + } + }, + }, + { + Description: "run -it --net", + Command: test.Command("__complete", "run", "-it", "--net", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains("host\n"), + test.Contains(data.Get("identifier")+"\n"), + ), + } + }, + }, + { + Description: "run -ti --rm --net", + Command: test.Command("__complete", "run", "-it", "--rm", "--net", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.Contains("host\n"), + test.Contains(data.Get("identifier")+"\n"), + ), + } + }, + }, + { + Description: "run --restart", + Command: test.Command("__complete", "run", "--restart", ""), + Expected: test.Expects(0, nil, test.Contains("always\n")), + }, + { + Description: "network --rm", + Command: test.Command("__complete", "network", "rm", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.All( + test.DoesNotContain("host\n"), + test.Contains(data.Get("identifier")+"\n"), + ), + } + }, + }, + { + Description: "run --cap-add", + Require: test.Not(test.Windows), + Command: test.Command("__complete", "run", "--cap-add", ""), + Expected: test.Expects(0, nil, test.All( + test.Contains("sys_admin\n"), + test.DoesNotContain("CAP_SYS_ADMIN\n"), + )), + }, + { + Description: "volume inspect", + Command: test.Command("__complete", "volume", "inspect", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("identifier") + "\n"), + } + }, + }, + { + Description: "volume rm", + Command: test.Command("__complete", "volume", "rm", ""), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("identifier") + "\n"), + } + }, + }, + { + Description: "no namespace --cgroup-manager", + Require: test.Not(test.Windows), + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("nerdctl", "__complete", "--cgroup-manager", "") + }, + Expected: test.Expects(0, nil, test.Contains("cgroupfs\n")), + }, + { + Description: "no namespace empty", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Custom("nerdctl", "__complete", "") + }, + Expected: test.Expects(0, nil, test.Contains("run\t")), + }, + { + Description: "namespace space empty", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + // mind {"--namespace=nerdctl-test"} vs {"--namespace", "nerdctl-test"} + return helpers.Custom("nerdctl", "__complete", "--namespace", string(helpers.Read(nerdtest.Namespace)), "") + }, + Expected: test.Expects(0, nil, test.Contains("run\t")), + }, + { + Description: "run -i", + Command: test.Command("__complete", "run", "-i", ""), + Expected: test.Expects(0, nil, test.Contains(testutil.CommonImage)), + }, + { + Description: "run -it", + Command: test.Command("__complete", "run", "-it", ""), + Expected: test.Expects(0, nil, test.Contains(testutil.CommonImage)), + }, + { + Description: "run -it --rm", + Command: test.Command("__complete", "run", "-it", "--rm", ""), + Expected: test.Expects(0, nil, test.Contains(testutil.CommonImage)), + }, + { + Description: "namespace run -i", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + // mind {"--namespace=nerdctl-test"} vs {"--namespace", "nerdctl-test"} + return helpers.Custom("nerdctl", "__complete", "--namespace", string(helpers.Read(nerdtest.Namespace)), "run", "-i", "") + }, + Expected: test.Expects(0, nil, test.Contains(testutil.CommonImage+"\n")), + }, + }, + } + + testCase.Run(t) +} diff --git a/cmd/nerdctl/container/container_run.go b/cmd/nerdctl/container/container_run.go index f3efa0bf286..ac7f7ac9fe3 100644 --- a/cmd/nerdctl/container/container_run.go +++ b/cmd/nerdctl/container/container_run.go @@ -465,3 +465,10 @@ func runAction(cmd *cobra.Command, args []string) error { } return nil } + +func runShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return completion.ImageNames(cmd) + } + return nil, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/nerdctl/container/container_run_freebsd.go b/cmd/nerdctl/container/container_run_freebsd.go index fa3c4ec5782..5ef9a6d94fb 100644 --- a/cmd/nerdctl/container/container_run_freebsd.go +++ b/cmd/nerdctl/container/container_run_freebsd.go @@ -24,7 +24,3 @@ func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]s candidates := []string{} return candidates, cobra.ShellCompDirectiveNoFileComp } - -func runShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} diff --git a/cmd/nerdctl/container/container_run_linux.go b/cmd/nerdctl/container/container_run_linux.go index 5c188aa3a25..a84bedddfdf 100644 --- a/cmd/nerdctl/container/container_run_linux.go +++ b/cmd/nerdctl/container/container_run_linux.go @@ -22,8 +22,6 @@ import ( "github.com/spf13/cobra" "github.com/containerd/containerd/v2/pkg/cap" - - "github.com/containerd/nerdctl/v2/cmd/nerdctl/completion" ) func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -35,10 +33,3 @@ func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]s } return candidates, cobra.ShellCompDirectiveNoFileComp } - -func runShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) == 0 { - return completion.ImageNames(cmd) - } - return nil, cobra.ShellCompDirectiveNoFileComp -} diff --git a/cmd/nerdctl/container/container_run_windows.go b/cmd/nerdctl/container/container_run_windows.go index fa3c4ec5782..5ef9a6d94fb 100644 --- a/cmd/nerdctl/container/container_run_windows.go +++ b/cmd/nerdctl/container/container_run_windows.go @@ -24,7 +24,3 @@ func capShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]s candidates := []string{} return candidates, cobra.ShellCompDirectiveNoFileComp } - -func runShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveNoFileComp -} From 27a181621d27d6edc9e24d6a33b0de58e55da31d Mon Sep 17 00:00:00 2001 From: xyz-li Date: Tue, 15 Oct 2024 11:45:58 +0800 Subject: [PATCH 0844/1066] [fix] fix image filter with nonexist image Signed-off-by: xyz-li --- cmd/nerdctl/image/image_list_test.go | 5 ++-- pkg/imgutil/filtering.go | 36 ++++++++++++++++++---------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index 76e1095a081..54773013110 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -17,6 +17,7 @@ package image import ( + "errors" "fmt" "slices" "strings" @@ -258,13 +259,13 @@ RUN echo "actually creating a layer so that docker sets the createdAt time" Description: "since=non-exists-image", Require: nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3511"), Command: test.Command("images", "--filter", "since=non-exists-image"), - Expected: test.Expects(-1, nil, nil), + Expected: test.Expects(-1, []error{errors.New("No such image: ")}, nil), }, { Description: "before=non-exists-image", Require: nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3511"), Command: test.Command("images", "--filter", "before=non-exists-image"), - Expected: test.Expects(-1, nil, nil), + Expected: test.Expects(-1, []error{errors.New("No such image: ")}, nil), }, }, } diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index 0085cd943fb..902f2ceca15 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -145,18 +145,28 @@ func FilterByCreatedAt(ctx context.Context, client *containerd.Client, before [] maxTime = time.Now() ) + fetchImageNames := func(names []string) string { + parsedNames := make([]string, 0, len(names)) + for _, name := range names { + parsedNames = append(parsedNames, strings.TrimPrefix(name, "name==")) + } + return strings.Join(parsedNames, ",") + } + imageStore := client.ImageService() if len(before) > 0 { beforeImages, err := imageStore.List(ctx, before...) if err != nil { return []images.Image{}, err } - if len(beforeImages) > 0 { - maxTime = beforeImages[0].CreatedAt - for _, image := range beforeImages { - if image.CreatedAt.After(maxTime) { - maxTime = image.CreatedAt - } + if len(beforeImages) == 0 { + //nolint:stylecheck + return []images.Image{}, fmt.Errorf("No such image: %s", fetchImageNames(before)) + } + maxTime = beforeImages[0].CreatedAt + for _, image := range beforeImages { + if image.CreatedAt.After(maxTime) { + maxTime = image.CreatedAt } } } @@ -166,12 +176,14 @@ func FilterByCreatedAt(ctx context.Context, client *containerd.Client, before [] if err != nil { return []images.Image{}, err } - if len(sinceImages) > 0 { - minTime = sinceImages[0].CreatedAt - for _, image := range sinceImages { - if image.CreatedAt.Before(minTime) { - minTime = image.CreatedAt - } + if len(sinceImages) == 0 { + //nolint:stylecheck + return []images.Image{}, fmt.Errorf("No such image: %s", fetchImageNames(since)) + } + minTime = sinceImages[0].CreatedAt + for _, image := range sinceImages { + if image.CreatedAt.Before(minTime) { + minTime = image.CreatedAt } } } From 84b4d942bc8192cd17ea49bd8edca207ba19fb37 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 17 Oct 2024 13:38:06 -0700 Subject: [PATCH 0845/1066] Change compose lock to use DataStore() Signed-off-by: apostasie --- pkg/cmd/compose/compose.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index f9254d2e21f..5dde0b825e4 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -30,6 +30,7 @@ import ( "github.com/containerd/platforms" "github.com/containerd/nerdctl/v2/pkg/api/types" + "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" @@ -55,7 +56,11 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op // Note that we do not close the lock explicitly. Instead, the lock will get released when the `locked` global // variable will get collected and the file descriptor closed (eg: when the binary exits). var err error - locked, err = lockutil.Lock(globalOptions.DataRoot) + dataStore, err := clientutil.DataStore(globalOptions.DataRoot, globalOptions.Address) + if err != nil { + return nil, err + } + locked, err = lockutil.Lock(dataStore) if err != nil { return nil, err } From 468b0df21f6cea98348a651a446084533d9856fb Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 17 Oct 2024 13:56:16 -0700 Subject: [PATCH 0846/1066] Fix duplicated test title Signed-off-by: apostasie --- cmd/nerdctl/image/image_list_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index 01acaf29a02..75fb23f065a 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -179,7 +179,7 @@ RUN echo "actually creating a layer so that docker sets the createdAt time" }, }, { - Description: "label=foo=bar label=version=0.1", + Description: "label=foo=bar label=version=0.2", Command: test.Command("images", "--filter", "label=foo=bar", "--filter", "label=version=0.2"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ From 1ab6df3c2a6aaaa926bbb42d46e7bba230cc9715 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 17 Oct 2024 13:58:19 -0700 Subject: [PATCH 0847/1066] (Un-)marking flaky tests - #3512 is likely fixed, so, deflaking test - a couple of other circumstances failed the build (one of them with Docker) - commenting in-line - marking another instance of https://github.com/containerd/nerdctl/issues/3524 Signed-off-by: apostasie --- cmd/nerdctl/container/container_create_linux_test.go | 2 ++ cmd/nerdctl/container/container_logs_test.go | 1 + cmd/nerdctl/container/container_stop_linux_test.go | 2 ++ cmd/nerdctl/image/image_inspect_test.go | 5 +++++ cmd/nerdctl/image/image_list_test.go | 9 ++++++++- cmd/nerdctl/image/image_save_test.go | 5 +++++ cmd/nerdctl/ipfs/ipfs_compose_linux_test.go | 2 ++ 7 files changed, 25 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/container/container_create_linux_test.go b/cmd/nerdctl/container/container_create_linux_test.go index 56b71ce854a..6e8dbe2b491 100644 --- a/cmd/nerdctl/container/container_create_linux_test.go +++ b/cmd/nerdctl/container/container_create_linux_test.go @@ -131,6 +131,8 @@ func TestCreateWithMACAddress(t *testing.T) { // res = base.Cmd("start", "-i", containerName). // CmdOption(testutil.WithStdin(strings.NewReader("ip addr show eth0 | grep ether | awk '{printf $2}'"))).Run() res = base.Cmd("start", "-a", containerName).Run() + // FIXME: flaky - this has failed on the CI once, with the output NOT containing anything + // https://github.com/containerd/nerdctl/actions/runs/11392051487/job/31697214002?pr=3535#step:7:271 assert.Assert(t, strings.Contains(res.Stdout(), expect), fmt.Sprintf("expected output to contain %q: %q", expect, res.Stdout())) assert.Assert(t, res.ExitCode == 0, "Command should have succeeded") } else { diff --git a/cmd/nerdctl/container/container_logs_test.go b/cmd/nerdctl/container/container_logs_test.go index 085c5f840c6..71debda52e9 100644 --- a/cmd/nerdctl/container/container_logs_test.go +++ b/cmd/nerdctl/container/container_logs_test.go @@ -82,6 +82,7 @@ func TestLogsOutStreamsSeparated(t *testing.T) { } func TestLogsWithInheritedFlags(t *testing.T) { + // Seen flaky with Docker t.Parallel() base := testutil.NewBase(t) for k, v := range base.Args { diff --git a/cmd/nerdctl/container/container_stop_linux_test.go b/cmd/nerdctl/container/container_stop_linux_test.go index 2c0e0bc2bea..ab03dfd7e45 100644 --- a/cmd/nerdctl/container/container_stop_linux_test.go +++ b/cmd/nerdctl/container/container_stop_linux_test.go @@ -73,6 +73,8 @@ func TestStopStart(t *testing.T) { func TestStopWithStopSignal(t *testing.T) { t.Parallel() + // There may be issues with logs in Docker. + // This test is flaky with Docker. Might be related to https://github.com/containerd/nerdctl/pull/3557 base := testutil.NewBase(t) testContainerName := testutil.Identifier(t) defer base.Cmd("rm", "-f", testContainerName).Run() diff --git a/cmd/nerdctl/image/image_inspect_test.go b/cmd/nerdctl/image/image_inspect_test.go index 792c3ddc81e..816b163abbd 100644 --- a/cmd/nerdctl/image/image_inspect_test.go +++ b/cmd/nerdctl/image/image_inspect_test.go @@ -18,6 +18,7 @@ package image import ( "encoding/json" + "runtime" "strings" "testing" @@ -63,6 +64,10 @@ func TestImageInspectSimpleCases(t *testing.T) { }, } + if runtime.GOOS == "windows" { + testCase.Require = nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3524") + } + testCase.Run(t) } diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index 75fb23f065a..89d8bbaee47 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -18,6 +18,7 @@ package image import ( "fmt" + "runtime" "slices" "strings" "testing" @@ -117,6 +118,13 @@ func TestImages(t *testing.T) { }, } + if runtime.GOOS == "windows" { + testCase.Require = test.Require( + testCase.Require, + nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3524"), + ) + } + testCase.Run(t) } @@ -189,7 +197,6 @@ RUN echo "actually creating a layer so that docker sets the createdAt time" }, { Description: "label=version", - Require: nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3512"), Command: test.Command("images", "--filter", "label=version"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ diff --git a/cmd/nerdctl/image/image_save_test.go b/cmd/nerdctl/image/image_save_test.go index 23860cf443e..eb2617a1eb3 100644 --- a/cmd/nerdctl/image/image_save_test.go +++ b/cmd/nerdctl/image/image_save_test.go @@ -19,6 +19,7 @@ package image import ( "os" "path/filepath" + "runtime" "strings" "testing" @@ -70,6 +71,10 @@ func TestSave(t *testing.T) { // See https://github.com/containerd/nerdctl/issues/3425 and others for details. testCase.Require = nerdtest.Private + if runtime.GOOS == "windows" { + testCase.Require = nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3524") + } + testCase.SubTests = []*test.Case{ { Description: "Single image, by id", diff --git a/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go b/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go index a8c597de950..e1b78cc4c1e 100644 --- a/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_compose_linux_test.go @@ -46,6 +46,7 @@ func TestIPFSCompNoBuild(t *testing.T) { test.Not(nerdtest.Docker), nerdtest.Registry, nerdtest.IPFS, + nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3510"), // See note below // nerdtest.Private, ) @@ -153,6 +154,7 @@ services: WORDPRESS_DB_USER: exampleuser WORDPRESS_DB_PASSWORD: examplepass WORDPRESS_DB_NAME: exampledb + # FIXME: this is flaky and will make the container fail on occasions volumes: - wordpress:/var/www/html From d48be62f68f5f80943b4b9fedc454a4fe02de262 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 17 Oct 2024 12:41:00 -0700 Subject: [PATCH 0848/1066] Fix semantic of Fail to not care about exit code Signed-off-by: apostasie --- pkg/testutil/test/helpers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/testutil/test/helpers.go b/pkg/testutil/test/helpers.go index 99d769d7c3e..06411df8e99 100644 --- a/pkg/testutil/test/helpers.go +++ b/pkg/testutil/test/helpers.go @@ -70,7 +70,7 @@ func (help *helpersInternal) Anyhow(args ...string) { // Fail will run a command and make sure it does fail func (help *helpersInternal) Fail(args ...string) { help.Command(args...).Run(&Expected{ - ExitCode: 1, + ExitCode: -1, }) } From ce8e077d9548277ea05e543565cb7d33b7e57e65 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 17 Oct 2024 12:42:28 -0700 Subject: [PATCH 0849/1066] Chores: spurious comments and syntax simplification Signed-off-by: apostasie --- .../network/network_create_linux_test.go | 8 +------- cmd/nerdctl/network/network_list_linux_test.go | 3 --- pkg/cmd/image/ensure.go | 3 --- pkg/referenceutil/referenceutil_test.go | 17 ----------------- pkg/testutil/testutil.go | 9 ++------- 5 files changed, 3 insertions(+), 37 deletions(-) diff --git a/cmd/nerdctl/network/network_create_linux_test.go b/cmd/nerdctl/network/network_create_linux_test.go index 2d1274f19ea..596375f33db 100644 --- a/cmd/nerdctl/network/network_create_linux_test.go +++ b/cmd/nerdctl/network/network_create_linux_test.go @@ -35,8 +35,6 @@ func TestNetworkCreate(t *testing.T) { testCase.SubTests = []*test.Case{ { Description: "vanilla", - // #3491 and #3508 may have helped - commenting this out for now - // Require: nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3086"), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("network", "create", data.Identifier()) netw := nerdtest.InspectNetwork(helpers, data.Identifier()) @@ -66,8 +64,6 @@ func TestNetworkCreate(t *testing.T) { }, { Description: "with MTU", - // #3491 and #3508 may have helped - commenting this out for now - // Require: nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3086"), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("network", "create", data.Identifier(), "--driver", "bridge", "--opt", "com.docker.network.driver.mtu=9216") }, @@ -81,9 +77,7 @@ func TestNetworkCreate(t *testing.T) { }, { Description: "with ipv6", - // #3491 and #3508 may have helped - commenting this out for now - // Require: nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3086"), - Require: nerdtest.OnlyIPv6, + Require: nerdtest.OnlyIPv6, Setup: func(data test.Data, helpers test.Helpers) { subnetStr := "2001:db8:8::/64" data.Set("subnetStr", subnetStr) diff --git a/cmd/nerdctl/network/network_list_linux_test.go b/cmd/nerdctl/network/network_list_linux_test.go index af8c8d1ca0b..22620287a66 100644 --- a/cmd/nerdctl/network/network_list_linux_test.go +++ b/cmd/nerdctl/network/network_list_linux_test.go @@ -29,9 +29,6 @@ import ( func TestNetworkLsFilter(t *testing.T) { testCase := nerdtest.Setup() - // #3491 and #3508 may have helped - commenting this out for now - // testCase.Require = nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3086"), - testCase.Setup = func(data test.Data, helpers test.Helpers) { data.Set("identifier", data.Identifier()) data.Set("label", "mylabel=label-1") diff --git a/pkg/cmd/image/ensure.go b/pkg/cmd/image/ensure.go index de2634871ea..fe5f6ca88c5 100644 --- a/pkg/cmd/image/ensure.go +++ b/pkg/cmd/image/ensure.go @@ -65,9 +65,6 @@ func ensureOne(ctx context.Context, client *containerd.Client, rawRef string, ta if err != nil { return err } - // if platform == nil { - // platform = platforms.DefaultSpec() - //} pltf := []ocispec.Platform{platform} platformComparer := platformutil.NewMatchComparerFromOCISpecPlatformSlice(pltf) diff --git a/pkg/referenceutil/referenceutil_test.go b/pkg/referenceutil/referenceutil_test.go index 11d6441ca6c..699d1c3f487 100644 --- a/pkg/referenceutil/referenceutil_test.go +++ b/pkg/referenceutil/referenceutil_test.go @@ -27,7 +27,6 @@ func TestReferenceUtil(t *testing.T) { needles := map[string]struct { Error string String string - Normalized string Suggested string FamiliarName string FamiliarMatch map[string]bool @@ -82,7 +81,6 @@ func TestReferenceUtil(t *testing.T) { "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50": { Error: "", String: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", - Normalized: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", Suggested: "untitled-abcde", FamiliarName: "", Protocol: "", @@ -94,7 +92,6 @@ func TestReferenceUtil(t *testing.T) { "4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50": { Error: "", String: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", - Normalized: "sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", Suggested: "untitled-abcde", FamiliarName: "", Protocol: "", @@ -106,7 +103,6 @@ func TestReferenceUtil(t *testing.T) { "image_name": { Error: "", String: "docker.io/library/image_name:latest", - Normalized: "docker.io/library/image_name:latest", Suggested: "image_name-abcde", FamiliarName: "image_name", Protocol: "", @@ -119,7 +115,6 @@ func TestReferenceUtil(t *testing.T) { "library/image_name": { Error: "", String: "docker.io/library/image_name:latest", - Normalized: "docker.io/library/image_name:latest", Suggested: "image_name-abcde", FamiliarName: "image_name", Protocol: "", @@ -132,7 +127,6 @@ func TestReferenceUtil(t *testing.T) { "something/image_name": { Error: "", String: "docker.io/something/image_name:latest", - Normalized: "docker.io/something/image_name:latest", Suggested: "image_name-abcde", FamiliarName: "something/image_name", Protocol: "", @@ -145,7 +139,6 @@ func TestReferenceUtil(t *testing.T) { "docker.io/library/image_name": { Error: "", String: "docker.io/library/image_name:latest", - Normalized: "docker.io/library/image_name:latest", Suggested: "image_name-abcde", FamiliarName: "image_name", Protocol: "", @@ -158,7 +151,6 @@ func TestReferenceUtil(t *testing.T) { "image_name:latest": { Error: "", String: "docker.io/library/image_name:latest", - Normalized: "docker.io/library/image_name:latest", Suggested: "image_name-abcde", FamiliarName: "image_name", Protocol: "", @@ -171,7 +163,6 @@ func TestReferenceUtil(t *testing.T) { "image_name:foo": { Error: "", String: "docker.io/library/image_name:foo", - Normalized: "docker.io/library/image_name:foo", Suggested: "image_name-abcde", FamiliarName: "image_name", Protocol: "", @@ -184,7 +175,6 @@ func TestReferenceUtil(t *testing.T) { "image_name@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50": { Error: "", String: "docker.io/library/image_name@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", - Normalized: "docker.io/library/image_name@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", Suggested: "image_name-abcde", FamiliarName: "image_name", Protocol: "", @@ -197,7 +187,6 @@ func TestReferenceUtil(t *testing.T) { "image_name:latest@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50": { Error: "", String: "docker.io/library/image_name:latest@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", - Normalized: "docker.io/library/image_name:latest@sha256:4b826db5f1f14d1db0b560304f189d4b17798ddce2278b7822c9d32313fe3f50", Suggested: "image_name-abcde", FamiliarName: "image_name", Protocol: "", @@ -210,7 +199,6 @@ func TestReferenceUtil(t *testing.T) { "ghcr.io:1234/image_name": { Error: "", String: "ghcr.io:1234/image_name:latest", - Normalized: "ghcr.io:1234/image_name:latest", Suggested: "image_name-abcde", FamiliarName: "ghcr.io:1234/image_name", Protocol: "", @@ -223,7 +211,6 @@ func TestReferenceUtil(t *testing.T) { "ghcr.io/sub_name/image_name": { Error: "", String: "ghcr.io/sub_name/image_name:latest", - Normalized: "ghcr.io/sub_name/image_name:latest", Suggested: "image_name-abcde", FamiliarName: "ghcr.io/sub_name/image_name", Protocol: "", @@ -236,7 +223,6 @@ func TestReferenceUtil(t *testing.T) { "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze": { Error: "", String: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", - Normalized: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", Suggested: "ipfs-bafkr-abcde", FamiliarName: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", Protocol: "ipfs", @@ -249,7 +235,6 @@ func TestReferenceUtil(t *testing.T) { "ipfs://bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze": { Error: "", String: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", - Normalized: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", Suggested: "ipfs-bafkr-abcde", FamiliarName: "bafkreicq4dg6nkef5ju422ptedcwfz6kcvpvvhuqeykfrwq5krazf3muze", Protocol: "ipfs", @@ -262,7 +247,6 @@ func TestReferenceUtil(t *testing.T) { "ipfs://ghcr.io/stargz-containers/alpine:3.13-org": { Error: "", String: "ghcr.io/stargz-containers/alpine:3.13-org", - Normalized: "ghcr.io/stargz-containers/alpine:3.13-org", Suggested: "alpine-abcde", FamiliarName: "ghcr.io/stargz-containers/alpine", FamiliarMatch: map[string]bool{ @@ -280,7 +264,6 @@ func TestReferenceUtil(t *testing.T) { "ipfs://alpine": { Error: "", String: "docker.io/library/alpine:latest", - Normalized: "docker.io/library/alpine:latest", Suggested: "alpine-abcde", FamiliarName: "alpine", Protocol: "ipfs", diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 8dd8a1edce6..3c83d22366f 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -180,9 +180,7 @@ func (b *Base) EnsureDaemonActive() { sleep = 3 * time.Second ) for i := 0; i < maxRetry; i++ { - cmd := exec.Command("systemctl", - append(systemctlArgs, - []string{"is-active", target}...)...) + cmd := exec.Command("systemctl", append(systemctlArgs, "is-active", target)...) out, err := cmd.CombinedOutput() b.T.Logf("(retry=%d) %s", i, string(out)) if err == nil { @@ -204,10 +202,7 @@ func (b *Base) DumpDaemonLogs(minutes int) { b.T.Helper() target := b.systemctlTarget() cmd := exec.Command("journalctl", - append(b.systemctlArgs(), - []string{"-u", target, - "--no-pager", - "-S", fmt.Sprintf("%d min ago", minutes)}...)...) + append(b.systemctlArgs(), "-u", target, "--no-pager", "-S", fmt.Sprintf("%d min ago", minutes))...) b.T.Logf("===== %v =====", cmd.Args) out, err := cmd.CombinedOutput() if err != nil { From 83bf7e039c1b2a1c8234a6ae676190eb1a61f35e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 22:08:37 +0000 Subject: [PATCH 0850/1066] build(deps): bump go.uber.org/mock from 0.4.0 to 0.5.0 Bumps [go.uber.org/mock](https://github.com/uber/mock) from 0.4.0 to 0.5.0. - [Release notes](https://github.com/uber/mock/releases) - [Changelog](https://github.com/uber-go/mock/blob/main/CHANGELOG.md) - [Commits](https://github.com/uber/mock/compare/v0.4.0...v0.5.0) --- updated-dependencies: - dependency-name: go.uber.org/mock dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 68eb2153826..5af256da78e 100644 --- a/go.mod +++ b/go.mod @@ -64,7 +64,7 @@ require ( github.com/vishvananda/netlink v1.3.0 github.com/vishvananda/netns v0.0.4 github.com/yuchanns/srslog v1.1.0 - go.uber.org/mock v0.4.0 + go.uber.org/mock v0.5.0 golang.org/x/crypto v0.28.0 golang.org/x/net v0.30.0 golang.org/x/sync v0.8.0 diff --git a/go.sum b/go.sum index 34ebae7dcb5..2aa10101e64 100644 --- a/go.sum +++ b/go.sum @@ -331,8 +331,8 @@ go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8d go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= 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= -go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= From 54966d87f9daba9ce73675df621a0f2b6e9df648 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 16 Oct 2024 22:03:08 -0700 Subject: [PATCH 0851/1066] Rewrite build tests Signed-off-by: apostasie --- .../builder/builder_build_linux_test.go | 85 -- .../builder/builder_build_oci_layout_test.go | 107 ++ cmd/nerdctl/builder/builder_build_test.go | 1200 +++++++++++------ cmd/nerdctl/builder/builder_builder_test.go | 152 +++ cmd/nerdctl/builder/builder_linux_test.go | 168 --- pkg/testutil/nerdtest/requirements.go | 7 +- pkg/testutil/testutil.go | 18 - pkg/testutil/testutil_freebsd.go | 1 + pkg/testutil/testutil_windows.go | 4 +- 9 files changed, 1075 insertions(+), 667 deletions(-) delete mode 100644 cmd/nerdctl/builder/builder_build_linux_test.go create mode 100644 cmd/nerdctl/builder/builder_build_oci_layout_test.go create mode 100644 cmd/nerdctl/builder/builder_builder_test.go delete mode 100644 cmd/nerdctl/builder/builder_linux_test.go diff --git a/cmd/nerdctl/builder/builder_build_linux_test.go b/cmd/nerdctl/builder/builder_build_linux_test.go deleted file mode 100644 index 0f80066b0a2..00000000000 --- a/cmd/nerdctl/builder/builder_build_linux_test.go +++ /dev/null @@ -1,85 +0,0 @@ -/* - 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 builder - -import ( - "fmt" - "testing" - - "gotest.tools/v3/assert" - - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestBuildContextWithOCILayout(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - - var dockerBuilderArgs []string - if testutil.IsDocker() { - // Default docker driver does not support OCI exporter. - // Reference: https://docs.docker.com/build/exporters/oci-docker/ - builderName := testutil.SetupDockerContainerBuilder(t) - dockerBuilderArgs = []string{"buildx", "--builder", builderName} - } - - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - ociLayout := "parent" - parentImageName := fmt.Sprintf("%s-%s", imageName, ociLayout) - - teardown := func() { - base.Cmd("rmi", parentImageName, imageName).Run() - } - t.Cleanup(teardown) - teardown() - - dockerfile := fmt.Sprintf(`FROM %s -LABEL layer=oci-layout-parent -CMD ["echo", "test-nerdctl-build-context-oci-layout-parent"]`, testutil.CommonImage) - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - tarPath := fmt.Sprintf("%s/%s.tar", buildCtx, ociLayout) - - // Create OCI archive from parent image. - base.Cmd("build", buildCtx, "--tag", parentImageName).AssertOK() - base.Cmd("image", "save", "--output", tarPath, parentImageName).AssertOK() - - // Unpack OCI archive into OCI layout directory. - ociLayoutDir := t.TempDir() - err := helpers.ExtractTarFile(ociLayoutDir, tarPath) - assert.NilError(t, err) - - dockerfile = fmt.Sprintf(`FROM %s -CMD ["echo", "test-nerdctl-build-context-oci-layout"]`, ociLayout) - buildCtx = helpers.CreateBuildContext(t, dockerfile) - - var buildArgs = []string{} - if testutil.IsDocker() { - buildArgs = dockerBuilderArgs - } - - buildArgs = append(buildArgs, "build", buildCtx, fmt.Sprintf("--build-context=%s=oci-layout://%s", ociLayout, ociLayoutDir), "--tag", imageName) - if testutil.IsDocker() { - // Need to load the container image from the builder to be able to run it. - buildArgs = append(buildArgs, "--load") - } - - base.Cmd(buildArgs...).AssertOK() - base.Cmd("run", "--rm", imageName).AssertOutContains("test-nerdctl-build-context-oci-layout") -} diff --git a/cmd/nerdctl/builder/builder_build_oci_layout_test.go b/cmd/nerdctl/builder/builder_build_oci_layout_test.go new file mode 100644 index 00000000000..a3fea9b5fa5 --- /dev/null +++ b/cmd/nerdctl/builder/builder_build_oci_layout_test.go @@ -0,0 +1,107 @@ +/* + 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 builder + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestBuildContextWithOCILayout(t *testing.T) { + nerdtest.Setup() + + var dockerBuilderArgs []string + + testCase := &test.Case{ + Require: test.Require( + nerdtest.Build, + test.Not(test.Windows), + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + if nerdtest.IsDocker() { + helpers.Anyhow("buildx", "stop", data.Identifier("-container")) + helpers.Anyhow("buildx", "rm", "--force", data.Identifier("-container")) + } + helpers.Anyhow("rmi", "-f", data.Identifier("-parent")) + helpers.Anyhow("rmi", "-f", data.Identifier("-child")) + }, + Setup: func(data test.Data, helpers test.Helpers) { + // Default docker driver does not support OCI exporter. + // Reference: https://docs.docker.com/build/exporters/oci-docker/ + if nerdtest.IsDocker() { + name := data.Identifier("-container") + helpers.Ensure("buildx", "create", "--name", name, "--driver=docker-container") + dockerBuilderArgs = []string{"buildx", "--builder", name} + } + + dockerfile := fmt.Sprintf(`FROM %s +LABEL layer=oci-layout-parent +CMD ["echo", "test-nerdctl-build-context-oci-layout-parent"]`, testutil.CommonImage) + + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + + tarPath := filepath.Join(buildCtx, "parent.tar") + dest := filepath.Join(buildCtx, "parent") + assert.NilError(helpers.T(), os.MkdirAll(dest, 0o700)) + helpers.Ensure("build", buildCtx, "--tag", data.Identifier("-parent")) + helpers.Ensure("image", "save", "--output", tarPath, data.Identifier("-parent")) + helpers.Custom("tar", "Cxf", dest, tarPath).Run(&test.Expected{}) + }, + + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + dockerfile := `FROM parent +CMD ["echo", "test-nerdctl-build-context-oci-layout"]` + + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + + var cmd test.TestableCommand + if nerdtest.IsDocker() { + cmd = helpers.Command(dockerBuilderArgs...) + } else { + cmd = helpers.Command() + } + cmd.WithArgs("build", buildCtx, fmt.Sprintf("--build-context=parent=oci-layout://%s", filepath.Join(buildCtx, "parent")), "--tag", data.Identifier("-child")) + if nerdtest.IsDocker() { + // Need to load the container image from the builder to be able to run it. + cmd.WithArgs("--load") + } + return cmd + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + assert.Assert(t, strings.Contains(helpers.Capture("run", "--rm", data.Identifier("-child")), "test-nerdctl-build-context-oci-layout"), info) + }, + } + }, + } + + testCase.Run(t) +} diff --git a/cmd/nerdctl/builder/builder_build_test.go b/cmd/nerdctl/builder/builder_build_test.go index 6b9052f9d12..e3d736f9435 100644 --- a/cmd/nerdctl/builder/builder_build_test.go +++ b/cmd/nerdctl/builder/builder_build_test.go @@ -17,531 +17,943 @@ package builder import ( + "errors" "fmt" "os" "path/filepath" + "runtime" "strings" "testing" "gotest.tools/v3/assert" - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" + "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func TestBuild(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() +func TestBuildBasics(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Require: nerdtest.Build, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-build-test-string"]`, testutil.CommonImage) + err := os.WriteFile(filepath.Join(data.TempDir(), "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + data.Set("buildCtx", data.TempDir()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + SubTests: []*test.Case{ + { + Description: "Successfully build with 'tag first', 'buildctx second'", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", "-t", data.Identifier(), data.Get("buildCtx")) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("nerdctl-build-test-string\n")), + }, + { + Description: "Successfully build with 'buildctx first', 'tag second'", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("nerdctl-build-test-string\n")), + }, + { + Description: "Successfully build with output docker, main tag still works", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "-t", data.Identifier(), "--output=type=docker,name="+data.Identifier("ignored")) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("nerdctl-build-test-string\n")), + }, + { + Description: "Successfully build with output docker, name cannot be used", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "-t", data.Identifier(), "--output=type=docker,name="+data.Identifier("ignored")) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier("ignored")) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(-1, nil, nil), + }, + }, + } - dockerfile := fmt.Sprintf(`FROM %s -CMD ["echo", "nerdctl-build-test-string"] - `, testutil.CommonImage) + testCase.Run(t) +} - buildCtx := helpers.CreateBuildContext(t, dockerfile) +func TestCanBuildOnOtherPlatform(t *testing.T) { + nerdtest.Setup() - base.Cmd("build", "-t", imageName, buildCtx).AssertOK() - base.Cmd("build", buildCtx, "-t", imageName).AssertOK() - base.Cmd("run", "--rm", imageName).AssertOutExactly("nerdctl-build-test-string\n") + requireEmulation := &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (bool, string) { + candidateArch := "arm64" + if runtime.GOARCH == "arm64" { + candidateArch = "amd64" + } + can, err := platformutil.CanExecProbably("linux/" + candidateArch) + assert.NilError(helpers.T(), err) - ignoredImageNamed := imageName + "-" + "ignored" - outputOpt := fmt.Sprintf("--output=type=docker,name=%s", ignoredImageNamed) - base.Cmd("build", buildCtx, "-t", imageName, outputOpt).AssertOK() + data.Set("OS", "linux") + data.Set("Architecture", candidateArch) + return can, "Current environment does not support emulation" + }, + } - base.Cmd("run", "--rm", imageName).AssertOutExactly("nerdctl-build-test-string\n") - base.Cmd("run", "--rm", ignoredImageNamed).AssertFail() + testCase := &test.Case{ + Require: test.Require( + nerdtest.Build, + requireEmulation, + ), + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s +RUN echo hello > /hello +CMD ["echo", "nerdctl-build-test-string"]`, testutil.CommonImage) + err := os.WriteFile(filepath.Join(data.TempDir(), "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + data.Set("buildCtx", data.TempDir()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", data.Get("buildCtx"), "--platform", fmt.Sprintf("%s/%s", data.Get("OS"), data.Get("Architecture")), "-t", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, nil), + } + + testCase.Run(t) } // TestBuildBaseImage tests if an image can be built on the previously built image. // This isn't currently supported by nerdctl with BuildKit OCI worker. func TestBuildBaseImage(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() - imageName2 := imageName + "-2" - defer base.Cmd("rmi", imageName2).Run() - - dockerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Require: nerdtest.Build, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier("first")) + helpers.Anyhow("rmi", "-f", data.Identifier("second")) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s RUN echo hello > /hello -CMD ["echo", "nerdctl-build-test-string"] - `, testutil.CommonImage) +CMD ["echo", "nerdctl-build-test-string"]`, testutil.CommonImage) + err := os.WriteFile(filepath.Join(data.TempDir(), "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", "-t", data.Identifier("first"), data.TempDir()) - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", "-t", imageName, buildCtx).AssertOK() - base.Cmd("build", buildCtx, "-t", imageName).AssertOK() - - dockerfile2 := fmt.Sprintf(`FROM %s + dockerfileSecond := fmt.Sprintf(`FROM %s RUN echo hello2 > /hello2 -CMD ["cat", "/hello2"] - `, imageName) - - buildCtx2 := helpers.CreateBuildContext(t, dockerfile2) - - base.Cmd("build", "-t", imageName2, buildCtx2).AssertOK() - base.Cmd("build", buildCtx2, "-t", imageName2).AssertOK() +CMD ["cat", "/hello2"]`, data.Identifier("first")) + err = os.WriteFile(filepath.Join(data.TempDir(), "Dockerfile"), []byte(dockerfileSecond), 0644) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", "-t", data.Identifier("second"), data.TempDir()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier("second")) + }, + Expected: test.Expects(0, nil, test.Equals("hello2\n")), + } - base.Cmd("run", "--rm", imageName2).AssertOutExactly("hello2\n") + testCase.Run(t) } // TestBuildFromContainerd tests if an image can be built on an image pulled by nerdctl. // This isn't currently supported by nerdctl with BuildKit OCI worker. func TestBuildFromContainerd(t *testing.T) { - testutil.DockerIncompatible(t) - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() - imageName2 := imageName + "-2" - defer base.Cmd("rmi", imageName2).Run() - - // FIXME: BuildKit sometimes tries to use base image manifests of platforms that hasn't been - // pulled by `nerdctl pull`. This leads to "not found" error for the base image. - // To avoid this issue, images shared to BuildKit should always be pulled by manifest - // digest or `--all-platforms` needs to be added. - base.Cmd("pull", "--all-platforms", testutil.CommonImage).AssertOK() - base.Cmd("tag", testutil.CommonImage, imageName).AssertOK() - base.Cmd("rmi", testutil.CommonImage).AssertOK() - - dockerfile2 := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Require: test.Require( + nerdtest.Build, + test.Not(nerdtest.Docker), + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier("first")) + helpers.Anyhow("rmi", "-f", data.Identifier("second")) + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "--quiet", testutil.CommonImage) + helpers.Ensure("tag", testutil.CommonImage, data.Identifier("first")) + + dockerfile := fmt.Sprintf(`FROM %s RUN echo hello2 > /hello2 -CMD ["cat", "/hello2"] - `, imageName) - - buildCtx2 := helpers.CreateBuildContext(t, dockerfile2) - - base.Cmd("build", "-t", imageName2, buildCtx2).AssertOK() - base.Cmd("build", buildCtx2, "-t", imageName2).AssertOK() +CMD ["cat", "/hello2"]`, data.Identifier("first")) + err := os.WriteFile(filepath.Join(data.TempDir(), "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", "-t", data.Identifier("second"), data.TempDir()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier("second")) + }, + Expected: test.Expects(0, nil, test.Equals("hello2\n")), + } - base.Cmd("run", "--rm", imageName2).AssertOutExactly("hello2\n") + testCase.Run(t) } func TestBuildFromStdin(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() - - dockerfile := fmt.Sprintf(`FROM %s -CMD ["echo", "nerdctl-build-test-stdin"] - `, testutil.CommonImage) + nerdtest.Setup() + + testCase := &test.Case{ + Require: nerdtest.Build, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-build-test-stdin"]`, testutil.CommonImage) + cmd := helpers.Command("build", "-t", data.Identifier(), "-f", "-", ".") + cmd.WithStdin(strings.NewReader(dockerfile)) + return cmd + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Errors: []error{errors.New(data.Identifier())}, + } + }, + } - base.Cmd("build", "-t", imageName, "-f", "-", ".").CmdOption(testutil.WithStdin(strings.NewReader(dockerfile))).AssertCombinedOutContains(imageName) + testCase.Run(t) } func TestBuildWithDockerfile(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() - - dockerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Require: nerdtest.Build, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-test-dockerfile"] `, testutil.CommonImage) + buildCtx := filepath.Join(data.TempDir(), "test") + err := os.MkdirAll(buildCtx, 0755) + assert.NilError(helpers.T(), err) + err = os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + data.Set("buildCtx", buildCtx) + }, + SubTests: []*test.Case{ + { + Description: "Dockerfile ..", + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command("build", "-t", data.Identifier(), "-f", "Dockerfile", "..") + cmd.WithCwd(data.Get("buildCtx")) + return cmd + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "Dockerfile .", + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command("build", "-t", data.Identifier(), "-f", "Dockerfile", ".") + cmd.WithCwd(data.Get("buildCtx")) + return cmd + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "../Dockerfile .", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command("build", "-t", data.Identifier(), "-f", "../Dockerfile", ".") + cmd.WithCwd(data.Get("buildCtx")) + return cmd + }, + Expected: test.Expects(1, nil, nil), + }, + }, + } - buildCtx := filepath.Join(t.TempDir(), "test") - err := os.MkdirAll(buildCtx, 0755) - assert.NilError(t, err) - err = os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0644) - assert.NilError(t, err) - - pwd, err := os.Getwd() - assert.NilError(t, err) - err = os.Chdir(buildCtx) - assert.NilError(t, err) - defer os.Chdir(pwd) - - // hack os.Getwd return "(unreachable)" on rootless - base.Env = append(base.Env, "PWD="+buildCtx) - - base.Cmd("build", "-t", imageName, "-f", "Dockerfile", "..").AssertOK() - base.Cmd("build", "-t", imageName, "-f", "Dockerfile", ".").AssertOK() - // fail err: no such file or directory - base.Cmd("build", "-t", imageName, "-f", "../Dockerfile", ".").AssertFail() + testCase.Run(t) } func TestBuildLocal(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) + nerdtest.Setup() + const testFileName = "nerdctl-build-test" const testContent = "nerdctl" - outputDir := t.TempDir() - dockerfile := fmt.Sprintf(`FROM scratch -COPY %s /`, - testFileName) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - if err := os.WriteFile(filepath.Join(buildCtx, testFileName), []byte(testContent), 0644); err != nil { - t.Fatal(err) + testCase := &test.Case{ + Require: nerdtest.Build, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM scratch +COPY %s /`, testFileName) + + err := os.WriteFile(filepath.Join(data.TempDir(), "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + + err = os.WriteFile(filepath.Join(data.TempDir(), testFileName), []byte(testContent), 0644) + assert.NilError(helpers.T(), err) + + data.Set("buildCtx", data.TempDir()) + }, + SubTests: []*test.Case{ + { + Description: "destination 1", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", "-o", fmt.Sprintf("type=local,dest=%s", data.TempDir()), data.Get("buildCtx")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + testFilePath := filepath.Join(data.TempDir(), testFileName) + _, err := os.Stat(testFilePath) + assert.NilError(helpers.T(), err, info) + dt, err := os.ReadFile(testFilePath) + assert.NilError(helpers.T(), err, info) + assert.Equal(helpers.T(), string(dt), testContent, info) + }, + } + }, + }, + { + Description: "destination 2", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", "-o", data.TempDir(), data.Get("buildCtx")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + testFilePath := filepath.Join(data.TempDir(), testFileName) + _, err := os.Stat(testFilePath) + assert.NilError(helpers.T(), err, info) + dt, err := os.ReadFile(testFilePath) + assert.NilError(helpers.T(), err, info) + assert.Equal(helpers.T(), string(dt), testContent, info) + }, + } + }, + }, + }, } - testFilePath := filepath.Join(outputDir, testFileName) - base.Cmd("build", "-o", fmt.Sprintf("type=local,dest=%s", outputDir), buildCtx).AssertOK() - if _, err := os.Stat(testFilePath); err != nil { - t.Fatal(err) - } - data, err := os.ReadFile(testFilePath) - assert.NilError(t, err) - assert.Equal(t, string(data), testContent) - - aliasOutputDir := t.TempDir() - testAliasFilePath := filepath.Join(aliasOutputDir, testFileName) - base.Cmd("build", "-o", aliasOutputDir, buildCtx).AssertOK() - if _, err := os.Stat(testAliasFilePath); err != nil { - t.Fatal(err) - } - data, err = os.ReadFile(testAliasFilePath) - assert.NilError(t, err) - assert.Equal(t, string(data), testContent) + testCase.Run(t) } func TestBuildWithBuildArg(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() - - dockerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Require: nerdtest.Build, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s ARG TEST_STRING=1 ENV TEST_STRING=$TEST_STRING CMD echo $TEST_STRING `, testutil.CommonImage) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", buildCtx, "-t", imageName).AssertOK() - base.Cmd("run", "--rm", imageName).AssertOutExactly("1\n") - - validCases := []struct { - name string - arg string - envValue string - envSet bool - expected string - }{ - {"ArgValueOverridesDefault", "TEST_STRING=2", "", false, "2\n"}, - {"EmptyArgValueOverridesDefault", "TEST_STRING=", "", false, "\n"}, - {"UnsetArgKeyPreservesDefault", "TEST_STRING", "", false, "1\n"}, - {"EnvValueOverridesDefault", "TEST_STRING", "3", true, "3\n"}, - {"EmptyEnvValueOverridesDefault", "TEST_STRING", "", true, "\n"}, + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + data.Set("buildCtx", buildCtx) + }, + SubTests: []*test.Case{ + { + Description: "No args", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("1\n")), + }, + { + Description: "ArgValueOverridesDefault", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "--build-arg", "TEST_STRING=2", "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("2\n")), + }, + { + Description: "EmptyArgValueOverridesDefault", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "--build-arg", "TEST_STRING=", "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("\n")), + }, + { + Description: "UnsetArgKeyPreservesDefault", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "--build-arg", "TEST_STRING", "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("1\n")), + }, + { + Description: "EnvValueOverridesDefault", + Env: map[string]string{ + "TEST_STRING": "3", + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "--build-arg", "TEST_STRING", "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("3\n")), + }, + { + Description: "EmptyEnvValueOverridesDefault", + Env: map[string]string{ + "TEST_STRING": "", + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "--build-arg", "TEST_STRING", "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("\n")), + }, + }, } - for _, tc := range validCases { - t.Run(tc.name, func(t *testing.T) { - subBase := testutil.NewBase(t) - if tc.envSet { - subBase.Env = append(base.Env, "TEST_STRING="+tc.envValue) - } - - subBase.Cmd("build", buildCtx, "-t", imageName, "--build-arg", tc.arg).AssertOK() - subBase.Cmd("run", "--rm", imageName).AssertOutExactly(tc.expected) - }) - } + testCase.Run(t) } func TestBuildWithIIDFile(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() - - dockerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Require: nerdtest.Build, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", buildCtx, "--iidfile", filepath.Join(data.TempDir(), "id.txt"), "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + imageID, err := os.ReadFile(filepath.Join(data.TempDir(), "id.txt")) + assert.NilError(helpers.T(), err) + return helpers.Command("run", "--rm", string(imageID)) + }, + + Expected: test.Expects(0, nil, test.Equals("nerdctl-build-test-string\n")), + } - buildCtx := helpers.CreateBuildContext(t, dockerfile) - fileName := filepath.Join(t.TempDir(), "id.txt") - - base.Cmd("build", "-t", imageName, buildCtx, "--iidfile", fileName).AssertOK() - base.Cmd("build", buildCtx, "-t", imageName, "--iidfile", fileName).AssertOK() - defer os.Remove(fileName) - - imageID, err := os.ReadFile(fileName) - assert.NilError(t, err) - - base.Cmd("run", "--rm", string(imageID)).AssertOutExactly("nerdctl-build-test-string\n") + testCase.Run(t) } func TestBuildWithLabels(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - - dockerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Require: nerdtest.Build, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s LABEL name=nerdctl-build-test-label `, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", buildCtx, "--label", "label=test", "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("inspect", data.Identifier(), "--format", "{{json .Config.Labels }}") + }, + + Expected: test.Expects(0, nil, test.Equals("{\"label\":\"test\",\"name\":\"nerdctl-build-test-label\"}\n")), + } - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", "-t", imageName, buildCtx, "--label", "label=test").AssertOK() - defer base.Cmd("rmi", imageName).Run() - - base.Cmd("inspect", imageName, "--format", "{{json .Config.Labels }}").AssertOutExactly("{\"label\":\"test\",\"name\":\"nerdctl-build-test-label\"}\n") + testCase.Run(t) } func TestBuildMultipleTags(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - img := testutil.Identifier(t) - imgWithNoTag, imgWithCustomTag := fmt.Sprintf("%s%d", img, 2), fmt.Sprintf("%s%d:hello", img, 3) - defer base.Cmd("rmi", img).AssertOK() - defer base.Cmd("rmi", imgWithNoTag).AssertOK() - defer base.Cmd("rmi", imgWithCustomTag).AssertOK() - - buildOutputs := []string{"nerdctl-build-test-string", "nerdctl-build-test-string-rebuild"} - for _, output := range buildOutputs { - dockerfile := fmt.Sprintf(`FROM %s - CMD ["echo", "%s"] - `, testutil.CommonImage, output) - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", "-t", img, buildCtx).AssertOK() - base.Cmd("build", buildCtx, "-t", img, "-t", imgWithNoTag, "-t", imgWithCustomTag).AssertOK() - base.Cmd("run", "--rm", img).AssertOutExactly(output + "\n") - base.Cmd("run", "--rm", imgWithNoTag).AssertOutExactly(output + "\n") - base.Cmd("run", "--rm", imgWithCustomTag).AssertOutExactly(output + "\n") + nerdtest.Setup() + + testCase := &test.Case{ + Require: nerdtest.Build, + Data: test.WithData("i1", "image"). + Set("i2", "image2"). + Set("i3", "image3:hello"), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Get("i1")) + helpers.Anyhow("rmi", "-f", data.Get("i2")) + helpers.Anyhow("rmi", "-f", data.Get("i3")) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-build-test-string"] + `, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", buildCtx, "-t", data.Get("i1"), "-t", data.Get("i2"), "-t", data.Get("i3")) + }, + SubTests: []*test.Case{ + { + Description: "i1", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get("i1")) + }, + + Expected: test.Expects(0, nil, test.Equals("nerdctl-build-test-string\n")), + }, + { + Description: "i2", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get("i2")) + }, + + Expected: test.Expects(0, nil, test.Equals("nerdctl-build-test-string\n")), + }, + { + Description: "i3", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Get("i3")) + }, + + Expected: test.Expects(0, nil, test.Equals("nerdctl-build-test-string\n")), + }, + }, } + + testCase.Run(t) } func TestBuildWithContainerfile(t *testing.T) { - testutil.DockerIncompatible(t) - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() - - containerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Require: test.Require( + nerdtest.Build, + test.Not(nerdtest.Docker), + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Containerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", buildCtx, "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("nerdctl-build-test-string\n")), + } - buildCtx := t.TempDir() - - var err = os.WriteFile(filepath.Join(buildCtx, "Containerfile"), []byte(containerfile), 0644) - assert.NilError(t, err) - base.Cmd("build", "-t", imageName, buildCtx).AssertOK() - base.Cmd("run", "--rm", imageName).AssertOutExactly("nerdctl-build-test-string\n") + testCase.Run(t) } func TestBuildWithDockerFileAndContainerfile(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).Run() - - dockerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Require: nerdtest.Build, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "dockerfile"] `, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + dockerfile = fmt.Sprintf(`FROM %s +CMD ["echo", "containerfile"] + `, testutil.CommonImage) + err = os.WriteFile(filepath.Join(buildCtx, "Containerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", buildCtx, "-t", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("dockerfile\n")), + } - containerfile := fmt.Sprintf(`FROM %s - CMD ["echo", "containerfile"] - `, testutil.CommonImage) - - tmpDir := t.TempDir() - - var err = os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644) - assert.NilError(t, err) - - err = os.WriteFile(filepath.Join(tmpDir, "Containerfile"), []byte(containerfile), 0644) - assert.NilError(t, err) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", "-t", imageName, buildCtx).AssertOK() - base.Cmd("run", "--rm", imageName).AssertOutExactly("dockerfile\n") + testCase.Run(t) } func TestBuildNoTag(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - base.Cmd("image", "prune", "--force", "--all").AssertOK() - - dockerfile := fmt.Sprintf(`FROM %s -CMD ["echo", "nerdctl-build-notag-string"] + nerdtest.Setup() + + // FIXME: this test should be rewritten and instead get the image id from the build, then query the image explicitly - instead of pruning / noparallel + testCase := &test.Case{ + NoParallel: true, + Require: nerdtest.Build, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("image", "prune", "--force", "--all") + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := helpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", buildCtx) + }, + Command: test.Command("images"), + Expected: test.Expects(0, nil, test.Contains("")), + } - base.Cmd("build", buildCtx).AssertOK() - base.Cmd("images").AssertOutContains("") - base.Cmd("image", "prune", "--force", "--all").AssertOK() + testCase.Run(t) } func TestBuildContextDockerImageAlias(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - base.Cmd("image", "prune", "--force", "--all").AssertOK() - - dockerfile := `FROM myorg/myapp + nerdtest.Setup() + + testCase := &test.Case{ + Require: nerdtest.Build, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := `FROM myorg/myapp CMD ["echo", "nerdctl-build-myorg/myapp"]` - buildCtx := helpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + data.Set("buildCtx", buildCtx) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", "-t", data.Identifier(), data.Get("buildCtx"), fmt.Sprintf("--build-context=myorg/myapp=docker-image://%s", testutil.CommonImage)) + }, + Expected: test.Expects(0, nil, nil), + } - base.Cmd("build", buildCtx, fmt.Sprintf("--build-context=myorg/myapp=docker-image://%s", testutil.CommonImage)).AssertOK() - base.Cmd("images").AssertOutContains("") - base.Cmd("image", "prune", "--force", "--all").AssertOK() + testCase.Run(t) } func TestBuildContextWithCopyFromDir(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - base.Cmd("image", "prune", "--force", "--all").AssertOK() + nerdtest.Setup() content := "hello_from_dir_2" filename := "hello.txt" - dir2 := t.TempDir() - filePath := filepath.Join(dir2, filename) - err := os.WriteFile(filePath, []byte(content), 0644) - assert.NilError(t, err) - - dockerfile := fmt.Sprintf(`FROM %s + testCase := &test.Case{ + Require: test.Require( + nerdtest.Build, + test.Not(nerdtest.Docker), + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dir2 := helpers.T().TempDir() + filePath := filepath.Join(dir2, filename) + err := os.WriteFile(filePath, []byte(content), 0o600) + assert.NilError(helpers.T(), err) + dockerfile := fmt.Sprintf(`FROM %s COPY --from=dir2 /%s /hello_from_dir2.txt RUN ["cat", "/hello_from_dir2.txt"]`, testutil.CommonImage, filename) + buildCtx := data.TempDir() + err = os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + data.Set("buildCtx", buildCtx) + data.Set("dir2", dir2) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", "-t", data.Identifier(), data.Get("buildCtx"), fmt.Sprintf("--build-context=dir2=%s", data.Get("dir2"))) + }, + Expected: test.Expects(0, nil, nil), + } - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("build", buildCtx, fmt.Sprintf("--build-context=dir2=%s", dir2)).AssertOK() - base.Cmd("images").AssertOutContains("") - base.Cmd("image", "prune", "--force", "--all").AssertOK() + testCase.Run(t) } // TestBuildSourceDateEpoch tests that $SOURCE_DATE_EPOCH is propagated from the client env // https://github.com/docker/buildx/pull/1482 func TestBuildSourceDateEpoch(t *testing.T) { - testutil.RequiresBuild(t) - base := testutil.NewBase(t) - imageName := testutil.Identifier(t) - defer base.Cmd("rmi", imageName).AssertOK() - - dockerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Require: test.Require( + nerdtest.Build, + test.Not(nerdtest.Docker), + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s ARG SOURCE_DATE_EPOCH RUN echo $SOURCE_DATE_EPOCH >/source-date-epoch CMD ["cat", "/source-date-epoch"] `, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + data.Set("buildCtx", buildCtx) + }, + SubTests: []*test.Case{ + { + Description: "1111111111", + Env: map[string]string{ + "SOURCE_DATE_EPOCH": "1111111111", + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "-t", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("1111111111\n")), + }, + { + Description: "2222222222", + Env: map[string]string{ + "SOURCE_DATE_EPOCH": "1111111111", + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("build", data.Get("buildCtx"), "--build-arg", "SOURCE_DATE_EPOCH=2222222222", "-t", data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("2222222222\n")), + }, + }, + } - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - const sourceDateEpochEnvStr = "1111111111" - base.Env = append(base.Env, "SOURCE_DATE_EPOCH="+sourceDateEpochEnvStr) - base.Cmd("build", "-t", imageName, buildCtx).AssertOK() - base.Cmd("run", "--rm", imageName).AssertOutExactly(sourceDateEpochEnvStr + "\n") - - const sourceDateEpochArgStr = "2222222222" - base.Cmd("build", "-t", imageName, "--build-arg", "SOURCE_DATE_EPOCH="+sourceDateEpochArgStr, buildCtx).AssertOK() - base.Cmd("run", "--rm", imageName).AssertOutExactly(sourceDateEpochArgStr + "\n") + testCase.Run(t) } func TestBuildNetwork(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - - dockerfile := fmt.Sprintf(`FROM %s + nerdtest.Setup() + + testCase := &test.Case{ + Require: test.Require( + nerdtest.Build, + test.Not(nerdtest.Docker), + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s RUN apk add --no-cache curl RUN curl -I http://google.com `, testutil.CommonImage) - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - validCases := []struct { - name string - network string - exitCode int - }{ - // When network=none, can't connect to internet, therefore cannot download packages in the dockerfile - // Order is important here, test fails for `-test.target=docker` in CI - {"test_with_no_network", "none", 1}, - {"test_with_empty_network", "", 0}, - {"test_with_default_network", "default", 0}, + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + data.Set("buildCtx", buildCtx) + }, + SubTests: []*test.Case{ + { + Description: "none", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", data.Get("buildCtx"), "-t", data.Identifier(), "--no-cache", "--network", "none") + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(1, nil, nil), + }, + { + Description: "empty", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", data.Get("buildCtx"), "-t", data.Identifier(), "--no-cache", "--network", "") + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "default", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", data.Get("buildCtx"), "-t", data.Identifier(), "--no-cache", "--network", "default") + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Expected: test.Expects(0, nil, nil), + }, + }, } - for _, tc := range validCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - // --no-cache is intentional here for `-test.target=docker` - base.Cmd("build", buildCtx, "-t", tc.name, "--no-cache", "--network", tc.network).AssertExitCode(tc.exitCode) - if tc.exitCode != 1 { - defer base.Cmd("rmi", tc.name).AssertOK() - } - }) - } -} - -func TestBuildNetworkShellCompletion(t *testing.T) { - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - const gsc = "__complete" - // Tests with build network - networkName := "default" - base.Cmd(gsc, "build", "--network", "").AssertOutContains(networkName) -} - -func buildWithNamedBuilder(base *testutil.Base, builderName string, args ...string) *testutil.Cmd { - buildArgs := []string{"build"} - if testutil.GetTarget() == testutil.Docker { - buildArgs = append(buildArgs, "--builder", builderName) - } - buildArgs = append(buildArgs, args...) - return base.Cmd(buildArgs...) + testCase.Run(t) } func TestBuildAttestation(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - builderName := testutil.Identifier(t) - if testutil.GetTarget() == testutil.Docker { - // create named builder for docker - defer base.Cmd("buildx", "rm", builderName).AssertOK() - base.Cmd("buildx", "create", "--name", builderName, "--bootstrap", "--use").AssertOK() - } - - dockerfile := "FROM " + testutil.NginxAlpineImage - buildCtx := helpers.CreateBuildContext(t, dockerfile) + nerdtest.Setup() - // Test sbom - outputSBOMDir := t.TempDir() - buildWithNamedBuilder(base, builderName, "--sbom=true", "-o", fmt.Sprintf("type=local,dest=%s", outputSBOMDir), buildCtx).AssertOK() const testSBOMFileName = "sbom.spdx.json" - testSBOMFilePath := filepath.Join(outputSBOMDir, testSBOMFileName) - if _, err := os.Stat(testSBOMFilePath); err != nil { - t.Fatal(err) - } - - // Test provenance - outputProvenanceDir := t.TempDir() - buildWithNamedBuilder(base, builderName, "--provenance=mode=min", "-o", fmt.Sprintf("type=local,dest=%s", outputProvenanceDir), buildCtx).AssertOK() const testProvenanceFileName = "provenance.json" - testProvenanceFilePath := filepath.Join(outputProvenanceDir, testProvenanceFileName) - if _, err := os.Stat(testProvenanceFilePath); err != nil { - t.Fatal(err) - } - // Test attestation - outputAttestationDir := t.TempDir() - buildWithNamedBuilder(base, builderName, "--attest=type=provenance,mode=min", "--attest=type=sbom", "-o", fmt.Sprintf("type=local,dest=%s", outputAttestationDir), buildCtx).AssertOK() - testSBOMFilePath = filepath.Join(outputAttestationDir, testSBOMFileName) - testProvenanceFilePath = filepath.Join(outputAttestationDir, testProvenanceFileName) - if _, err := os.Stat(testSBOMFilePath); err != nil { - t.Fatal(err) - } - if _, err := os.Stat(testProvenanceFilePath); err != nil { - t.Fatal(err) + testCase := &test.Case{ + Require: test.Require( + nerdtest.Build, + test.Not(nerdtest.Docker), + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + if nerdtest.IsDocker() { + helpers.Anyhow("buildx", "rm", data.Identifier("builder")) + } + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + if nerdtest.IsDocker() { + helpers.Anyhow("buildx", "create", "--name", data.Identifier("builder"), "--bootstrap", "--use") + } + + dockerfile := fmt.Sprintf(`FROM %s`, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + data.Set("buildCtx", buildCtx) + }, + SubTests: []*test.Case{ + { + Description: "SBOM", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + outputSBOMDir := helpers.T().TempDir() + data.Set("outputSBOMFile", filepath.Join(outputSBOMDir, testSBOMFileName)) + + cmd := helpers.Command("build") + if nerdtest.IsDocker() { + cmd.WithArgs("--builder", data.Identifier("builder")) + } + cmd.WithArgs("--sbom=true", "-o", fmt.Sprintf("type=local,dest=%s", outputSBOMDir), data.Get("buildCtx")) + return cmd + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + _, err := os.Stat(data.Get("outputSBOMFile")) + assert.NilError(t, err, info) + }, + } + }, + }, + { + Description: "Provenance", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + outputProvenanceDir := data.TempDir() + data.Set("outputProvenanceFile", filepath.Join(outputProvenanceDir, testProvenanceFileName)) + + cmd := helpers.Command("build") + if nerdtest.IsDocker() { + cmd.WithArgs("--builder", data.Identifier("builder")) + } + cmd.WithArgs("--provenance=mode=min", "-o", fmt.Sprintf("type=local,dest=%s", outputProvenanceDir), data.Get("buildCtx")) + return cmd + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + _, err := os.Stat(data.Get("outputProvenanceFile")) + assert.NilError(t, err, info) + }, + } + }, + }, + { + Description: "Attestation", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + outputAttestationDir := data.TempDir() + data.Set("outputSBOMFile", filepath.Join(outputAttestationDir, testSBOMFileName)) + data.Set("outputProvenanceFile", filepath.Join(outputAttestationDir, testProvenanceFileName)) + + cmd := helpers.Command("build") + if nerdtest.IsDocker() { + cmd.WithArgs("--builder", data.Identifier("builder")) + } + cmd.WithArgs("--attest=type=provenance,mode=min", "--attest=type=sbom", "-o", fmt.Sprintf("type=local,dest=%s", outputAttestationDir), data.Get("buildCtx")) + return cmd + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + _, err := os.Stat(data.Get("outputSBOMFile")) + assert.NilError(t, err, info) + _, err = os.Stat(data.Get("outputProvenanceFile")) + assert.NilError(t, err, info) + }, + } + }, + }, + }, } + + testCase.Run(t) } diff --git a/cmd/nerdctl/builder/builder_builder_test.go b/cmd/nerdctl/builder/builder_builder_test.go new file mode 100644 index 00000000000..9be5e185faa --- /dev/null +++ b/cmd/nerdctl/builder/builder_builder_test.go @@ -0,0 +1,152 @@ +/* + 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 builder + +import ( + "bytes" + "errors" + "fmt" + "os" + "path/filepath" + "testing" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestBuilder(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + NoParallel: true, + Require: test.Require( + nerdtest.Build, + test.Not(test.Windows), + ), + SubTests: []*test.Case{ + { + Description: "PruneForce", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-test-builder-prune"]`, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", buildCtx) + }, + Command: test.Command("builder", "prune", "--force"), + Expected: test.Expects(0, nil, nil), + }, + { + Description: "PruneForceAll", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-test-builder-prune"]`, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + helpers.Ensure("build", buildCtx) + }, + Command: test.Command("builder", "prune", "--force", "--all"), + Expected: test.Expects(0, nil, nil), + }, + { + Description: "Debug", + NoParallel: true, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + dockerfile := fmt.Sprintf(`FROM %s +CMD ["echo", "nerdctl-builder-debug-test-string"]`, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + cmd := helpers.Command("builder", "debug", buildCtx) + cmd.WithStdin(bytes.NewReader([]byte("c\n"))) + return cmd + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "WithPull", + Setup: func(data test.Data, helpers test.Helpers) { + // FIXME: this test should be rewritten to dynamically retrieve the ids, and use images + // available on all platforms + oldImage := testutil.BusyboxImage + oldImageSha := "141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47" + newImage := testutil.AlpineImage + newImageSha := "ec14c7992a97fc11425907e908340c6c3d6ff602f5f13d899e6b7027c9b4133a" + + helpers.Ensure("pull", "--quiet", oldImage) + helpers.Ensure("tag", oldImage, newImage) + + dockerfile := fmt.Sprintf(`FROM %s`, newImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + + data.Set("buildCtx", buildCtx) + data.Set("oldImageSha", oldImageSha) + data.Set("newImageSha", newImageSha) + }, + SubTests: []*test.Case{ + { + Description: "pull false", + NoParallel: true, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", data.Get("buildCtx"), "--pull=false") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Errors: []error{errors.New(data.Get("oldImageSha"))}, + } + }, + }, + { + Description: "pull true", + NoParallel: true, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", data.Get("buildCtx"), "--pull=true") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Errors: []error{errors.New(data.Get("newImageSha"))}, + } + }, + }, + { + Description: "no pull", + NoParallel: true, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", data.Get("buildCtx")) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Errors: []error{errors.New(data.Get("newImageSha"))}, + } + }, + }, + }, + }, + }, + } + + testCase.Run(t) +} diff --git a/cmd/nerdctl/builder/builder_linux_test.go b/cmd/nerdctl/builder/builder_linux_test.go deleted file mode 100644 index 862320142f9..00000000000 --- a/cmd/nerdctl/builder/builder_linux_test.go +++ /dev/null @@ -1,168 +0,0 @@ -/* - 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 builder - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "path/filepath" - "testing" - - "gotest.tools/v3/assert" - - "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestBuilderPrune(t *testing.T) { - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - - base := testutil.NewBase(t) - - dockerfile := fmt.Sprintf(`FROM %s -CMD ["echo", "nerdctl-test-builder-prune"]`, testutil.CommonImage) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - testCases := []struct { - name string - commandArgs []string - }{ - { - name: "TestBuilderPruneForce", - commandArgs: []string{"builder", "prune", "--force"}, - }, - { - name: "TestBuilderPruneForceAll", - commandArgs: []string{"builder", "prune", "--force", "--all"}, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - base.Cmd("build", buildCtx).AssertOK() - base.Cmd(tc.commandArgs...).AssertOK() - }) - } -} - -func TestBuilderDebug(t *testing.T) { - testutil.DockerIncompatible(t) - base := testutil.NewBase(t) - - dockerfile := fmt.Sprintf(`FROM %s -CMD ["echo", "nerdctl-builder-debug-test-string"] - `, testutil.CommonImage) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - base.Cmd("builder", "debug", buildCtx).CmdOption(testutil.WithStdin(bytes.NewReader([]byte("c\n")))).AssertOK() -} - -func TestBuildWithPull(t *testing.T) { - testutil.DockerIncompatible(t) - if rootlessutil.IsRootless() { - t.Skipf("skipped because the test needs a custom buildkitd config") - } - testutil.RequiresBuild(t) - testutil.RegisterBuildCacheCleanup(t) - - oldImage := testutil.BusyboxImage - oldImageSha := "141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47" - newImage := testutil.AlpineImage - - buildkitConfig := fmt.Sprintf(`[worker.oci] -enabled = false - -[worker.containerd] -enabled = true -namespace = "%s"`, testutil.Namespace) - - cleanup := useBuildkitConfig(t, buildkitConfig) - defer cleanup() - - testCases := []struct { - name string - pull string - }{ - { - name: "build with local image", - pull: "false", - }, - { - name: "build with newest image", - pull: "true", - }, - { - name: "build with buildkit default", - // buildkit default pulls from remote - pull: "default", - }, - } - - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - testutil.RegisterBuildCacheCleanup(t) - base := testutil.NewBase(t) - base.Cmd("image", "prune", "--force", "--all").AssertOK() - - base.Cmd("pull", oldImage).Run() - base.Cmd("tag", oldImage, newImage).Run() - - dockerfile := fmt.Sprintf(`FROM %s`, newImage) - tmpDir := t.TempDir() - err := os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644) - assert.NilError(t, err) - - buildCtx := helpers.CreateBuildContext(t, dockerfile) - - buildCmd := []string{"build", buildCtx} - switch tc.pull { - case "false": - buildCmd = append(buildCmd, "--pull=false") - base.Cmd(buildCmd...).AssertErrContains(oldImageSha) - case "true": - buildCmd = append(buildCmd, "--pull=true") - base.Cmd(buildCmd...).AssertErrNotContains(oldImageSha) - case "default": - base.Cmd(buildCmd...).AssertErrNotContains(oldImageSha) - } - }) - } -} - -func useBuildkitConfig(t *testing.T, config string) (cleanup func()) { - buildkitConfigPath := "/etc/buildkit/buildkitd.toml" - - currConfig, err := exec.Command("cat", buildkitConfigPath).Output() - assert.NilError(t, err) - - os.WriteFile(buildkitConfigPath, []byte(config), 0644) - _, err = exec.Command("systemctl", "restart", "buildkit").Output() - assert.NilError(t, err) - - return func() { - assert.NilError(t, os.WriteFile(buildkitConfigPath, currConfig, 0644)) - _, err = exec.Command("systemctl", "restart", "buildkit").Output() - assert.NilError(t, err) - } -} diff --git a/pkg/testutil/nerdtest/requirements.go b/pkg/testutil/nerdtest/requirements.go index 0ab60d382d8..575270a129b 100644 --- a/pkg/testutil/nerdtest/requirements.go +++ b/pkg/testutil/nerdtest/requirements.go @@ -271,7 +271,12 @@ var Build = &test.Requirement{ return ret, mess }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("builder", "prune", "--all", "--force") + // Previously, every build test was sequential, and was purging the build cache. + // Running this in parallel of any other test depending on build will trash it. + // The only way to parallelize any test involving build is indeed to disable this. + // The price to pay is that we might get cache from another test. + // This can be avoided individually by passing --no-cache if and when necessary + // helpers.Anyhow("builder", "prune", "--all", "--force") }, } diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index 8dd8a1edce6..a7bb0c6ee2e 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -859,21 +859,3 @@ func KubectlHelper(base *Base, args ...string) *Cmd { Base: base, } } - -// SetupDockerContainerBuilder creates a Docker builder using the docker-container driver -// and adds cleanup steps to test cleanup. The builder name is returned as output. -// -// If not docker, this function returns an empty string as the builder name. -func SetupDockerContainerBuilder(t *testing.T) string { - var name string - if IsDocker() { - name = fmt.Sprintf("%s-container", Identifier(t)) - base := NewBase(t) - base.Cmd("buildx", "create", "--name", name, "--driver=docker-container").AssertOK() - t.Cleanup(func() { - base.Cmd("buildx", "stop", name).AssertOK() - base.Cmd("buildx", "rm", "--force", name).AssertOK() - }) - } - return name -} diff --git a/pkg/testutil/testutil_freebsd.go b/pkg/testutil/testutil_freebsd.go index 5c0fb9ba293..026c68a3012 100644 --- a/pkg/testutil/testutil_freebsd.go +++ b/pkg/testutil/testutil_freebsd.go @@ -30,6 +30,7 @@ const ( ) var ( + BusyboxImage = mirrorOf("busybox:1.28") AlpineImage = mirrorOf("alpine:3.13") NginxAlpineImage = mirrorOf("nginx:1.19-alpine") GolangImage = mirrorOf("golang:1.18") diff --git a/pkg/testutil/testutil_windows.go b/pkg/testutil/testutil_windows.go index edf86ba9143..69934ae1a51 100644 --- a/pkg/testutil/testutil_windows.go +++ b/pkg/testutil/testutil_windows.go @@ -43,7 +43,9 @@ const ( NginxAlpineImage = "registry.k8s.io/e2e-test-images/nginx:1.14-2" NginxAlpineIndexHTMLSnippet = "Welcome to nginx!" - GolangImage = "fixme-test-using-this-image-is-disabled-on-windows" + GolangImage = "fixme-test-using-this-image-is-disabled-on-windows" + BusyboxImage = "fixme-test-using-this-image-is-disabled-on-windows" + AlpineImage = "fixme-test-using-this-image-is-disabled-on-windows" // This error string is expected when attempting to connect to a TCP socket // for a service which actively refuses the connection. From ca76611c84c34e606c8e4ef19047808573193906 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 15 Oct 2024 18:08:53 -0700 Subject: [PATCH 0852/1066] Fix and enable CI unit testing for windows Signed-off-by: apostasie --- .github/workflows/test.yml | 26 +++++++++++++++++-- pkg/cmd/builder/build_test.go | 12 +++++++++ pkg/composer/serviceparser/build_test.go | 6 +++++ .../serviceparser/serviceparser_test.go | 13 ++++++++++ .../credentialsstore_test.go | 4 +++ .../dockercompat/dockercompat_test.go | 2 +- pkg/logging/cri_logger_test.go | 4 +++ pkg/logging/json_logger_test.go | 4 +++ pkg/mountutil/mountutil_windows_test.go | 2 +- 9 files changed, 69 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4577a894cce..7c56fd5acbe 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,8 +40,19 @@ jobs: make lint-imports test-unit: - runs-on: ubuntu-24.04 - timeout-minutes: 20 + timeout-minutes: 5 + name: unit | ${{ matrix.goos }} + runs-on: "${{ matrix.os }}" + defaults: + run: + shell: bash + strategy: + matrix: + include: + - os: windows-2022 + goos: windows + - os: ubuntu-24.04 + goos: linux steps: - uses: actions/checkout@v4.2.1 with: @@ -51,6 +62,17 @@ jobs: go-version: ${{ env.GO_VERSION }} check-latest: true cache: true + - if: ${{ matrix.goos=='windows' }} + uses: actions/checkout@v4.2.1 + with: + repository: containerd/containerd + ref: v1.7.23 + path: containerd + fetch-depth: 1 + - if: ${{ matrix.goos=='windows' }} + name: "Set up CNI" + working-directory: containerd + run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Run unit tests" run: go test -v ./pkg/... diff --git a/pkg/cmd/builder/build_test.go b/pkg/cmd/builder/build_test.go index 954738cdbc6..081d899d7f3 100644 --- a/pkg/cmd/builder/build_test.go +++ b/pkg/cmd/builder/build_test.go @@ -17,7 +17,10 @@ package builder import ( + "fmt" + "path/filepath" "reflect" + "runtime" "testing" specs "github.com/opencontainers/image-spec/specs-go/v1" @@ -213,6 +216,15 @@ func TestParseBuildctlArgsForOCILayout(t *testing.T) { }, } + if runtime.GOOS == "windows" { + abspath, err := filepath.Abs("/tmp/oci-layout") + assert.NilError(t, err) + tests[1].expectedErr = fmt.Sprintf( + "open %s\\index.json: The system cannot find the path specified.", + abspath, + ) + } + for _, test := range tests { t.Run(test.name, func(t *testing.T) { args, err := parseBuildContextFromOCILayout(test.ociLayoutName, test.ociLayoutPath) diff --git a/pkg/composer/serviceparser/build_test.go b/pkg/composer/serviceparser/build_test.go index 2ffa8962515..34af7143aec 100644 --- a/pkg/composer/serviceparser/build_test.go +++ b/pkg/composer/serviceparser/build_test.go @@ -17,6 +17,7 @@ package serviceparser import ( + "runtime" "testing" "gotest.tools/v3/assert" @@ -30,6 +31,11 @@ func lastOf(ss []string) string { func TestParseBuild(t *testing.T) { t.Parallel() + + if runtime.GOOS == "windows" { + t.Skip("test is not compatible with windows") + } + const dockerComposeYAML = ` services: foo: diff --git a/pkg/composer/serviceparser/serviceparser_test.go b/pkg/composer/serviceparser/serviceparser_test.go index 65cf517cb67..337617a49f9 100644 --- a/pkg/composer/serviceparser/serviceparser_test.go +++ b/pkg/composer/serviceparser/serviceparser_test.go @@ -20,6 +20,7 @@ import ( "fmt" "os" "path/filepath" + "runtime" "strconv" "testing" @@ -79,6 +80,11 @@ var in = strutil.InStringSlice func TestParse(t *testing.T) { t.Parallel() + + if runtime.GOOS == "windows" { + t.Skip("test is not compatible with windows") + } + const dockerComposeYAML = ` version: '3.1' @@ -333,6 +339,10 @@ services: func TestParseRelative(t *testing.T) { t.Parallel() + + if runtime.GOOS == "windows" { + t.Skip("test is not compatible with windows") + } const dockerComposeYAML = ` services: foo: @@ -408,6 +418,9 @@ services: func TestParseConfigs(t *testing.T) { t.Parallel() + if runtime.GOOS == "windows" { + t.Skip("test is not compatible with windows") + } const dockerComposeYAML = ` services: foo: diff --git a/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go b/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go index a9890dffdcd..003fe1aa211 100644 --- a/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go +++ b/pkg/imgutil/dockerconfigresolver/credentialsstore_test.go @@ -46,6 +46,10 @@ func TestBrokenCredentialsStore(t *testing.T) { // Anyhow, this test is about extreme cases & conditions (filesystem errors wrt credentials loading). t.Skip("skipping broken credential store tests for freebsd") } + if runtime.GOOS == "windows" { + // Same as above + t.Skip("test is not compatible with windows") + } testCases := []struct { description string diff --git a/pkg/inspecttypes/dockercompat/dockercompat_test.go b/pkg/inspecttypes/dockercompat/dockercompat_test.go index 483f7aed3d8..12814bc31fc 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat_test.go +++ b/pkg/inspecttypes/dockercompat/dockercompat_test.go @@ -68,7 +68,7 @@ func TestContainerFromNative(t *testing.T) { expected: &Container{ Created: "0001-01-01T00:00:00Z", Platform: runtime.GOOS, - ResolvConfPath: tempStateDir + "/resolv.conf", + ResolvConfPath: filepath.Join(tempStateDir, "resolv.conf"), State: &ContainerState{ Status: "running", Running: true, diff --git a/pkg/logging/cri_logger_test.go b/pkg/logging/cri_logger_test.go index f497b436a44..6d45e4999bc 100644 --- a/pkg/logging/cri_logger_test.go +++ b/pkg/logging/cri_logger_test.go @@ -30,6 +30,7 @@ import ( "os" "path/filepath" "reflect" + "runtime" "testing" "time" ) @@ -234,6 +235,9 @@ func TestReadLogsLimitsWithTimestamps(t *testing.T) { func TestReadRotatedLog(t *testing.T) { tmpDir := t.TempDir() + if runtime.GOOS == "windows" { + t.Skip("windows implementation does not seem to work right now and should be fixed: https://github.com/containerd/nerdctl/issues/3554") + } file, err := os.CreateTemp(tmpDir, "logfile") if err != nil { t.Errorf("unable to create temp file, error: %s", err.Error()) diff --git a/pkg/logging/json_logger_test.go b/pkg/logging/json_logger_test.go index 53e6e434867..7d0be36285d 100644 --- a/pkg/logging/json_logger_test.go +++ b/pkg/logging/json_logger_test.go @@ -22,12 +22,16 @@ import ( "fmt" "os" "path/filepath" + "runtime" "testing" "time" ) func TestReadRotatedJSONLog(t *testing.T) { tmpDir := t.TempDir() + if runtime.GOOS == "windows" { + t.Skip("windows implementation does not seem to work right now and should be fixed: https://github.com/containerd/nerdctl/issues/3554") + } file, err := os.CreateTemp(tmpDir, "logfile") if err != nil { t.Errorf("unable to create temp file, error: %s", err.Error()) diff --git a/pkg/mountutil/mountutil_windows_test.go b/pkg/mountutil/mountutil_windows_test.go index 661c45c0f5a..05428b113c5 100644 --- a/pkg/mountutil/mountutil_windows_test.go +++ b/pkg/mountutil/mountutil_windows_test.go @@ -38,7 +38,7 @@ func TestParseVolumeOptions(t *testing.T) { vType: "bind", src: "dummy", optsRaw: "rw", - wants: []string{}, + wants: nil, }, { vType: "volume", From 36f7eb91311bb49865cbff96cc0afa2644936634 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 14 Oct 2024 21:13:18 -0700 Subject: [PATCH 0853/1066] Rewrite commit tests Signed-off-by: apostasie --- .../container/container_commit_linux_test.go | 124 +++++++++--------- .../container/container_commit_test.go | 81 ++++++++---- 2 files changed, 112 insertions(+), 93 deletions(-) diff --git a/cmd/nerdctl/container/container_commit_linux_test.go b/cmd/nerdctl/container/container_commit_linux_test.go index 8a4af41fdcd..710e37aeef4 100644 --- a/cmd/nerdctl/container/container_commit_linux_test.go +++ b/cmd/nerdctl/container/container_commit_linux_test.go @@ -21,76 +21,70 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -/* -This test below is meant to assert that https://github.com/containerd/nerdctl/issues/827 is NOT fixed. -Obviously, once we fix the issue, it should be replaced by something that assert it works. -Unfortunately, this is flaky. -It will regularly succeed or fail, making random PR fail the Kube check. -*/ - -func TestKubeCommitPush(t *testing.T) { - t.Parallel() - - base := testutil.NewBaseForKubernetes(t) - tID := testutil.Identifier(t) - - var containerID string - // var registryIP string - - setup := func() { - testutil.KubectlHelper(base, "run", "--image", testutil.CommonImage, tID, "--", "sleep", "Inf"). - AssertOK() - - testutil.KubectlHelper(base, "wait", "pod", tID, "--for=condition=ready", "--timeout=1m"). - AssertOK() - - testutil.KubectlHelper(base, "exec", tID, "--", "mkdir", "-p", "/tmp/whatever"). - AssertOK() - - cmd := testutil.KubectlHelper(base, "get", "pods", tID, "-o", "jsonpath={ .status.containerStatuses[0].containerID }") - cmd.Run() - containerID = strings.TrimPrefix(cmd.Out(), "containerd://") - - // This below is missing configuration to allow for plain http communication - // This is left here for future work to successfully start a registry usable in the cluster - /* - // Start a registry - testutil.KubectlHelper(base, "run", "--port", "5000", "--image", testutil.RegistryImageStable, "testregistry"). - AssertOK() - - testutil.KubectlHelper(base, "wait", "pod", "testregistry", "--for=condition=ready", "--timeout=1m"). - AssertOK() - - cmd = testutil.KubectlHelper(base, "get", "pods", tID, "-o", "jsonpath={ .status.hostIPs[0].ip }") - cmd.Run() - registryIP = cmd.Out() - - cmd = testutil.KubectlHelper(base, "apply", "-f", "-", fmt.Sprintf(`apiVersion: v1 - kind: ConfigMap - metadata: - name: local-registry - namespace: nerdctl-test - data: - localRegistryHosting.v1: | - host: "%s:5000" - help: "https://kind.sigs.k8s.io/docs/user/local-registry/" - `, registryIP)) - */ - +func TestKubeCommitSave(t *testing.T) { + testCase := nerdtest.Setup() + + testCase.Require = nerdtest.OnlyKubernetes + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + containerID := "" + // NOTE: kubectl namespaces are not the same as containerd namespaces. + // We still want kube test objects segregated in their own Kube API namespace. + nerdtest.KubeCtlCommand(helpers, "create", "namespace", "nerdctl-test-k8s").Run(&test.Expected{}) + nerdtest.KubeCtlCommand(helpers, "run", "--image", testutil.CommonImage, data.Identifier(), "--", "sleep", "Inf").Run(&test.Expected{}) + nerdtest.KubeCtlCommand(helpers, "wait", "pod", data.Identifier(), "--for=condition=ready", "--timeout=1m").Run(&test.Expected{}) + nerdtest.KubeCtlCommand(helpers, "exec", data.Identifier(), "--", "mkdir", "-p", "/tmp/whatever").Run(&test.Expected{}) + nerdtest.KubeCtlCommand(helpers, "get", "pods", data.Identifier(), "-o", "jsonpath={ .status.containerStatuses[0].containerID }").Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + containerID = strings.TrimPrefix(stdout, "containerd://") + }, + }) + data.Set("containerID", containerID) } - tearDown := func() { - testutil.KubectlHelper(base, "delete", "pod", "--all").Run() + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + nerdtest.KubeCtlCommand(helpers, "delete", "pod", "--all").Run(nil) } - tearDown() - t.Cleanup(tearDown) - setup() + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + helpers.Ensure("commit", data.Get("containerID"), "testcommitsave") + return helpers.Command("save", "testcommitsave") + } - t.Run("test commit / push on Kube (https://github.com/containerd/nerdctl/issues/827)", func(t *testing.T) { - base.Cmd("commit", containerID, "testcommitsave").AssertOK() - base.Cmd("save", "testcommitsave").AssertOK() - }) + testCase.Expected = test.Expects(0, nil, nil) + + testCase.Run(t) + + // This below is missing configuration to allow for plain http communication + // This is left here for future work to successfully start a registry usable in the cluster + /* + // Start a registry + nerdtest.KubeCtlCommand(helpers, "run", "--port", "5000", "--image", testutil.RegistryImageStable, "testregistry"). + Run(&test.Expected{}) + + nerdtest.KubeCtlCommand(helpers, "wait", "pod", "testregistry", "--for=condition=ready", "--timeout=1m"). + AssertOK() + + cmd = nerdtest.KubeCtlCommand(helpers, "get", "pods", tID, "-o", "jsonpath={ .status.hostIPs[0].ip }") + cmd.Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + registryIP = stdout + }, + }) + + cmd = nerdtest.KubeCtlCommand(helpers, "apply", "-f", "-", fmt.Sprintf(`apiVersion: v1 + kind: ConfigMap + metadata: + name: local-registry + namespace: nerdctl-test + data: + localRegistryHosting.v1: | + host: "%s:5000" + help: "https://kind.sigs.k8s.io/docs/user/local-registry/" + `, registryIP)) + */ } diff --git a/cmd/nerdctl/container/container_commit_test.go b/cmd/nerdctl/container/container_commit_test.go index f9f553d9ca1..9382a782d7a 100644 --- a/cmd/nerdctl/container/container_commit_test.go +++ b/cmd/nerdctl/container/container_commit_test.go @@ -17,39 +17,64 @@ package container import ( - "fmt" "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestCommit(t *testing.T) { - t.Parallel() - base := testutil.NewBase(t) - switch base.Info().CgroupDriver { - case "none", "": - t.Skip("requires cgroup (for pausing)") - } - testContainer := testutil.Identifier(t) - testImage := testutil.Identifier(t) + "-img" - defer base.Cmd("rm", "-f", testContainer).Run() - defer base.Cmd("rmi", testImage).Run() - - for _, pause := range []string{ - "true", - "false", - } { - base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", "infinity").AssertOK() - base.EnsureContainerStarted(testContainer) - base.Cmd("exec", testContainer, "sh", "-euxc", `echo hello-test-commit > /foo`).AssertOK() - base.Cmd( - "commit", - "-c", `CMD ["/foo"]`, - "-c", `ENTRYPOINT ["cat"]`, - fmt.Sprintf("--pause=%s", pause), - testContainer, testImage).AssertOK() - base.Cmd("run", "--rm", testImage).AssertOutExactly("hello-test-commit\n") - base.Cmd("rm", "-f", testContainer).Run() - base.Cmd("rmi", testImage).Run() + testCase := nerdtest.Setup() + + testCase.SubTests = []*test.Case{ + { + Description: "with pause", + Require: nerdtest.CGroup, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + nerdtest.EnsureContainerStarted(helpers, data.Identifier()) + helpers.Ensure("exec", data.Identifier(), "sh", "-euxc", `echo hello-test-commit > /foo`) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + helpers.Ensure( + "commit", + "-c", `CMD ["/foo"]`, + "-c", `ENTRYPOINT ["cat"]`, + "--pause=true", + data.Identifier(), data.Identifier()) + return helpers.Command("run", "--rm", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("hello-test-commit\n")), + }, + { + Description: "no pause", + Require: test.Not(test.Windows), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + nerdtest.EnsureContainerStarted(helpers, data.Identifier()) + helpers.Ensure("exec", data.Identifier(), "sh", "-euxc", `echo hello-test-commit > /foo`) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + helpers.Ensure( + "commit", + "-c", `CMD ["/foo"]`, + "-c", `ENTRYPOINT ["cat"]`, + "--pause=false", + data.Identifier(), data.Identifier()) + return helpers.Command("run", "--rm", data.Identifier()) + }, + Expected: test.Expects(0, nil, test.Equals("hello-test-commit\n")), + }, } + + testCase.Run(t) } From 914238eb6362052e8d4871e92138f069eda7c63b Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 15 Oct 2024 01:17:37 -0700 Subject: [PATCH 0854/1066] Kuberneters testing tooling cleanup Signed-off-by: apostasie --- pkg/testutil/nerdtest/requirements.go | 7 ++++++- pkg/testutil/nerdtest/third-party.go | 8 ++++++++ pkg/testutil/testutil.go | 18 ------------------ 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/pkg/testutil/nerdtest/requirements.go b/pkg/testutil/nerdtest/requirements.go index 575270a129b..3c365095b03 100644 --- a/pkg/testutil/nerdtest/requirements.go +++ b/pkg/testutil/nerdtest/requirements.go @@ -64,8 +64,13 @@ var OnlyIPv6 = &test.Requirement{ var OnlyKubernetes = &test.Requirement{ Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { helpers.Write(kubernetes, only) + if _, err := exec.LookPath("kubectl"); err != nil { + return false, fmt.Sprintf("kubectl is not in the path: %+v", err) + } ret = environmentHasKubernetes() - if !ret { + if ret { + helpers.Write(Namespace, "k8s.io") + } else { mess = "runner skips Kubernetes compatible tests in the non-Kubernetes environment" } return ret, mess diff --git a/pkg/testutil/nerdtest/third-party.go b/pkg/testutil/nerdtest/third-party.go index 21199f3a815..087ed50ed78 100644 --- a/pkg/testutil/nerdtest/third-party.go +++ b/pkg/testutil/nerdtest/third-party.go @@ -35,6 +35,14 @@ func BuildCtlCommand(helpers test.Helpers, args ...string) test.TestableCommand return cmd } +func KubeCtlCommand(helpers test.Helpers, args ...string) test.TestableCommand { + kubectl, _ := exec.LookPath("kubectl") + cmd := helpers.Custom(kubectl) + cmd.WithArgs("--namespace=nerdctl-test-k8s") + cmd.WithArgs(args...) + return cmd +} + func RegistryWithTokenAuth(data test.Data, helpers test.Helpers, user, pass string, port int, tls bool) (*registry.Server, *registry.TokenAuthServer) { rca := ca.New(data, helpers.T()) as := registry.NewCesantaAuthServer(data, helpers, rca, 0, user, pass, tls) diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index baa0de31e32..da87d67178c 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -762,14 +762,6 @@ func NewBaseWithIPv6Compatible(t *testing.T) *Base { return newBase(t, Namespace, true, false) } -func NewBaseForKubernetes(t *testing.T) *Base { - base := newBase(t, "k8s.io", false, true) - // NOTE: kubectl namespaces are not the same as containerd namespaces. - // We still want kube test objects segregated in their own Kube API namespace. - KubectlHelper(base, "create", "namespace", Namespace).Run() - return base -} - func NewBase(t *testing.T) *Base { return newBase(t, Namespace, false, false) } @@ -844,13 +836,3 @@ func RegisterBuildCacheCleanup(t *testing.T) { NewBase(t).Cmd("builder", "prune", "--all", "--force").Run() }) } - -func KubectlHelper(base *Base, args ...string) *Cmd { - base.T.Helper() - icmdCmd := icmd.Command("kubectl", append([]string{"--namespace", Namespace}, args...)...) - icmdCmd.Env = base.Env - return &Cmd{ - Cmd: icmdCmd, - Base: base, - } -} From 9603bf405ef4bfc0d42b2f3bd15b14a242093c9c Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 15 Oct 2024 01:19:50 -0700 Subject: [PATCH 0855/1066] Registry testing tooling cleanup Signed-off-by: apostasie --- cmd/nerdctl/issues/issues_linux_test.go | 25 ++--- cmd/nerdctl/login/login_linux_test.go | 9 +- .../testregistry/testregistry_linux.go | 97 ------------------- 3 files changed, 18 insertions(+), 113 deletions(-) diff --git a/cmd/nerdctl/issues/issues_linux_test.go b/cmd/nerdctl/issues/issues_linux_test.go index 0a59126fc13..a371aaa6c0f 100644 --- a/cmd/nerdctl/issues/issues_linux_test.go +++ b/cmd/nerdctl/issues/issues_linux_test.go @@ -24,23 +24,24 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest/registry" "github.com/containerd/nerdctl/v2/pkg/testutil/test" - "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) func TestIssue3425(t *testing.T) { nerdtest.Setup() - var registry *testregistry.RegistryServer + var reg *registry.Server testCase := &test.Case{ + Require: nerdtest.Registry, Setup: func(data test.Data, helpers test.Helpers) { - base := testutil.NewBase(t) - registry = testregistry.NewWithNoAuth(base, 0, false) + reg = nerdtest.RegistryWithNoAuth(data, helpers, 0, false) + reg.Setup(data, helpers) }, Cleanup: func(data test.Data, helpers test.Helpers) { - if registry != nil { - registry.Cleanup(nil) + if reg != nil { + reg.Cleanup(data, helpers) } }, SubTests: []*test.Case{ @@ -52,14 +53,14 @@ func TestIssue3425(t *testing.T) { helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage) helpers.Ensure("image", "rm", "-f", testutil.CommonImage) helpers.Ensure("image", "pull", testutil.CommonImage) - helpers.Ensure("tag", testutil.CommonImage, fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + helpers.Ensure("tag", testutil.CommonImage, fmt.Sprintf("localhost:%d/%s", reg.Port, data.Identifier())) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("rmi", "-f", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + helpers.Anyhow("rmi", "-f", fmt.Sprintf("localhost:%d/%s", reg.Port, data.Identifier())) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - return helpers.Command("push", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + return helpers.Command("push", fmt.Sprintf("localhost:%d/%s", reg.Port, data.Identifier())) }, Expected: test.Expects(0, nil, nil), }, @@ -71,14 +72,14 @@ func TestIssue3425(t *testing.T) { helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "touch", "/something") helpers.Ensure("image", "rm", "-f", testutil.CommonImage) helpers.Ensure("image", "pull", testutil.CommonImage) - helpers.Ensure("commit", data.Identifier(), fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + helpers.Ensure("commit", data.Identifier(), fmt.Sprintf("localhost:%d/%s", reg.Port, data.Identifier())) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("rmi", "-f", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + helpers.Anyhow("rmi", "-f", fmt.Sprintf("localhost:%d/%s", reg.Port, data.Identifier())) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - return helpers.Command("push", fmt.Sprintf("localhost:%d/%s", registry.Port, data.Identifier())) + return helpers.Command("push", fmt.Sprintf("localhost:%d/%s", reg.Port, data.Identifier())) }, Expected: test.Expects(0, nil, nil), }, diff --git a/cmd/nerdctl/login/login_linux_test.go b/cmd/nerdctl/login/login_linux_test.go index 0a53a6a623e..2ac21fa374f 100644 --- a/cmd/nerdctl/login/login_linux_test.go +++ b/cmd/nerdctl/login/login_linux_test.go @@ -31,6 +31,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/imgutil/dockerconfigresolver" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" "github.com/containerd/nerdctl/v2/pkg/testutil/testca" "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry" ) @@ -108,8 +109,8 @@ func TestLoginPersistence(t *testing.T) { t.Run(fmt.Sprintf("Server %s", tc.auth), func(t *testing.T) { t.Parallel() - username := testregistry.SafeRandomString(30) + "∞" - password := testregistry.SafeRandomString(30) + ":∞" + username := test.RandomStringBase64(30) + "∞" + password := test.RandomStringBase64(30) + ":∞" // Add the requested authentication var auth testregistry.Auth @@ -297,8 +298,8 @@ func TestLoginAgainstVariants(t *testing.T) { } // Generate credentials that are specific to each registry, so that we never cross hit another one - username := testregistry.SafeRandomString(30) + "∞" - password := testregistry.SafeRandomString(30) + ":∞" + username := test.RandomStringBase64(30) + "∞" + password := test.RandomStringBase64(30) + ":∞" // Get a CA if we want TLS var ca *testca.CA diff --git a/pkg/testutil/testregistry/testregistry_linux.go b/pkg/testutil/testregistry/testregistry_linux.go index 72701d5998d..d6610f9046a 100644 --- a/pkg/testutil/testregistry/testregistry_linux.go +++ b/pkg/testutil/testregistry/testregistry_linux.go @@ -17,8 +17,6 @@ package testregistry import ( - "crypto/rand" - "encoding/base64" "fmt" "net" "os" @@ -249,75 +247,6 @@ func (ba *BasicAuth) Params(base *testutil.Base) []string { return ret } -func NewIPFSRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundCleanup func(error)) *RegistryServer { - EnsureImages(base) - - name := testutil.Identifier(base.T) - // listen on 0.0.0.0 to enable 127.0.0.1 - listenIP := net.ParseIP("0.0.0.0") - hostIP, err := nettestutil.NonLoopbackIPv4() - assert.NilError(base.T, err, fmt.Errorf("failed finding ipv4 non loopback interface: %w", err)) - port, err = portlock.Acquire(port) - assert.NilError(base.T, err, fmt.Errorf("failed acquiring port: %w", err)) - - containerName := fmt.Sprintf("ipfs-registry-%s-%d", name, port) - // Cleanup possible leftovers first - base.Cmd("rm", "-f", containerName).Run() - - args := []string{ - "run", - "--pull=never", - "-d", - "-p", fmt.Sprintf("%s:%d:%d", listenIP, port, port), - "--name", containerName, - "--entrypoint=/bin/sh", - testutil.KuboImage, - "-c", "--", - fmt.Sprintf("ipfs init && ipfs config Addresses.API /ip4/0.0.0.0/tcp/%d && ipfs daemon --offline", port), - } - - cleanup := func(err error) { - result := base.Cmd("rm", "-f", containerName).Run() - errPortRelease := portlock.Release(port) - if boundCleanup != nil { - boundCleanup(err) - } - if err == nil { - assert.NilError(base.T, result.Error, fmt.Errorf("failed removing container: %w", err)) - assert.NilError(base.T, errPortRelease, fmt.Errorf("failed releasing port: %w", err)) - } - } - - scheme := "http" - - err = func() error { - cmd := base.Cmd(args...).Run() - if cmd.Error != nil { - base.T.Logf("%s:\n%s\n%s\n-------\n%s", containerName, cmd.Cmd, cmd.Stdout(), cmd.Stderr()) - return cmd.Error - } - - if _, err = nettestutil.HTTPGet(fmt.Sprintf("%s://%s:%s/api/v0", scheme, hostIP.String(), strconv.Itoa(port)), 30, true); err != nil { - return err - } - - return nil - }() - - assert.NilError(base.T, err, fmt.Errorf("failed starting IPFS registry container in a timely manner: %w", err)) - - return &RegistryServer{ - IP: hostIP, - Port: port, - Scheme: scheme, - ListenIP: listenIP, - Cleanup: cleanup, - Logs: func() { - base.T.Logf("%s: %q", containerName, base.Cmd("logs", containerName).Run().String()) - }, - } -} - func NewRegistry(base *testutil.Base, ca *testca.CA, port int, auth Auth, boundCleanup func(error)) *RegistryServer { EnsureImages(base) @@ -469,29 +398,3 @@ func NewWithNoAuth(base *testutil.Base, port int, tls bool) *RegistryServer { } return NewRegistry(base, ca, port, &NoAuth{}, nil) } - -func NewWithBasicAuth(base *testutil.Base, user, pass string, port int, tls bool) *RegistryServer { - auth := &BasicAuth{ - Username: user, - Password: pass, - } - var ca *testca.CA - if tls { - ca = testca.New(base.T) - } - return NewRegistry(base, ca, port, auth, nil) -} - -func SafeRandomString(n int) string { - b := make([]byte, n) - l, err := rand.Read(b) - if err != nil { - panic(err) - } - if l != n { - panic(fmt.Errorf("expected %d bytes, got %d bytes", n, l)) - } - // XXX WARNING there is something in the registry (or more likely in the way we generate htpasswd files) - // that is broken and does not resist truly random strings - return base64.URLEncoding.EncodeToString(b) -} From 5609de3d48554c6f69184d2bead0f91f55a873ba Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 18 Oct 2024 13:07:42 -0700 Subject: [PATCH 0856/1066] Workaround and document weird docker issue Signed-off-by: apostasie --- cmd/nerdctl/container/container_commit_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cmd/nerdctl/container/container_commit_test.go b/cmd/nerdctl/container/container_commit_test.go index 9382a782d7a..144180f79c2 100644 --- a/cmd/nerdctl/container/container_commit_test.go +++ b/cmd/nerdctl/container/container_commit_test.go @@ -36,6 +36,12 @@ func TestCommit(t *testing.T) { helpers.Anyhow("rmi", "-f", data.Identifier()) }, Setup: func(data test.Data, helpers test.Helpers) { + // FIXME: short of pulling first, docker will fail to start the container. + // Debugging shows container exited immediately. Nothing in the container logs. Not much in journalctl. + // It is not clear what is happening. + if nerdtest.IsDocker() { + helpers.Ensure("pull", testutil.CommonImage) + } helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") nerdtest.EnsureContainerStarted(helpers, data.Identifier()) helpers.Ensure("exec", data.Identifier(), "sh", "-euxc", `echo hello-test-commit > /foo`) @@ -59,6 +65,10 @@ func TestCommit(t *testing.T) { helpers.Anyhow("rmi", "-f", data.Identifier()) }, Setup: func(data test.Data, helpers test.Helpers) { + // See note above about docker failing. + if nerdtest.IsDocker() { + helpers.Ensure("pull", testutil.CommonImage) + } helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") nerdtest.EnsureContainerStarted(helpers, data.Identifier()) helpers.Ensure("exec", data.Identifier(), "sh", "-euxc", `echo hello-test-commit > /foo`) From 0cc9d29147213eb27e1f88043d27486d1ad11fb8 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 18 Oct 2024 13:09:33 -0700 Subject: [PATCH 0857/1066] Enhance debugability for kubernetes rig Signed-off-by: apostasie --- hack/build-integration-kubernetes.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hack/build-integration-kubernetes.sh b/hack/build-integration-kubernetes.sh index e41f13fcf7f..5647e4dd4f8 100755 --- a/hack/build-integration-kubernetes.sh +++ b/hack/build-integration-kubernetes.sh @@ -104,8 +104,9 @@ main(){ # 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 run -d --quiet --name go-kind golang:"$GO_VERSION" sleep Inf exec::nerdctl cp go-kind:/usr/local/go /tmp/go + exec::nerdctl rm -f go-kind # Create fresh cluster log::info "Creating new cluster" From 564ff06e2b8a8d4e180618d60ce6f9b1537d54b3 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 18 Oct 2024 13:03:32 -0700 Subject: [PATCH 0858/1066] Separate lint + enable on other platforms Signed-off-by: apostasie --- .github/workflows/lint.yml | 79 +++++++++++++++++++++++++++++++ .github/workflows/test-canary.yml | 21 -------- .github/workflows/test.yml | 26 ---------- 3 files changed, 79 insertions(+), 47 deletions(-) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000000..57051520299 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,79 @@ +name: lint + +on: + push: + branches: + - main + - 'release/**' + pull_request: + +env: + GO_VERSION: 1.23.x + +jobs: + go: + timeout-minutes: 5 + name: "go | ${{ matrix.goos }} | ${{ matrix.canary }}" + runs-on: "${{ matrix.os }}" + defaults: + run: + shell: bash + strategy: + matrix: + include: + - os: ubuntu-24.04 + goos: linux + - os: ubuntu-24.04 + goos: freebsd + # FIXME: this is currently failing in a non-sensical way, so, running on linux instead... + # - os: windows-2022 + - os: ubuntu-24.04 + goos: windows + - os: ubuntu-24.04 + goos: linux + # This allows the canary script to select any upcoming golang alpha/beta/RC + canary: go-canary + env: + GOOS: "${{ matrix.goos }}" + steps: + - uses: actions/checkout@v4.2.1 + with: + fetch-depth: 1 + - name: Set GO env + run: | + # If canary is specified, get the latest available golang pre-release instead of the major version + if [ "$canary" != "" ]; then + . ./hack/build-integration-canary.sh + canary::golang::latest + fi + - uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + check-latest: true + cache: true + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + args: --verbose + + other: + timeout-minutes: 5 + name: yaml | shell | imports order + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4.2.1 + with: + fetch-depth: 1 + - uses: actions/setup-go@v5 + with: + go-version: ${{ env.GO_VERSION }} + check-latest: true + cache: true + - name: yaml + run: make lint-yaml + - name: shell + run: make lint-shell + - name: go imports ordering + run: | + go install -v github.com/incu6us/goimports-reviser/v3@latest + make lint-imports diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index dc07fe92de7..14dbb5e1455 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -15,27 +15,6 @@ env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: - lint: - runs-on: "ubuntu-24.04" - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4.2.1 - with: - fetch-depth: 1 - - name: Set GO env - run: | - . ./hack/build-integration-canary.sh - canary::golang::latest - - uses: actions/setup-go@v5 - with: - go-version: ${{ env.GO_VERSION }} - check-latest: true - cache: true - - name: golangci-lint - uses: golangci/golangci-lint-action@v6.1.1 - with: - args: --verbose - linux: runs-on: "ubuntu-24.04" timeout-minutes: 40 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7c56fd5acbe..5eff7064fa9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,32 +13,6 @@ env: GO_VERSION: 1.23.x jobs: - lint: - runs-on: ubuntu-24.04 - timeout-minutes: 20 - steps: - - uses: actions/checkout@v4.2.1 - with: - fetch-depth: 1 - - uses: actions/setup-go@v5 - with: - go-version: ${{ env.GO_VERSION }} - check-latest: true - cache: true - - name: golangci-lint - uses: golangci/golangci-lint-action@v6.1.1 - with: - version: v1.60.1 - args: --verbose - - name: yamllint-lint - run: make lint-yaml - - name: shellcheck - run: make lint-shell - - name: go imports ordering - run: | - go install -v github.com/incu6us/goimports-reviser/v3@latest - make lint-imports - test-unit: timeout-minutes: 5 name: unit | ${{ matrix.goos }} From d963545ad6516c4be2535c29ad8661e06cc28ff1 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 18 Oct 2024 13:06:45 -0700 Subject: [PATCH 0859/1066] Fix ensurecontainerstarted logic and better debug Signed-off-by: apostasie --- docs/testing/tools.md | 4 +- pkg/testutil/nerdtest/registry/cesanta.go | 58 ++++++++++++----------- pkg/testutil/nerdtest/utilities.go | 46 ++++++++++-------- pkg/testutil/test/command.go | 8 +++- pkg/testutil/test/helpers.go | 2 +- 5 files changed, 69 insertions(+), 49 deletions(-) diff --git a/docs/testing/tools.md b/docs/testing/tools.md index d1f64cd4c80..2f53441b30c 100644 --- a/docs/testing/tools.md +++ b/docs/testing/tools.md @@ -48,7 +48,9 @@ You already saw two (`test.Expects` and `test.Contains`): First, `test.Expects(exitCode int, errors []error, outputCompare Comparator)`, which is convenient to quickly describe what you expect overall. -`exitCode` is obvious (note that passing -1 as an exit code will just verify the commands does fail without comparing the code). +`exitCode` is obvious (note that passing -1 as an exit code will just +verify the commands does fail without comparing the code, and -2 will not verify the exit +code at all). `errors` is a slice of go `error`, that allows you to compare what is seen on stderr with existing errors (for example: `errdefs.ErrNotFound`), or more generally diff --git a/pkg/testutil/nerdtest/registry/cesanta.go b/pkg/testutil/nerdtest/registry/cesanta.go index b8924e8c369..cf074542c35 100644 --- a/pkg/testutil/nerdtest/registry/cesanta.go +++ b/pkg/testutil/nerdtest/registry/cesanta.go @@ -82,34 +82,38 @@ func (cc *CesantaConfig) Save(path string) error { return err } +// FIXME: this is a copy of the utility method EnsureContainerStarted +// We cannot reference it (circular dep), so the copy. +// To be fixed later when we will be done migrating test helpers to the new framework and we can split them +// in meaningful subpackages. + func ensureContainerStarted(helpers test.Helpers, con string) { - const maxRetry = 5 - const sleep = time.Second - success := false - for i := 0; i < maxRetry && !success; i++ { - time.Sleep(sleep) - count := i - cmd := helpers.Command("container", "inspect", con) - cmd.Run(&test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var dc []dockercompat.Container - err := json.Unmarshal([]byte(stdout), &dc) - assert.NilError(t, err, "Unable to unmarshal output\n"+info) - assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) - if dc[0].State.Running { - success = true - return - } - if count == maxRetry-1 { - // FIXME: there is currently no simple way to capture stderr - // Sometimes, it is convenient for debugging, like here - // Here we cheat with unbuffer which will bundle stderr and stdout together - // This is just bad - t.Error(helpers.Err("logs", con)) - t.Fatalf("container %s still not running after %d retries", con, count) - } - }, - }) + started := false + for i := 0; i < 5 && !started; i++ { + helpers.Command("container", "inspect", con). + Run(&test.Expected{ + ExitCode: test.ExitCodeNoCheck, + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Container + err := json.Unmarshal([]byte(stdout), &dc) + if err != nil || len(dc) == 0 { + return + } + assert.Equal(t, len(dc), 1, "Unexpectedly got multiple results\n"+info) + started = dc[0].State.Running + }, + }) + time.Sleep(time.Second) + } + + if !started { + ins := helpers.Capture("container", "inspect", con) + lgs := helpers.Capture("logs", con) + ps := helpers.Capture("ps", "-a") + helpers.T().Log(ins) + helpers.T().Log(lgs) + helpers.T().Log(ps) + helpers.T().Fatalf("container %s still not running after %d retries", con, 5) } } diff --git a/pkg/testutil/nerdtest/utilities.go b/pkg/testutil/nerdtest/utilities.go index 384f5132110..f23ce2b2c9a 100644 --- a/pkg/testutil/nerdtest/utilities.go +++ b/pkg/testutil/nerdtest/utilities.go @@ -87,28 +87,36 @@ func InspectImage(helpers test.Helpers, name string) dockercompat.Image { } const ( - maxRetry = 5 + maxRetry = 10 sleep = time.Second ) func EnsureContainerStarted(helpers test.Helpers, con string) { - for i := 0; i < maxRetry; i++ { - count := i - cmd := helpers.Command("container", "inspect", con) - cmd.Run(&test.Expected{ - Output: func(stdout string, info string, t *testing.T) { - var dc []dockercompat.Container - err := json.Unmarshal([]byte(stdout), &dc) - assert.NilError(t, err, "Unable to unmarshal output\n"+info) - assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) - if dc[0].State.Running { - return - } - if count == maxRetry-1 { - t.Fatalf("container %s still not running after %d retries", con, count) - } - time.Sleep(sleep) - }, - }) + started := false + for i := 0; i < maxRetry && !started; i++ { + helpers.Command("container", "inspect", con). + Run(&test.Expected{ + ExitCode: test.ExitCodeNoCheck, + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Container + err := json.Unmarshal([]byte(stdout), &dc) + if err != nil || len(dc) == 0 { + return + } + assert.Equal(t, len(dc), 1, "Unexpectedly got multiple results\n"+info) + started = dc[0].State.Running + }, + }) + time.Sleep(sleep) + } + + if !started { + ins := helpers.Capture("container", "inspect", con) + lgs := helpers.Capture("logs", con) + ps := helpers.Capture("ps", "-a") + helpers.T().Log(ins) + helpers.T().Log(lgs) + helpers.T().Log(ps) + helpers.T().Fatalf("container %s still not running after %d retries", con, maxRetry) } } diff --git a/pkg/testutil/test/command.go b/pkg/testutil/test/command.go index a5b1de747d0..5f072e647a8 100644 --- a/pkg/testutil/test/command.go +++ b/pkg/testutil/test/command.go @@ -28,6 +28,9 @@ import ( "gotest.tools/v3/icmd" ) +const ExitCodeGenericFail = -1 +const ExitCodeNoCheck = -2 + // GenericCommand is a concrete Command implementation type GenericCommand struct { Config Config @@ -117,7 +120,10 @@ func (gc *GenericCommand) Run(expect *Expected) { // Build the debug string - additionally attach the env (which iCmd does not do) debug := result.String() + "Env:\n" + strings.Join(env, "\n") // ExitCode goes first - if expect.ExitCode == -1 { + if expect.ExitCode == ExitCodeNoCheck { //nolint:revive + // -2 means we do not care at all about exit code + } else if expect.ExitCode == ExitCodeGenericFail { + // -1 means any error assert.Assert(gc.t, result.ExitCode != 0, "Expected exit code to be different than 0\n"+debug) } else { diff --git a/pkg/testutil/test/helpers.go b/pkg/testutil/test/helpers.go index 06411df8e99..9247f4098e8 100644 --- a/pkg/testutil/test/helpers.go +++ b/pkg/testutil/test/helpers.go @@ -70,7 +70,7 @@ func (help *helpersInternal) Anyhow(args ...string) { // Fail will run a command and make sure it does fail func (help *helpersInternal) Fail(args ...string) { help.Command(args...).Run(&Expected{ - ExitCode: -1, + ExitCode: ExitCodeGenericFail, }) } From e1622152cf62f7759b655cc5b3f55a4c61bb374f Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 18 Oct 2024 13:07:12 -0700 Subject: [PATCH 0860/1066] Add legacy tests into the 'retry' bucket Signed-off-by: apostasie --- pkg/testutil/testutil.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/testutil/testutil.go b/pkg/testutil/testutil.go index da87d67178c..525225fb996 100644 --- a/pkg/testutil/testutil.go +++ b/pkg/testutil/testutil.go @@ -787,6 +787,9 @@ func newBase(t *testing.T, ns string, ipv6Compatible bool, kubernetesCompatible } else if !base.EnableKubernetes && base.KubernetesCompatible { t.Skip("runner skips Kubernetes compatible tests in the non-Kubernetes environment") } + if !GetFlakyEnvironment() && !GetEnableKubernetes() && !GetEnableIPv6() { + t.Skip("legacy tests are considered flaky by default and are skipped unless in the flaky environment") + } var err error switch base.Target { case Nerdctl: From c3627e11bc9eba4d4c38eb5dda3733f49f739f3b Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Tue, 8 Oct 2024 23:30:01 +0900 Subject: [PATCH 0861/1066] fix: Allow to delete images when names of images are short digest ids of another images. "nerdctl rmi " can be run to delete the target images. However, at the current implementation, the deletion fails when images names are the short digest ids of another images. The specific behavior is described below, which is how it works in the current implementation. First, suppose there are alpine and busybox images. ``` > nerdctl images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE busybox latest 768e5c6f5cb6 3 seconds ago linux/arm64 4.092MB 1.845MB alpine latest beefdbd8a1da 11 seconds ago linux/arm64 10.46MB 4.09MB ``` Then, we tag the alpine image using digest id of the busybox image. ``` > nerdctl tag alpine $(dn inspect busybox | jq -rc .[0].RepoDigests[0] | awk -F':' '{print substr($2, 1, 8)}') > nerdctl images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE 768e5c6f latest beefdbd8a1da 4 seconds ago linux/arm64 10.46MB 4.09MB busybox latest 768e5c6f5cb6 22 hours ago linux/arm64 4.092MB 1.845MB alpine latest beefdbd8a1da 22 hours ago linux/arm64 10.46MB 4.09MB ``` In this situation, running 'nerdctl rmi "$(dn inspect busybox | jq -rc .[0].RepoDigests[0] | awk -F':' '{print substr($2, 1, 8)}')"' will fail to remove the image. The details of the error are as follows. ``` > nerdctl rmi "$(dn inspect busybox | jq -rc .[0].RepoDigests[0] | awk -F':' '{print substr($2, 1, 8)}')" FATA[0000] 1 errors: multiple IDs found with provided prefix: 768e5c6f ``` This issue is reported in the following issue. - https://github.com/containerd/nerdctl/issues/3016 Therefore, this pull request modifies this so that images can be deleted with "nerdctl rmi " when images names are the short digest ids of another images. Signed-off-by: Hayato Kiwata --- cmd/nerdctl/image/image_remove_test.go | 49 ++++++++++++++++++++++++++ pkg/cmd/image/remove.go | 15 +++++--- pkg/idutil/imagewalker/imagewalker.go | 37 ++++++++++++------- 3 files changed, 84 insertions(+), 17 deletions(-) diff --git a/cmd/nerdctl/image/image_remove_test.go b/cmd/nerdctl/image/image_remove_test.go index 85b665f350f..5e48372332c 100644 --- a/cmd/nerdctl/image/image_remove_test.go +++ b/cmd/nerdctl/image/image_remove_test.go @@ -18,8 +18,11 @@ package image import ( "errors" + "strings" "testing" + "gotest.tools/v3/assert" + "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" @@ -302,3 +305,49 @@ func TestRemove(t *testing.T) { testCase.Run(t) } + +// TestIssue3016 tests https://github.com/containerd/nerdctl/issues/3016 +func TestIssue3016(t *testing.T) { + testCase := nerdtest.Setup() + + const ( + tagIDKey = "tagID" + ) + + testCase.SubTests = []*test.Case{ + { + Description: "Issue #3016 - Tags created using the short digest ids of container images cannot be deleted using the nerdctl rmi command.", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.CommonImage) + helpers.Ensure("pull", testutil.NginxAlpineImage) + + img := nerdtest.InspectImage(helpers, testutil.NginxAlpineImage) + repoName, _ := imgutil.ParseRepoTag(testutil.NginxAlpineImage) + tagID := strings.TrimPrefix(img.RepoDigests[0], repoName+"@sha256:")[0:8] + + helpers.Ensure("tag", testutil.CommonImage, tagID) + + data.Set(tagIDKey, tagID) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("rmi", data.Get(tagIDKey)) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Errors: []error{}, + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("images", data.Get(tagIDKey)).Run(&test.Expected{ + ExitCode: 0, + Output: func(stdout string, info string, t *testing.T) { + assert.Equal(t, len(strings.Split(stdout, "\n")), 2) + }, + }) + }, + } + }, + }, + } + + testCase.Run(t) +} diff --git a/pkg/cmd/image/remove.go b/pkg/cmd/image/remove.go index 09d76b90e69..3afa2bff80b 100644 --- a/pkg/cmd/image/remove.go +++ b/pkg/cmd/image/remove.go @@ -65,11 +65,18 @@ func Remove(ctx context.Context, client *containerd.Client, args []string, optio walker := &imagewalker.ImageWalker{ Client: client, OnFound: func(ctx context.Context, found imagewalker.Found) error { - // if found multiple images, return error unless in force-mode and - // there is only 1 unique image. - if found.MatchCount > 1 && !(options.Force && found.UniqueImages == 1) { - return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + if found.NameMatchIndex == -1 { + // if found multiple images, return error unless in force-mode and + // there is only 1 unique image. + if found.MatchCount > 1 && !(options.Force && found.UniqueImages == 1) { + return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + } + } else if found.NameMatchIndex != found.MatchIndex { + // when there is an image with a name matching the argument but the argument is a digest short id, + // the deletion process is not performed. + return nil } + if cid, ok := runningImages[found.Image.Name]; ok { return fmt.Errorf("conflict: unable to delete %s (cannot be forced) - image is being used by running container %s", found.Req, cid) } diff --git a/pkg/idutil/imagewalker/imagewalker.go b/pkg/idutil/imagewalker/imagewalker.go index df948a48f01..4103711ed91 100644 --- a/pkg/idutil/imagewalker/imagewalker.go +++ b/pkg/idutil/imagewalker/imagewalker.go @@ -31,11 +31,12 @@ import ( ) type Found struct { - Image images.Image - Req string // The raw request string. name, short ID, or long ID. - MatchIndex int // Begins with 0, up to MatchCount - 1. - MatchCount int // 1 on exact match. > 1 on ambiguous match. Never be <= 0. - UniqueImages int // Number of unique images in all found images. + Image images.Image + Req string // The raw request string. name, short ID, or long ID. + MatchIndex int // Begins with 0, up to MatchCount - 1. + MatchCount int // 1 on exact match. > 1 on ambiguous match. Never be <= 0. + UniqueImages int // Number of unique images in all found images. + NameMatchIndex int // Image index with a name matching the argument for `nerdctl rmi`. } type OnFound func(ctx context.Context, found Found) error @@ -50,8 +51,12 @@ type ImageWalker struct { // Returns the number of the found entries. func (w *ImageWalker) Walk(ctx context.Context, req string) (int, error) { var filters []string - if parsedReference, err := referenceutil.Parse(req); err == nil { - filters = append(filters, fmt.Sprintf("name==%s", parsedReference.String())) + var parsedReferenceStr string + + parsedReference, err := referenceutil.Parse(req) + if err == nil { + parsedReferenceStr = parsedReference.String() + filters = append(filters, fmt.Sprintf("name==%s", parsedReferenceStr)) } filters = append(filters, fmt.Sprintf("name==%s", req), @@ -68,17 +73,23 @@ func (w *ImageWalker) Walk(ctx context.Context, req string) (int, error) { // to handle the `rmi -f` case where returned images are different but // have the same short prefix. uniqueImages := make(map[digest.Digest]bool) - for _, image := range images { + nameMatchIndex := -1 + for i, image := range images { uniqueImages[image.Target.Digest] = true + // to get target image index for `nerdctl rmi `. + if (parsedReferenceStr != "" && image.Name == parsedReferenceStr) || image.Name == req { + nameMatchIndex = i + } } for i, img := range images { f := Found{ - Image: img, - Req: req, - MatchIndex: i, - MatchCount: matchCount, - UniqueImages: len(uniqueImages), + Image: img, + Req: req, + MatchIndex: i, + MatchCount: matchCount, + UniqueImages: len(uniqueImages), + NameMatchIndex: nameMatchIndex, } if e := w.OnFound(ctx, f); e != nil { return -1, e From 4f20a14d693ad07f626071e7e50322dc7a779f67 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 18 Oct 2024 13:11:29 -0700 Subject: [PATCH 0862/1066] CI: enable no-retry/retry testing separation and workflows cleanup Signed-off-by: apostasie --- .../ghcr-image-build-and-publish.yml | 3 +- .github/workflows/lint.yml | 1 - .github/workflows/project.yml | 2 +- .github/workflows/test-canary.yml | 12 ++- .github/workflows/test-kube.yml | 5 +- .github/workflows/test.yml | 98 +++++++++---------- Dockerfile | 14 +-- Makefile | 3 + hack/test-integration.sh | 49 ++++++++++ 9 files changed, 113 insertions(+), 74 deletions(-) create mode 100755 hack/test-integration.sh diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index ebb35de53cb..bd7941780a2 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -1,4 +1,4 @@ -name: Container Image Build +name: image # This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by @@ -21,7 +21,6 @@ env: # github.repository as / IMAGE_NAME: ${{ github.repository }} - jobs: build: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 57051520299..be29a8c2aec 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -55,7 +55,6 @@ jobs: uses: golangci/golangci-lint-action@v6 with: args: --verbose - other: timeout-minutes: 5 name: yaml | shell | imports order diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml index a03da712e02..6961f0fd565 100644 --- a/.github/workflows/project.yml +++ b/.github/workflows/project.yml @@ -9,7 +9,7 @@ on: jobs: project: - name: Project Checks + name: checks runs-on: ubuntu-24.04 timeout-minutes: 20 steps: diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 14dbb5e1455..7c9226f45f8 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -44,11 +44,13 @@ jobs: - name: "Run unit tests" run: go test -v ./pkg/... - name: "Run integration tests" - run: docker run -t --rm --privileged test-integration + run: docker run -t --rm --privileged test-integration ./hack/test-integration.sh -test.only-flaky=false + - name: "Run integration tests (flaky)" + run: docker run -t --rm --privileged test-integration ./hack/test-integration.sh -test.only-flaky=true windows: - runs-on: windows-latest timeout-minutes: 30 + runs-on: windows-latest defaults: run: shell: bash @@ -74,6 +76,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl + - run: go install -v gotest.tools/gotestsum@v1 # This here is solely to get the cni install script, which has not been modified in 3+ years. # There is little to no reason to update this to latest containerd - uses: actions/checkout@v4.2.1 @@ -91,5 +94,6 @@ jobs: ctrdVersion: ${{ env.CONTAINERD_VERSION }} run: powershell hack/configure-windows-ci.ps1 - name: "Run integration tests" - # See https://github.com/containerd/nerdctl/blob/main/docs/testing/README.md#about-parallelization - run: go test -p 1 -v ./cmd/nerdctl/... + run: ./hack/test-integration.sh -test.only-flaky=false + - name: "Run integration tests (flaky)" + run: ./hack/test-integration.sh -test.only-flaky=true diff --git a/.github/workflows/test-kube.yml b/.github/workflows/test-kube.yml index c8e2ccda405..3c6faaaa457 100644 --- a/.github/workflows/test-kube.yml +++ b/.github/workflows/test-kube.yml @@ -10,13 +10,12 @@ on: paths-ignore: - '**.md' -env: - ROOTFUL: true - jobs: linux: runs-on: "ubuntu-24.04" timeout-minutes: 40 + env: + ROOTFUL: true steps: - uses: actions/checkout@v4.2.1 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5eff7064fa9..863b956938c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,9 +11,14 @@ on: env: GO_VERSION: 1.23.x + SHORT_TIMEOUT: 5 + LONG_TIMEOUT: 60 jobs: test-unit: + # Supposed to work: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#example-returning-a-json-data-type + # Apparently does not + # timeout-minutes: ${{ fromJSON(env.SHORT_TIMEOUT) }} timeout-minutes: 5 name: unit | ${{ matrix.goos }} runs-on: "${{ matrix.os }}" @@ -48,11 +53,12 @@ jobs: working-directory: containerd run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Run unit tests" - run: go test -v ./pkg/... + run: make test-unit test-integration: + timeout-minutes: 60 + name: rootful | ${{ matrix.containerd }} | ${{ matrix.runner }} runs-on: "${{ matrix.runner }}" - timeout-minutes: 40 strategy: fail-fast: false matrix: @@ -95,23 +101,21 @@ jobs: docker run --privileged --rm tonistiigi/binfmt --install linux/arm64 docker run --privileged --rm tonistiigi/binfmt --install linux/arm/v7 - name: "Run integration tests" - uses: nick-fields/retry@v3 - with: - timeout_minutes: 30 - max_attempts: 2 - retry_on: error - command: docker run -t --rm --privileged test-integration + run: docker run -t --rm --privileged test-integration ./hack/test-integration.sh -test.only-flaky=false + - name: "Run integration tests (flaky)" + run: docker run -t --rm --privileged test-integration ./hack/test-integration.sh -test.only-flaky=true test-integration-ipv6: + timeout-minutes: 60 + name: ipv6 | ${{ matrix.containerd }} | ${{ matrix.ubuntu }} runs-on: "ubuntu-${{ matrix.ubuntu }}" - timeout-minutes: 40 strategy: fail-fast: false matrix: # ubuntu-20.04: cgroup v1, ubuntu-22.04 and later: cgroup v2 include: - ubuntu: 24.04 - containerd: v1.7.23 + containerd: v2.0.0-rc.5 env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -129,7 +133,7 @@ jobs: echo '{"ipv6": true, "fixed-cidr-v6": "2001:db8:1::/64", "experimental": true, "ip6tables": true}' | sudo tee /etc/docker/daemon.json sudo systemctl restart docker - name: "Prepare integration test environment" - run: docker build -t test-integration-ipv6 --target test-integration-ipv6 --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . + run: docker build -t test-integration --target test-integration --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . - name: "Remove snap loopback devices (conflicts with our loopback devices in TestRunDevice)" run: | sudo systemctl disable --now snapd.service snapd.socket @@ -147,20 +151,16 @@ jobs: docker run --privileged --rm tonistiigi/binfmt --install linux/arm/v7 - name: "Run integration tests" # The nested IPv6 network inside docker and qemu is complex and needs a bunch of sysctl config. - # Therefore it's hard to debug why the IPv6 tests fail in such an isolation layer. + # Therefore, it's hard to debug why the IPv6 tests fail in such an isolation layer. # On the other side, using the host network is easier at configuration. # Besides, each job is running on a different instance, which means using host network here # is safe and has no side effects on others. - uses: nick-fields/retry@v3 - with: - timeout_minutes: 30 - max_attempts: 2 - retry_on: error - command: docker run --network host -t --rm --privileged test-integration-ipv6 + run: docker run --network host -t --rm --privileged test-integration ./hack/test-integration.sh -test.only-ipv6 test-integration-rootless: - runs-on: "ubuntu-${{ matrix.ubuntu }}" timeout-minutes: 60 + name: "${{ matrix.target }} | ${{ matrix.containerd }} | ${{ matrix.rootlesskit }} | ${{ matrix.ubuntu }}" + runs-on: "ubuntu-${{ matrix.ubuntu }}" strategy: fail-fast: false matrix: @@ -169,24 +169,24 @@ jobs: - ubuntu: 20.04 containerd: v1.6.36 rootlesskit: v1.1.1 # Deprecated - target: test-integration-rootless + target: rootless - ubuntu: 22.04 containerd: v1.7.23 rootlesskit: v2.3.1 - target: test-integration-rootless + target: rootless - ubuntu: 24.04 containerd: v2.0.0-rc.5 rootlesskit: v2.3.1 - target: test-integration-rootless + target: rootless - ubuntu: 24.04 containerd: v1.7.23 rootlesskit: v2.3.1 - target: test-integration-rootless-port-slirp4netns + target: rootless-port-slirp4netns env: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" - TEST_TARGET: "${{ matrix.target }}" + TEST_TARGET: "test-integration-${{ matrix.target }}" steps: - name: "Set up AppArmor" if: matrix.ubuntu == '24.04' @@ -226,16 +226,14 @@ jobs: fi echo "WORKAROUND_ISSUE_622=${WORKAROUND_ISSUE_622}" >> "$GITHUB_ENV" - name: "Test (network driver=slirp4netns, port driver=builtin)" - uses: nick-fields/retry@v3 - with: - timeout_minutes: 30 - max_attempts: 2 - retry_on: error - command: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=${WORKAROUND_ISSUE_622} ${TEST_TARGET} + run: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=${WORKAROUND_ISSUE_622} ${TEST_TARGET} /test-integration-rootless.sh ./hack/test-integration.sh -test.only-flaky=false + - name: "Test (network driver=slirp4netns, port driver=builtin) (flaky)" + run: docker run -t --rm --privileged -e WORKAROUND_ISSUE_622=${WORKAROUND_ISSUE_622} ${TEST_TARGET} /test-integration-rootless.sh ./hack/test-integration.sh -test.only-flaky=true - cross: + build: + timeout-minutes: 5 + name: "build | ${{ matrix.go-version }}" runs-on: ubuntu-24.04 - timeout-minutes: 40 strategy: matrix: go-version: ["1.22.x", "1.23.x"] @@ -248,12 +246,13 @@ jobs: go-version: ${{ matrix.go-version }} cache: true check-latest: true - - name: "Cross" + - name: "build" run: GO_VERSION="$(echo ${{ matrix.go-version }} | sed -e s/.x//)" make binaries test-integration-docker-compatibility: + timeout-minutes: 60 + name: docker runs-on: ubuntu-24.04 - timeout-minutes: 45 steps: - uses: actions/checkout@v4.2.1 with: @@ -280,26 +279,18 @@ jobs: - name: "Prepare integration test environment" run: | sudo apt-get install -y expect + go install -v gotest.tools/gotestsum@v1 - name: "Ensure that the integration test suite is compatible with Docker" - uses: nick-fields/retry@v3 - with: - timeout_minutes: 30 - max_attempts: 2 - retry_on: error - # See https://github.com/containerd/nerdctl/blob/main/docs/testing/README.md#about-parallelization - command: go test -p 1 -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon + run: WITH_SUDO=true ./hack/test-integration.sh -test.target=docker - name: "Ensure that the IPv6 integration test suite is compatible with Docker" - uses: nick-fields/retry@v3 - with: - timeout_minutes: 30 - max_attempts: 2 - retry_on: error - # See https://github.com/containerd/nerdctl/blob/main/docs/testing/README.md#about-parallelization - command: go test -p 1 -timeout 20m -v -exec sudo ./cmd/nerdctl/... -args -test.target=docker -test.allow-kill-daemon -test.only-ipv6 + run: WITH_SUDO=true ./hack/test-integration.sh -test.target=docker -test.only-ipv6 + - name: "Ensure that the integration test suite is compatible with Docker (flaky only)" + run: WITH_SUDO=true ./hack/test-integration.sh -test.target=docker -test.only-flaky test-integration-windows: - runs-on: windows-2022 timeout-minutes: 30 + name: windows + runs-on: windows-2022 defaults: run: shell: bash @@ -313,6 +304,7 @@ jobs: cache: true check-latest: true - run: go install ./cmd/nerdctl + - run: go install -v gotest.tools/gotestsum@v1 - uses: actions/checkout@v4.2.1 with: repository: containerd/containerd @@ -326,16 +318,16 @@ jobs: env: ctrdVersion: 1.7.23 run: powershell hack/configure-windows-ci.ps1 - # TODO: Run unit tests - name: "Run integration tests" - # See https://github.com/containerd/nerdctl/blob/main/docs/testing/README.md#about-parallelization - run: go test -p 1 -v ./cmd/nerdctl/... + run: ./hack/test-integration.sh -test.only-flaky=false + - name: "Run integration tests (flaky)" + run: ./hack/test-integration.sh -test.only-flaky=true test-integration-freebsd: + timeout-minutes: 60 name: FreeBSD # ubuntu-24.04 lacks the vagrant package runs-on: ubuntu-22.04 - timeout-minutes: 20 steps: - uses: actions/checkout@v4.2.1 diff --git a/Dockerfile b/Dockerfile index a594358aee4..f1e32fd4153 100644 --- a/Dockerfile +++ b/Dockerfile @@ -276,7 +276,8 @@ ARG DEBIAN_FRONTEND=noninteractive # `expect` package contains `unbuffer(1)`, which is used for emulating TTY for testing RUN apt-get update -qq && apt-get install -qq --no-install-recommends \ expect \ - git + git \ + make COPY --from=goversion /GOVERSION /GOVERSION ARG TARGETARCH RUN curl -fsSL --proto '=https' --tlsv1.2 https://golang.org/dl/$(cat /GOVERSION).linux-${TARGETARCH:-amd64}.tar.gz | tar xzvC /usr/local @@ -314,8 +315,7 @@ RUN curl -o nydus-static.tgz -fsSL --proto '=https' --tlsv1.2 "https://github.co tar xzf nydus-static.tgz && \ mv nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/bin/ && \ rm nydus-static.tgz -CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=./cmd/nerdctl/...", \ - "--", "-timeout=60m", "-p", "1", "-args", "-test.allow-kill-daemon"] +CMD ["./hack/test-integration.sh"] FROM test-integration AS test-integration-rootless # Install SSH for creating systemd user session. @@ -338,17 +338,11 @@ RUN systemctl disable test-integration-ipfs-offline VOLUME /home/rootless/.local/share COPY ./Dockerfile.d/test-integration-rootless.sh / RUN chmod a+rx /test-integration-rootless.sh -CMD ["/test-integration-rootless.sh", \ - "gotestsum", "--format=testname", "--rerun-fails=2", "--packages=./cmd/nerdctl/...", \ - "--", "-timeout=60m", "-p", "1", "-args", "-test.allow-kill-daemon"] +CMD ["/test-integration-rootless.sh", "./hack/test-integration.sh"] # test for CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=slirp4netns FROM test-integration-rootless AS test-integration-rootless-port-slirp4netns COPY ./Dockerfile.d/home_rootless_.config_systemd_user_containerd.service.d_port-slirp4netns.conf /home/rootless/.config/systemd/user/containerd.service.d/port-slirp4netns.conf RUN chown -R rootless:rootless /home/rootless/.config -FROM test-integration AS test-integration-ipv6 -CMD ["gotestsum", "--format=testname", "--rerun-fails=2", "--packages=./cmd/nerdctl/...", \ - "--", "-timeout=60m", "-p", "1", "-args", "-test.allow-kill-daemon", "-test.only-ipv6"] - FROM base AS demo diff --git a/Makefile b/Makefile index 0831c640047..ae4e18c94f3 100644 --- a/Makefile +++ b/Makefile @@ -86,6 +86,9 @@ lint-yaml: lint-shell: $(call recursive_wildcard,$(MAKEFILE_DIR)/,*.sh) shellcheck -a -x $^ +test-unit: + go test -v $(MAKEFILE_DIR)/pkg/... + binaries: nerdctl install: diff --git a/hack/test-integration.sh b/hack/test-integration.sh new file mode 100755 index 00000000000..73e2b4ebb19 --- /dev/null +++ b/hack/test-integration.sh @@ -0,0 +1,49 @@ +#!/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 + +readonly timeout="60m" +readonly retries="2" +readonly needsudo="${WITH_SUDO:-}" + +# See https://github.com/containerd/nerdctl/blob/main/docs/testing/README.md#about-parallelization +args=(--format=testname --jsonfile /tmp/test-integration.log --packages="$root"/../cmd/nerdctl/...) + +if [ "$#" == 0 ]; then + "$root"/test-integration.sh -test.only-flaky=false + "$root"/test-integration.sh -test.only-flaky=true + exit +fi + +for arg in "$@"; do + if [ "$arg" == "-test.only-flaky=true" ] || [ "$arg" == "-test.only-flaky" ]; then + args+=("--rerun-fails=$retries") + break + fi +done + +if [ "$needsudo" == "true" ] || [ "$needsudo" == "yes" ] || [ "$needsudo" == "1" ]; then + gotestsum "${args[@]}" -- -timeout="$timeout" -p 1 -exec sudo -args -test.allow-kill-daemon "$@" +else + gotestsum "${args[@]}" -- -timeout="$timeout" -p 1 -args -test.allow-kill-daemon "$@" +fi + +echo "These are the tests that took more than 10 seconds:" +gotestsum tool slowest --threshold 10s --jsonfile /tmp/test-integration.log From ec12b584da3224c6b373ec7b9dfe9c02096d43ab Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Tue, 15 Oct 2024 18:46:01 +0000 Subject: [PATCH 0863/1066] Move image load func to imgutil package Signed-off-by: Austin Vazquez --- cmd/nerdctl/image/image_load.go | 4 ++-- pkg/{cmd/image => imgutil/load}/load.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) rename pkg/{cmd/image => imgutil/load}/load.go (99%) diff --git a/cmd/nerdctl/image/image_load.go b/cmd/nerdctl/image/image_load.go index cd0698a3270..a80918f66f5 100644 --- a/cmd/nerdctl/image/image_load.go +++ b/cmd/nerdctl/image/image_load.go @@ -23,7 +23,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/clientutil" - "github.com/containerd/nerdctl/v2/pkg/cmd/image" + "github.com/containerd/nerdctl/v2/pkg/imgutil/load" ) func NewLoadCommand() *cobra.Command { @@ -94,5 +94,5 @@ func loadAction(cmd *cobra.Command, _ []string) error { } defer cancel() - return image.Load(ctx, client, options) + return load.Load(ctx, client, options) } diff --git a/pkg/cmd/image/load.go b/pkg/imgutil/load/load.go similarity index 99% rename from pkg/cmd/image/load.go rename to pkg/imgutil/load/load.go index 649a37102b9..2673e442597 100644 --- a/pkg/cmd/image/load.go +++ b/pkg/imgutil/load/load.go @@ -14,7 +14,7 @@ limitations under the License. */ -package image +package load import ( "context" @@ -98,6 +98,7 @@ func loadImage(ctx context.Context, client *containerd.Client, in io.Reader, pla if !options.Quiet { fmt.Fprintf(options.Stdout, "unpacking %s (%s)...\n", img.Name, img.Target.Digest) } + err = image.Unpack(ctx, options.GOptions.Snapshotter) if err != nil { return err From d8ab512e735c20ab922198c584b8cf69ba192793 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Tue, 15 Oct 2024 19:49:59 +0000 Subject: [PATCH 0864/1066] Refactor load from archive functionality Signed-off-by: Austin Vazquez --- cmd/nerdctl/image/image_load.go | 3 +- pkg/imgutil/load/load.go | 92 ++++++++++++++++++++------------- 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/cmd/nerdctl/image/image_load.go b/cmd/nerdctl/image/image_load.go index a80918f66f5..3ff8b18a892 100644 --- a/cmd/nerdctl/image/image_load.go +++ b/cmd/nerdctl/image/image_load.go @@ -94,5 +94,6 @@ func loadAction(cmd *cobra.Command, _ []string) error { } defer cancel() - return load.Load(ctx, client, options) + _, err = load.FromArchive(ctx, client, options) + return err } diff --git a/pkg/imgutil/load/load.go b/pkg/imgutil/load/load.go index 2673e442597..718585e8a7f 100644 --- a/pkg/imgutil/load/load.go +++ b/pkg/imgutil/load/load.go @@ -34,24 +34,12 @@ import ( "github.com/containerd/nerdctl/v2/pkg/platformutil" ) -type readCounter struct { - io.Reader - N int -} - -func (r *readCounter) Read(p []byte) (int, error) { - n, err := r.Reader.Read(p) - if n > 0 { - r.N += n - } - return n, err -} - -func Load(ctx context.Context, client *containerd.Client, options types.ImageLoadOptions) error { +// FromArchive loads and unpacks the images from the tar archive specified in image load options. +func FromArchive(ctx context.Context, client *containerd.Client, options types.ImageLoadOptions) ([]images.Image, error) { if options.Input != "" { f, err := os.Open(options.Input) if err != nil { - return err + return nil, err } defer f.Close() options.Stdin = f @@ -59,55 +47,85 @@ func Load(ctx context.Context, client *containerd.Client, options types.ImageLoa // check if stdin is empty. stdinStat, err := os.Stdin.Stat() if err != nil { - return err + return nil, err } if stdinStat.Size() == 0 && (stdinStat.Mode()&os.ModeNamedPipe) == 0 { - return errors.New("stdin is empty and input flag is not specified") + return nil, errors.New("stdin is empty and input flag is not specified") } } decompressor, err := compression.DecompressStream(options.Stdin) if err != nil { - return err + return nil, err } platMC, err := platformutil.NewMatchComparer(options.AllPlatforms, options.Platform) if err != nil { - return err + return nil, err + } + imgs, err := importImages(ctx, client, decompressor, options.GOptions.Snapshotter, platMC) + if err != nil { + return nil, err + } + unpackedImages := make([]images.Image, 0, len(imgs)) + for _, img := range imgs { + err := unpackImage(ctx, client, img, platMC, options) + if err != nil { + return unpackedImages, fmt.Errorf("error unpacking image (%s): %w", img.Name, err) + } + unpackedImages = append(unpackedImages, img) + } + return unpackedImages, nil +} + +type readCounter struct { + io.Reader + N int +} + +func (r *readCounter) Read(p []byte) (int, error) { + n, err := r.Reader.Read(p) + if n > 0 { + r.N += n } - return loadImage(ctx, client, decompressor, platMC, options) + return n, err } -func loadImage(ctx context.Context, client *containerd.Client, in io.Reader, platMC platforms.MatchComparer, options types.ImageLoadOptions) error { +func importImages(ctx context.Context, client *containerd.Client, in io.Reader, snapshotter string, platformMC platforms.MatchComparer) ([]images.Image, error) { // In addition to passing WithImagePlatform() to client.Import(), we also need to pass WithDefaultPlatform() to NewClient(). // Otherwise unpacking may fail. r := &readCounter{Reader: in} - imgs, err := client.Import(ctx, r, containerd.WithDigestRef(archive.DigestTranslator(options.GOptions.Snapshotter)), containerd.WithSkipDigestRef(func(name string) bool { return name != "" }), containerd.WithImportPlatform(platMC)) + imgs, err := client.Import(ctx, r, + containerd.WithDigestRef(archive.DigestTranslator(snapshotter)), + containerd.WithSkipDigestRef(func(name string) bool { return name != "" }), + containerd.WithImportPlatform(platformMC), + ) if err != nil { if r.N == 0 { // Avoid confusing "unrecognized image format" - return errors.New("no image was built") + return nil, errors.New("no image was built") } if errors.Is(err, images.ErrEmptyWalk) { err = fmt.Errorf("%w (Hint: set `--platform=PLATFORM` or `--all-platforms`)", err) } - return err + return nil, err } - for _, img := range imgs { - image := containerd.NewImageWithPlatform(client, img, platMC) + return imgs, nil +} - // TODO: Show unpack status - if !options.Quiet { - fmt.Fprintf(options.Stdout, "unpacking %s (%s)...\n", img.Name, img.Target.Digest) - } +func unpackImage(ctx context.Context, client *containerd.Client, model images.Image, platform platforms.MatchComparer, options types.ImageLoadOptions) error { + image := containerd.NewImageWithPlatform(client, model, platform) - err = image.Unpack(ctx, options.GOptions.Snapshotter) - if err != nil { - return err - } + if !options.Quiet { + fmt.Fprintf(options.Stdout, "unpacking %s (%s)...\n", model.Name, model.Target.Digest) + } - // Loaded message is shown even when quiet. - repo, tag := imgutil.ParseRepoTag(img.Name) - fmt.Fprintf(options.Stdout, "Loaded image: %s:%s\n", repo, tag) + err := image.Unpack(ctx, options.GOptions.Snapshotter) + if err != nil { + return err } + // Loaded message is shown even when quiet. + repo, tag := imgutil.ParseRepoTag(model.Name) + fmt.Fprintf(options.Stdout, "Loaded image: %s:%s\n", repo, tag) + return nil } From cc78fb3bd121f8aa759513ee02ec85d9d581eb20 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 20 Oct 2024 13:10:47 -0700 Subject: [PATCH 0865/1066] Remove old build tag syntax Signed-off-by: apostasie --- pkg/logging/logs_other.go | 1 - pkg/logging/logs_windows.go | 1 - 2 files changed, 2 deletions(-) diff --git a/pkg/logging/logs_other.go b/pkg/logging/logs_other.go index 6270efbe0fe..94cd53ef2b2 100644 --- a/pkg/logging/logs_other.go +++ b/pkg/logging/logs_other.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows /* Copyright The containerd Authors. diff --git a/pkg/logging/logs_windows.go b/pkg/logging/logs_windows.go index 262ac0c2d42..c6902d5b52a 100644 --- a/pkg/logging/logs_windows.go +++ b/pkg/logging/logs_windows.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows /* Copyright The containerd Authors. From 05918629dd0c66bbdaa405eb0013ff4f9a0f989f Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 20 Oct 2024 13:15:34 -0700 Subject: [PATCH 0866/1066] Remove no-op description from top-level tests Signed-off-by: apostasie --- cmd/nerdctl/image/image_convert_linux_test.go | 2 -- cmd/nerdctl/image/image_list_test.go | 6 ++---- cmd/nerdctl/image/image_pull_linux_test.go | 3 --- cmd/nerdctl/image/image_push_linux_test.go | 2 -- cmd/nerdctl/image/image_save_test.go | 3 +-- 5 files changed, 3 insertions(+), 13 deletions(-) diff --git a/cmd/nerdctl/image/image_convert_linux_test.go b/cmd/nerdctl/image/image_convert_linux_test.go index 85f0e243eaa..3a202a818ef 100644 --- a/cmd/nerdctl/image/image_convert_linux_test.go +++ b/cmd/nerdctl/image/image_convert_linux_test.go @@ -30,7 +30,6 @@ func TestImageConvert(t *testing.T) { nerdtest.Setup() testCase := &test.Case{ - Description: "Test image conversion", Require: test.Require( test.Not(test.Windows), test.Not(nerdtest.Docker), @@ -101,7 +100,6 @@ func TestImageConvertNydusVerify(t *testing.T) { var registry *testregistry.RegistryServer testCase := &test.Case{ - Description: "TestImageConvertNydusVerify", Require: test.Require( test.Linux, test.Binary("nydus-image"), diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index e89b2d44230..6aae9354a90 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -37,8 +37,7 @@ func TestImages(t *testing.T) { nerdtest.Setup() testCase := &test.Case{ - Description: "TestImages", - Require: test.Not(nerdtest.Docker), + Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("pull", "--quiet", testutil.CommonImage) helpers.Ensure("pull", "--quiet", testutil.NginxAlpineImage) @@ -133,8 +132,7 @@ func TestImagesFilter(t *testing.T) { nerdtest.Setup() testCase := &test.Case{ - Description: "TestImagesFilter", - Require: nerdtest.Build, + Require: nerdtest.Build, Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("pull", "--quiet", testutil.CommonImage) helpers.Ensure("tag", testutil.CommonImage, "taggedimage:one-fragment-one") diff --git a/cmd/nerdctl/image/image_pull_linux_test.go b/cmd/nerdctl/image/image_pull_linux_test.go index d2d624671fd..611c834b2ed 100644 --- a/cmd/nerdctl/image/image_pull_linux_test.go +++ b/cmd/nerdctl/image/image_pull_linux_test.go @@ -38,7 +38,6 @@ func TestImagePullWithCosign(t *testing.T) { var keyPair *testhelpers.CosignKeyPair testCase := &test.Case{ - Description: "TestImagePullWithCosign", Require: test.Require( test.Linux, nerdtest.Build, @@ -107,7 +106,6 @@ func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { var registry *testregistry.RegistryServer testCase := &test.Case{ - Description: "TestImagePullPlainHttpWithDefaultPort", Require: test.Require( test.Linux, test.Not(nerdtest.Docker), @@ -150,7 +148,6 @@ func TestImagePullSoci(t *testing.T) { nerdtest.Setup() testCase := &test.Case{ - Description: "TestImagePullSoci", Require: test.Require( test.Linux, test.Not(nerdtest.Docker), diff --git a/cmd/nerdctl/image/image_push_linux_test.go b/cmd/nerdctl/image/image_push_linux_test.go index 11dac1f8b3d..791141876ee 100644 --- a/cmd/nerdctl/image/image_push_linux_test.go +++ b/cmd/nerdctl/image/image_push_linux_test.go @@ -37,8 +37,6 @@ func TestPush(t *testing.T) { var registryNoAuthHTTPRandom, registryNoAuthHTTPDefault, registryTokenAuthHTTPSRandom *testregistry.RegistryServer testCase := &test.Case{ - Description: "Test push", - Require: test.Linux, Setup: func(data test.Data, helpers test.Helpers) { diff --git a/cmd/nerdctl/image/image_save_test.go b/cmd/nerdctl/image/image_save_test.go index eb2617a1eb3..90aa59909d2 100644 --- a/cmd/nerdctl/image/image_save_test.go +++ b/cmd/nerdctl/image/image_save_test.go @@ -35,8 +35,7 @@ func TestSaveContent(t *testing.T) { nerdtest.Setup() testCase := &test.Case{ - Description: "Test content (linux only)", - Require: test.Not(test.Windows), + Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("pull", "--quiet", testutil.CommonImage) }, From 62ad40462d937f2868ecb5f44e479fb49d161f60 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 20 Oct 2024 20:35:30 -0700 Subject: [PATCH 0867/1066] Ensure rm uses -f when cleaning Signed-off-by: apostasie --- cmd/nerdctl/ipfs/ipfs_simple_linux_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go b/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go index cddc1805d30..5c7b5697464 100644 --- a/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go @@ -104,7 +104,7 @@ func TestIPFSSimple(t *testing.T) { helpers.Ensure("pull", "ipfs://"+data.Get(transformedImageCIDKey)) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", data.Identifier("commit-container")) + helpers.Anyhow("rm", "-f", data.Identifier("commit-container")) helpers.Anyhow("rmi", "-f", data.Identifier("commit-image")) if data.Get(mainImageCIDKey) != "" { helpers.Anyhow("rmi", "-f", data.Get(mainImageCIDKey)) @@ -142,7 +142,7 @@ func TestIPFSSimple(t *testing.T) { helpers.Ensure("pull", "ipfs://"+data.Get(transformedImageCIDKey)) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", data.Identifier("commit-container")) + helpers.Anyhow("rm", "-f", data.Identifier("commit-container")) helpers.Anyhow("rmi", "-f", data.Identifier("commit-image")) if data.Get(mainImageCIDKey) != "" { helpers.Anyhow("rmi", "-f", data.Get(mainImageCIDKey)) From a4b2959b4e2179bb3aafa0b5b08a1fa2ac2efcd6 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Mon, 14 Oct 2024 16:20:27 +0000 Subject: [PATCH 0868/1066] Add container run from oci-archive Signed-off-by: Austin Vazquez --- .../container/container_create_linux_test.go | 32 +++++++++++++++++ cmd/nerdctl/container/container_run_test.go | 28 +++++++++++++++ docs/command-reference.md | 2 ++ pkg/cmd/container/create.go | 34 +++++++++++++++++++ pkg/imgutil/load/load.go | 20 +++++++++++ pkg/referenceutil/referenceutil.go | 7 ++++ pkg/referenceutil/referenceutil_test.go | 3 ++ 7 files changed, 126 insertions(+) diff --git a/cmd/nerdctl/container/container_create_linux_test.go b/cmd/nerdctl/container/container_create_linux_test.go index 6e8dbe2b491..2da8ae92302 100644 --- a/cmd/nerdctl/container/container_create_linux_test.go +++ b/cmd/nerdctl/container/container_create_linux_test.go @@ -29,6 +29,7 @@ import ( "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" @@ -306,3 +307,34 @@ func TestIssue2993(t *testing.T) { testCase.Run(t) } + +func TestCreateFromOCIArchive(t *testing.T) { + testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) + + // Docker does not support creating containers from OCI archive. + testutil.DockerIncompatible(t) + + base := testutil.NewBase(t) + imageName := testutil.Identifier(t) + containerName := testutil.Identifier(t) + + teardown := func() { + base.Cmd("rm", "-f", containerName).Run() + base.Cmd("rmi", "-f", imageName).Run() + } + defer teardown() + teardown() + + const sentinel = "test-nerdctl-create-from-oci-archive" + dockerfile := fmt.Sprintf(`FROM %s + CMD ["echo", "%s"]`, testutil.CommonImage, sentinel) + + buildCtx := helpers.CreateBuildContext(t, dockerfile) + tag := fmt.Sprintf("%s:latest", imageName) + tarPath := fmt.Sprintf("%s/%s.tar", buildCtx, imageName) + + base.Cmd("build", "--tag", tag, fmt.Sprintf("--output=type=oci,dest=%s", tarPath), buildCtx).AssertOK() + base.Cmd("create", "--rm", "--name", containerName, fmt.Sprintf("oci-archive://%s", tarPath)).AssertOK() + base.Cmd("start", "--attach", containerName).AssertOutContains("test-nerdctl-create-from-oci-archive") +} diff --git a/cmd/nerdctl/container/container_run_test.go b/cmd/nerdctl/container/container_run_test.go index 4d796fa750e..b7054c77722 100644 --- a/cmd/nerdctl/container/container_run_test.go +++ b/cmd/nerdctl/container/container_run_test.go @@ -658,3 +658,31 @@ func TestRunQuiet(t *testing.T) { assert.Assert(t, wasQuiet(result.Combined(), sentinel), "Found %s in container run output", sentinel) } + +func TestRunFromOCIArchive(t *testing.T) { + testutil.RequiresBuild(t) + testutil.RegisterBuildCacheCleanup(t) + + // Docker does not support running container images from OCI archive. + testutil.DockerIncompatible(t) + + base := testutil.NewBase(t) + imageName := testutil.Identifier(t) + + teardown := func() { + base.Cmd("rmi", "-f", imageName).Run() + } + defer teardown() + teardown() + + const sentinel = "test-nerdctl-run-from-oci-archive" + dockerfile := fmt.Sprintf(`FROM %s + CMD ["echo", "%s"]`, testutil.CommonImage, sentinel) + + buildCtx := helpers.CreateBuildContext(t, dockerfile) + tag := fmt.Sprintf("%s:latest", imageName) + tarPath := fmt.Sprintf("%s/%s.tar", buildCtx, imageName) + + base.Cmd("build", "--tag", tag, fmt.Sprintf("--output=type=oci,dest=%s", tarPath), buildCtx).AssertOK() + base.Cmd("run", "--rm", fmt.Sprintf("oci-archive://%s", tarPath)).AssertOutContainsAll(fmt.Sprintf("Loaded image: %s", tag), sentinel) +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 070c7db395e..1bd141aecc1 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -134,6 +134,7 @@ Run a command in a new container. Usage: `nerdctl run [OPTIONS] IMAGE [COMMAND] [ARG...]` :nerd_face: `ipfs://` prefix can be used for `IMAGE` to pull it from IPFS. See [`ipfs.md`](./ipfs.md) for details. +:nerd_face: `oci-archive://` prefix can be used for `IMAGE` to specify a local file system path to an OCI formatted tarball. Basic flags: @@ -423,6 +424,7 @@ Create a new container. Usage: `nerdctl create [OPTIONS] IMAGE [COMMAND] [ARG...]` :nerd_face: `ipfs://` prefix can be used for `IMAGE` to pull it from IPFS. See [`ipfs.md`](./ipfs.md) for details. +:nerd_face: `oci-archive://` prefix can be used for `IMAGE` to specify a local file system path to an OCI formatted tarball. The `nerdctl create` command similar to `nerdctl run -d` except the container is never started. You can then use the `nerdctl start ` command to start the container at any point. diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index fe01cee7bd1..b0effcff12d 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -50,6 +50,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/flagutil" "github.com/containerd/nerdctl/v2/pkg/idgen" "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/imgutil/load" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" @@ -123,6 +124,39 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa } opts = append(opts, platformOpts...) + if _, err := referenceutil.Parse(args[0]); errors.Is(err, referenceutil.ErrLoadOCIArchiveRequired) { + imageRef := args[0] + + // Load and create the platform specified by the user. + // If none specified, fallback to the default platform. + platform := []string{} + if options.Platform != "" { + platform = append(platform, options.Platform) + } + + images, err := load.FromOCIArchive(ctx, client, imageRef, types.ImageLoadOptions{ + Stdout: options.Stdout, + GOptions: options.GOptions, + Platform: platform, + AllPlatforms: false, + Quiet: options.ImagePullOpt.Quiet, + }) + if err != nil { + return nil, nil, err + } else if len(images) == 0 { + // This is a regression and should not occur. + return nil, nil, errors.New("OCI archive did not contain any images") + } + + image := images[0].Name + // Multiple images loaded from the provided archive. Default to the first image found. + if len(images) != 1 { + log.L.Warnf("multiple images are found for the platform, defaulting to image %s...", image) + } + + args[0] = image + } + var ensuredImage *imgutil.EnsuredImage if !options.Rootfs { var platformSS []string // len: 0 or 1 diff --git a/pkg/imgutil/load/load.go b/pkg/imgutil/load/load.go index 718585e8a7f..0afb322f4e4 100644 --- a/pkg/imgutil/load/load.go +++ b/pkg/imgutil/load/load.go @@ -22,6 +22,7 @@ import ( "fmt" "io" "os" + "strings" containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/images" @@ -76,6 +77,25 @@ func FromArchive(ctx context.Context, client *containerd.Client, options types.I return unpackedImages, nil } +// FromOCIArchive loads and unpacks the images from the OCI formatted archive at the provided file system path. +func FromOCIArchive(ctx context.Context, client *containerd.Client, pathToOCIArchive string, options types.ImageLoadOptions) ([]images.Image, error) { + const ociArchivePrefix = "oci-archive://" + pathToOCIArchive = strings.TrimPrefix(pathToOCIArchive, ociArchivePrefix) + + const separator = ":" + if strings.Contains(pathToOCIArchive, separator) { + subs := strings.Split(pathToOCIArchive, separator) + if len(subs) != 2 { + return nil, errors.New("too many seperators found in oci-archive path") + } + pathToOCIArchive = subs[0] + } + + options.Input = pathToOCIArchive + + return FromArchive(ctx, client, options) +} + type readCounter struct { io.Reader N int diff --git a/pkg/referenceutil/referenceutil.go b/pkg/referenceutil/referenceutil.go index 33df62f2358..4047a2ccad5 100644 --- a/pkg/referenceutil/referenceutil.go +++ b/pkg/referenceutil/referenceutil.go @@ -17,6 +17,7 @@ package referenceutil import ( + "errors" "path" "strings" @@ -31,6 +32,8 @@ const IPFSProtocol Protocol = "ipfs" const IPNSProtocol Protocol = "ipns" const shortIDLength = 5 +var ErrLoadOCIArchiveRequired = errors.New("image must be loaded from archive before parsing image reference") + type ImageReference struct { Protocol Protocol Digest digest.Digest @@ -97,6 +100,10 @@ func Parse(rawRef string) (*ImageReference, error) { } else if strings.HasPrefix(rawRef, "ipns://") { ir.Protocol = IPNSProtocol rawRef = rawRef[7:] + } else if strings.HasPrefix(rawRef, "oci-archive://") { + // The image must be loaded from the specified archive path first + // before parsing the image reference specified in its OCI image manifest. + return nil, ErrLoadOCIArchiveRequired } if decodedCID, err := cid.Decode(rawRef); err == nil { ir.Protocol = IPFSProtocol diff --git a/pkg/referenceutil/referenceutil_test.go b/pkg/referenceutil/referenceutil_test.go index 699d1c3f487..8c066434857 100644 --- a/pkg/referenceutil/referenceutil_test.go +++ b/pkg/referenceutil/referenceutil_test.go @@ -273,6 +273,9 @@ func TestReferenceUtil(t *testing.T) { Tag: "latest", ExplicitTag: "", }, + "oci-archive:///tmp/build/saved-image.tar": { + Error: "image must be loaded from archive before parsing image reference", + }, } for k, v := range needles { From 3b203a3556acf293cd76175d64d1846aef210d9a Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 27 Jun 2024 22:33:34 +0900 Subject: [PATCH 0869/1066] update runc (1.2.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- hack/build-integration-canary.sh | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index a594358aee4..84c0600e543 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v2.0.0-rc.5 -ARG RUNC_VERSION=v1.1.15 +ARG RUNC_VERSION=v1.2.0 ARG CNI_PLUGINS_VERSION=v1.5.1 # Extra deps: Build diff --git a/hack/build-integration-canary.sh b/hack/build-integration-canary.sh index 32fdfb3d249..0396ada100e 100755 --- a/hack/build-integration-canary.sh +++ b/hack/build-integration-canary.sh @@ -28,10 +28,7 @@ readonly root # "Blacklisting" here means that any dependency which name is blacklisted will be left untouched, at the version # currently pinned in the Dockerfile. # This is convenient so that currently broken alpha/beta/RC can be held back temporarily to keep the build green - -# Currently pinned, see: -# - https://github.com/containerd/nerdctl/pull/3153 -blacklist=(runc) +blacklist=() # List all the repositories we depend on to build and run integration tests dependencies=( @@ -219,6 +216,7 @@ canary::build::integration(){ docker_args=(docker build -t test-integration --target test-integration) for dep in "${dependencies[@]}"; do + local bl="" shortname="${dep##*/}" [ "$shortname" != "plugins" ] || shortname="cni-plugins" [ "$shortname" != "fuse-overlayfs-snapshotter" ] || shortname="containerd-fuse-overlayfs" From 5db8a48ddacb3eeacfc6008c355196ba0ffa9eb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Oct 2024 22:34:33 +0000 Subject: [PATCH 0870/1066] build(deps): bump github.com/fatih/color from 1.17.0 to 1.18.0 Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.17.0 to 1.18.0. - [Release notes](https://github.com/fatih/color/releases) - [Commits](https://github.com/fatih/color/compare/v1.17.0...v1.18.0) --- updated-dependencies: - dependency-name: github.com/fatih/color dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5af256da78e..6c33bbbd745 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 - github.com/fatih/color v1.17.0 + github.com/fatih/color v1.18.0 github.com/fluent/fluent-logger-golang v1.9.0 github.com/fsnotify/fsnotify v1.7.0 github.com/go-viper/mapstructure/v2 v2.2.1 diff --git a/go.sum b/go.sum index 2aa10101e64..04e54cc70db 100644 --- a/go.sum +++ b/go.sum @@ -104,8 +104,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fahedouch/go-logrotate v0.2.1 h1:Q0Hk9Kp/Y4iwy9uR9e/60fEoxGhvfk8MG7WwtL9aarM= github.com/fahedouch/go-logrotate v0.2.1/go.mod h1:Mmyex1f9fGXBNnhS9uHsbnO9BGvADF4VGqVnqAJalgc= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= From bbb5b305338a60a192c31c4b4cbd8d66f0face58 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 20 Oct 2024 13:17:26 -0700 Subject: [PATCH 0871/1066] Add new requirements (HyperV, CgroupsAccessible) Signed-off-by: apostasie --- pkg/testutil/nerdtest/requirements.go | 17 +++++++++++ pkg/testutil/nerdtest/requirements_other.go | 29 +++++++++++++++++++ pkg/testutil/nerdtest/requirements_windows.go | 28 ++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 pkg/testutil/nerdtest/requirements_other.go create mode 100644 pkg/testutil/nerdtest/requirements_windows.go diff --git a/pkg/testutil/nerdtest/requirements.go b/pkg/testutil/nerdtest/requirements.go index 3c365095b03..a5d89481203 100644 --- a/pkg/testutil/nerdtest/requirements.go +++ b/pkg/testutil/nerdtest/requirements.go @@ -171,6 +171,23 @@ var CGroup = &test.Requirement{ }, } +var CgroupsAccessible = test.Require( + CGroup, + &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + isRootLess := getTarget() == targetNerdctl && rootlessutil.IsRootless() + if isRootLess { + stdout := helpers.Capture("info", "--format", "{{ json . }}") + var dinf dockercompat.Info + err := json.Unmarshal([]byte(stdout), &dinf) + assert.NilError(helpers.T(), err, "failed to parse docker info") + return dinf.CgroupVersion == "2", "we are rootless, and cgroup version is not 2" + } + return true, "" + }, + }, +) + // Soci requires that the soci snapshotter is enabled var Soci = &test.Requirement{ Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { diff --git a/pkg/testutil/nerdtest/requirements_other.go b/pkg/testutil/nerdtest/requirements_other.go new file mode 100644 index 00000000000..74e280670c7 --- /dev/null +++ b/pkg/testutil/nerdtest/requirements_other.go @@ -0,0 +1,29 @@ +//go:build !windows + +/* + 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 nerdtest + +import ( + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +var HyperV = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + return false, "HyperV is a windows-only feature" + }, +} diff --git a/pkg/testutil/nerdtest/requirements_windows.go b/pkg/testutil/nerdtest/requirements_windows.go new file mode 100644 index 00000000000..a1155a970db --- /dev/null +++ b/pkg/testutil/nerdtest/requirements_windows.go @@ -0,0 +1,28 @@ +/* + 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 nerdtest + +import ( + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +var HyperV = &test.Requirement{ + Check: func(data test.Data, helpers test.Helpers) (ret bool, mess string) { + return testutil.HyperVSupported(), "HyperV is not enabled, skipping test" + }, +} From 0ee1a5929b6c5e0c23b9b32f04c026866a277ea2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 22:25:56 +0000 Subject: [PATCH 0872/1066] build(deps): bump actions/checkout from 4.2.1 to 4.2.2 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.1 to 4.2.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.1...v4.2.2) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../ghcr-image-build-and-publish.yml | 2 +- .github/workflows/lint.yml | 4 ++-- .github/workflows/project.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test-canary.yml | 6 +++--- .github/workflows/test-kube.yml | 2 +- .github/workflows/test.yml | 20 +++++++++---------- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index bd7941780a2..84ab99f681b 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index be29a8c2aec..433922ed207 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -36,7 +36,7 @@ jobs: env: GOOS: "${{ matrix.goos }}" steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - name: Set GO env @@ -60,7 +60,7 @@ jobs: name: yaml | shell | imports order runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - uses: actions/setup-go@v5 diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml index 6961f0fd565..ebeef72caec 100644 --- a/.github/workflows/project.yml +++ b/.github/workflows/project.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 60117672325..4043288037c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 - uses: actions/setup-go@v5 with: go-version: 1.23.x diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 7c9226f45f8..75a666d32b4 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -19,7 +19,7 @@ jobs: runs-on: "ubuntu-24.04" timeout-minutes: 40 steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -55,7 +55,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - name: Set GO env @@ -79,7 +79,7 @@ jobs: - run: go install -v gotest.tools/gotestsum@v1 # This here is solely to get the cni install script, which has not been modified in 3+ years. # There is little to no reason to update this to latest containerd - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: repository: containerd/containerd ref: "v1.7.23" diff --git a/.github/workflows/test-kube.yml b/.github/workflows/test-kube.yml index 3c6faaaa457..2bd0d00f28c 100644 --- a/.github/workflows/test-kube.yml +++ b/.github/workflows/test-kube.yml @@ -17,7 +17,7 @@ jobs: env: ROOTFUL: true steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - name: "Run Kubernetes integration tests" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 863b956938c..c2faa76231a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,7 +33,7 @@ jobs: - os: ubuntu-24.04 goos: linux steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -42,7 +42,7 @@ jobs: check-latest: true cache: true - if: ${{ matrix.goos=='windows' }} - uses: actions/checkout@v4.2.1 + uses: actions/checkout@v4.2.2 with: repository: containerd/containerd ref: v1.7.23 @@ -80,7 +80,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -120,7 +120,7 @@ jobs: UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - name: Enable ipv4 and ipv6 forwarding @@ -203,7 +203,7 @@ jobs: } EOT sudo systemctl restart apparmor.service - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -238,7 +238,7 @@ jobs: matrix: go-version: ["1.22.x", "1.23.x"] steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -254,7 +254,7 @@ jobs: name: docker runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -295,7 +295,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - uses: actions/setup-go@v5 @@ -305,7 +305,7 @@ jobs: check-latest: true - run: go install ./cmd/nerdctl - run: go install -v gotest.tools/gotestsum@v1 - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: repository: containerd/containerd ref: v1.7.23 @@ -330,7 +330,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 - uses: actions/cache@v4 with: path: /root/.vagrant.d From 247fcca2aeaa8c44296f2e0bf6bbe7831f7c9df5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 02:57:51 +0000 Subject: [PATCH 0873/1066] build(deps): bump github.com/containerd/containerd/v2 Bumps [github.com/containerd/containerd/v2](https://github.com/containerd/containerd) from 2.0.0-rc.5 to 2.0.0-rc.6. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v2.0.0-rc.5...v2.0.0-rc.6) --- updated-dependencies: - dependency-name: github.com/containerd/containerd/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 28 +++++++++++++++------------- go.sum | 56 ++++++++++++++++++++++++++++++-------------------------- 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 6c33bbbd745..58646e4d73e 100644 --- a/go.mod +++ b/go.mod @@ -10,15 +10,15 @@ go 1.22.0 require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 - github.com/Microsoft/hcsshim v0.12.7 + github.com/Microsoft/hcsshim v0.12.8 github.com/compose-spec/compose-go/v2 v2.3.0 github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd/api v1.8.0-rc.3 - github.com/containerd/containerd/v2 v2.0.0-rc.5 + github.com/containerd/containerd/api v1.8.0-rc.4 + github.com/containerd/containerd/v2 v2.0.0-rc.6 github.com/containerd/continuity v0.4.3 - github.com/containerd/errdefs v0.1.0 + github.com/containerd/errdefs v0.3.0 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.10 github.com/containerd/imgcrypt v1.2.0-rc1.0.20240709223013-f3769dc3e47f @@ -81,9 +81,11 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/cilium/ebpf v0.16.0 // indirect + github.com/containerd/containerd v1.7.23 // indirect + github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/go-runc v1.1.0 // indirect github.com/containerd/plugin v0.1.0 // indirect - github.com/containerd/ttrpc v1.2.5 // indirect + github.com/containerd/ttrpc v1.2.6-0.20240827082320-b5cd6e4b3287 // indirect github.com/containers/ocicrypt v1.2.0 // indirect github.com/djherbis/times v1.6.0 // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect @@ -116,7 +118,7 @@ require ( github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-varint v0.0.7 // indirect github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect - github.com/opencontainers/selinux v1.11.0 // indirect + github.com/opencontainers/selinux v1.11.1 // indirect github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect @@ -130,15 +132,15 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect - go.opentelemetry.io/otel v1.30.0 // indirect - go.opentelemetry.io/otel/metric v1.30.0 // indirect - go.opentelemetry.io/otel/trace v1.30.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect + go.opentelemetry.io/otel v1.31.0 // indirect + go.opentelemetry.io/otel/metric v1.31.0 // indirect + go.opentelemetry.io/otel/trace v1.31.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect golang.org/x/mod v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/grpc v1.67.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect + google.golang.org/grpc v1.67.1 // indirect + google.golang.org/protobuf v1.35.1 // indirect lukechampine.com/blake3 v1.3.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect tags.cncf.io/container-device-interface v0.8.0 // indirect diff --git a/go.sum b/go.sum index 04e54cc70db..2a1dc9b97ad 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+ github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= 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.12.7 h1:MP6R1spmjxTE4EU4J3YsrTxn8CjvN9qwjTKJXldFaRg= -github.com/Microsoft/hcsshim v0.12.7/go.mod h1:HPbAuJ9BvQYYZbB4yEQcyGIsTP5L4yHKeO9XO149AEM= +github.com/Microsoft/hcsshim v0.12.8 h1:BtDWYlFMcWhorrvSSo2M7z0csPdw6t7no/C3FsSvqiI= +github.com/Microsoft/hcsshim v0.12.8/go.mod h1:cibQ4BqhJ32FXDwPdQhKhwrwophnh3FuT4nwQZF907w= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= @@ -31,14 +31,18 @@ github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGD github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= 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/api v1.8.0-rc.3 h1:q9MyeXmuAGEyKmUGYvvFftNX1RQhfTLsAvYK+SQHQso= -github.com/containerd/containerd/api v1.8.0-rc.3/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= -github.com/containerd/containerd/v2 v2.0.0-rc.5 h1:ejHlOWce4MxQr+lGXdbCCyOZIWqIq027DjXI73SUwg8= -github.com/containerd/containerd/v2 v2.0.0-rc.5/go.mod h1:biu3ZtJwDHEdVxxho680KtHqFfk8WPA1hULNf/vJ7Lw= +github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ= +github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= +github.com/containerd/containerd/api v1.8.0-rc.4 h1:Z650GHP0OxsoTwwii5U2hyTt7eCRQvvDnRM7pEH/DE0= +github.com/containerd/containerd/api v1.8.0-rc.4/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= +github.com/containerd/containerd/v2 v2.0.0-rc.6 h1:uIUmoiXH770KCkTzzqksSpQg7JZ4tC0eM2qXm5EAuwI= +github.com/containerd/containerd/v2 v2.0.0-rc.6/go.mod h1:O+llF4jv6jUxQC6J44UMzpeKI30yhdwkcsL7kUlCyek= 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/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= +github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= +github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= 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.10 h1:c2U73nld7spSWfiJwSh/8W9DK+/qQwYM2rngIhCyhyg= @@ -61,8 +65,8 @@ github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5e github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:9WSor0wu2swhtYoFkrjy3GHt7aNgKR2A7FhnpP+CH5o= github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319 h1:WdmIerlurjZSoLI2w8014yzJY+q4qdO/A3ZJBEK7LQA= github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:L/J/O36DzcGxq3drHM45sJRr/pEQTG5u+tbffVhP6r8= -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/ttrpc v1.2.6-0.20240827082320-b5cd6e4b3287 h1:zwv64tCdT888KxuXQuv5i36cEdljoXq3sVqLmOEbCQI= +github.com/containerd/ttrpc v1.2.6-0.20240827082320-b5cd6e4b3287/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= @@ -251,8 +255,8 @@ github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/ github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 h1:DmNGcqH3WDbV5k8OJ+esPWbqUOX5rMLR2PMvziDMJi0= github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI= github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= -github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8= +github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= @@ -321,14 +325,14 @@ go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdH go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= 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.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= -go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= -go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= -go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= -go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= -go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= -go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= 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.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= @@ -409,15 +413,15 @@ 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/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= 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= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -427,8 +431,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= From 5551d6d3464afa7fb4ca066f78674e35f8d8850c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 24 Oct 2024 17:57:30 +0900 Subject: [PATCH 0874/1066] update containerd (2.0.0-rc.6) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 919c0b89dab..22188c77c7c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v2.0.0-rc.5 +ARG CONTAINERD_VERSION=v2.0.0-rc.6 ARG RUNC_VERSION=v1.2.0 ARG CNI_PLUGINS_VERSION=v1.5.1 From 98442f5069044371771fc59ffa3644a57229a1b0 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 24 Oct 2024 17:58:29 +0900 Subject: [PATCH 0875/1066] update CNI plugins (1.6.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.1 | 2 -- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.0 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.0 diff --git a/Dockerfile b/Dockerfile index 22188c77c7c..cf0e56d5b00 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ # Basic deps ARG CONTAINERD_VERSION=v2.0.0-rc.6 ARG RUNC_VERSION=v1.2.0 -ARG CNI_PLUGINS_VERSION=v1.5.1 +ARG CNI_PLUGINS_VERSION=v1.6.0 # Extra deps: Build ARG BUILDKIT_VERSION=v0.16.0 diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.1 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.1 deleted file mode 100644 index 6a91ab30028..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.5.1 +++ /dev/null @@ -1,2 +0,0 @@ -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/cni-plugins-v1.6.0 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.0 new file mode 100644 index 00000000000..8329f9a59c5 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.0 @@ -0,0 +1,2 @@ +682b49ff8933a997a52107161f1745f8312364b4c7f605ccdf7a77499130d89d cni-plugins-linux-amd64-v1.6.0.tgz +db09ab057ecf60b05ba05cbec38d55b95cc139c7f1078e2e4857cc13af158cee cni-plugins-linux-arm64-v1.6.0.tgz From 90fbd09b80ced593db2ab24cbef29b88275f6d85 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 24 Oct 2024 18:01:39 +0900 Subject: [PATCH 0876/1066] update Nydus (2.3.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cf0e56d5b00..fa05ef9a2a3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,7 @@ ARG GO_VERSION=1.23 ARG UBUNTU_VERSION=24.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.12.0 -ARG NYDUS_VERSION=v2.2.5 +ARG NYDUS_VERSION=v2.3.0 ARG SOCI_SNAPSHOTTER_VERSION=0.7.0 ARG KUBO_VERSION=v0.29.0 From 509460546e9eaaa93092e65104370075bcc8614a Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 24 Oct 2024 18:02:06 +0900 Subject: [PATCH 0877/1066] update Kubo (0.31.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index fa05ef9a2a3..05018174b63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,7 +48,7 @@ ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.12.0 ARG NYDUS_VERSION=v2.3.0 ARG SOCI_SNAPSHOTTER_VERSION=0.7.0 -ARG KUBO_VERSION=v0.29.0 +ARG KUBO_VERSION=v0.31.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0 AS xx From af25fd406960119d2ac11a1d3f69c82c7627d700 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 24 Oct 2024 06:16:38 +0000 Subject: [PATCH 0878/1066] add white image Signed-off-by: Kay Yan --- README.md | 6 +++++- docs/images/nerdctl-white.svg | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 docs/images/nerdctl-white.svg diff --git a/README.md b/README.md index 8076cd67446..b0cb1698a95 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,11 @@ # nerdctl: Docker-compatible CLI for containerd -![logo](docs/images/nerdctl.svg) + + + + logo + `nerdctl` is a Docker-compatible CLI for [contai**nerd**](https://containerd.io). diff --git a/docs/images/nerdctl-white.svg b/docs/images/nerdctl-white.svg new file mode 100644 index 00000000000..8edeab006a5 --- /dev/null +++ b/docs/images/nerdctl-white.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + From bb240f124d666221b986502b9ff9e8d4adcf09e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 22:16:58 +0000 Subject: [PATCH 0879/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.3.0 to 2.4.0. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.3.0...v2.4.0) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 58646e4d73e..b47dff8fae1 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.8 - github.com/compose-spec/compose-go/v2 v2.3.0 + github.com/compose-spec/compose-go/v2 v2.4.0 github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index 2a1dc9b97ad..583d51bb357 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.3.0 h1:5eomqgNcs/GqVknPtXF68V3muc67cOdXD35zCXn1aes= -github.com/compose-spec/compose-go/v2 v2.3.0/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.4.0 h1:Hb0YNtknMWZGHUuULtV/f0cYJVTLt7TWHGEtJwOPzK4= +github.com/compose-spec/compose-go/v2 v2.4.0/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= From 443d504b557d02fcb0fdc73df2bd0e25bbd0b22b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:00:48 +0000 Subject: [PATCH 0880/1066] build(deps): bump github.com/containerd/continuity from 0.4.3 to 0.4.4 Bumps [github.com/containerd/continuity](https://github.com/containerd/continuity) from 0.4.3 to 0.4.4. - [Release notes](https://github.com/containerd/continuity/releases) - [Commits](https://github.com/containerd/continuity/compare/v0.4.3...v0.4.4) --- updated-dependencies: - dependency-name: github.com/containerd/continuity dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b47dff8fae1..c369ed5c7ab 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0-rc.4 github.com/containerd/containerd/v2 v2.0.0-rc.6 - github.com/containerd/continuity v0.4.3 + github.com/containerd/continuity v0.4.4 github.com/containerd/errdefs v0.3.0 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.10 diff --git a/go.sum b/go.sum index 583d51bb357..0d4a8ed5445 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/containerd/containerd/api v1.8.0-rc.4 h1:Z650GHP0OxsoTwwii5U2hyTt7eCR github.com/containerd/containerd/api v1.8.0-rc.4/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/v2 v2.0.0-rc.6 h1:uIUmoiXH770KCkTzzqksSpQg7JZ4tC0eM2qXm5EAuwI= github.com/containerd/containerd/v2 v2.0.0-rc.6/go.mod h1:O+llF4jv6jUxQC6J44UMzpeKI30yhdwkcsL7kUlCyek= -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/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= +github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= From fcdd7262b36a0efbec5907080b6038b0fdaf45bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:01:01 +0000 Subject: [PATCH 0881/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.4.0 to 2.4.1. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.4.0...v2.4.1) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b47dff8fae1..8369d4618ab 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.8 - github.com/compose-spec/compose-go/v2 v2.4.0 + github.com/compose-spec/compose-go/v2 v2.4.1 github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index 583d51bb357..74752fa0d18 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.4.0 h1:Hb0YNtknMWZGHUuULtV/f0cYJVTLt7TWHGEtJwOPzK4= -github.com/compose-spec/compose-go/v2 v2.4.0/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.4.1 h1:tEg6Qn/9LZnKg42fZlFmxN4lxSqnCvsiG5TXnxzvI4c= +github.com/compose-spec/compose-go/v2 v2.4.1/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= From eddb0eb8fb2f6ac84f108fd64cc21a5016b99c87 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 29 Oct 2024 09:01:44 +0900 Subject: [PATCH 0882/1066] go.mod: github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- go.mod | 6 +++--- go.sum | 12 ++++++------ pkg/cmd/image/crypt.go | 4 ++-- pkg/imgutil/imgutil.go | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index 05018174b63..6099e85352f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ ARG BUILDKIT_VERSION=v0.16.0 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption -ARG IMGCRYPT_VERSION=v1.1.11 +ARG IMGCRYPT_VERSION=v2.0.0-rc.1 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v2.3.1 ARG SLIRP4NETNS_VERSION=v1.3.1 diff --git a/go.mod b/go.mod index f6c7a46d8fa..8fc5274b9b9 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/containerd/errdefs v0.3.0 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.10 - github.com/containerd/imgcrypt v1.2.0-rc1.0.20240709223013-f3769dc3e47f + github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.14.1-0.20240806063146-8fa319bfe9c5 github.com/containerd/platforms v0.2.1 @@ -130,7 +130,7 @@ require ( github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect - go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect + go.mozilla.org/pkcs7 v0.9.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/otel v1.31.0 // indirect @@ -138,7 +138,7 @@ require ( go.opentelemetry.io/otel/trace v1.31.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect golang.org/x/mod v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.35.1 // indirect lukechampine.com/blake3 v1.3.0 // indirect diff --git a/go.sum b/go.sum index 7f1e20fd125..a2078cf01b3 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,8 @@ github.com/containerd/go-cni v1.1.10 h1:c2U73nld7spSWfiJwSh/8W9DK+/qQwYM2rngIhCy github.com/containerd/go-cni v1.1.10/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA= github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U= -github.com/containerd/imgcrypt v1.2.0-rc1.0.20240709223013-f3769dc3e47f h1:VuW2PlwpES6W86asOw+ysYEpARdlPkwpM6DsT4sbv8U= -github.com/containerd/imgcrypt v1.2.0-rc1.0.20240709223013-f3769dc3e47f/go.mod h1:F9roK2DzKlFnV+h+ZJy/r2FoS28bIvxKgdcoV7o8Sms= +github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 h1:7OMu5otk5Z2GeQs24JBPOmYbTc50+q6jo02qWNJc0p8= +github.com/containerd/imgcrypt/v2 v2.0.0-rc.1/go.mod h1:3/Ab3iliBt/aBVNYOwecT1YagCqAiHidOmVsrjtHF1A= 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.14.1-0.20240806063146-8fa319bfe9c5 h1:NpscnGdkmWwlb0o2Q+rDO/kfoLObfY2sHwB6M5uF58Q= @@ -321,8 +321,8 @@ github.com/yuchanns/srslog v1.1.0 h1:CEm97Xxxd8XpJThE0gc/XsqUGgPufh5u5MUjC27/KOk github.com/yuchanns/srslog v1.1.0/go.mod h1:HsLjdv3XV02C3kgBW2bTyW6i88OQE+VYJZIxrPKPPak= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak= -go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +go.mozilla.org/pkcs7 v0.9.0 h1:yM4/HS9dYv7ri2biPtxt8ikvB37a980dg69/pKmS+eI= +go.mozilla.org/pkcs7 v0.9.0/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= 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.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= @@ -413,8 +413,8 @@ 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/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= 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/pkg/cmd/image/crypt.go b/pkg/cmd/image/crypt.go index 68a18b43117..981d39dfd51 100644 --- a/pkg/cmd/image/crypt.go +++ b/pkg/cmd/image/crypt.go @@ -26,8 +26,8 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/images/converter" - "github.com/containerd/imgcrypt/images/encryption" - "github.com/containerd/imgcrypt/images/encryption/parsehelpers" + "github.com/containerd/imgcrypt/v2/images/encryption" + "github.com/containerd/imgcrypt/v2/images/encryption/parsehelpers" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/platformutil" diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 7a6d01acb23..09ca283b5dc 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -33,8 +33,8 @@ import ( "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/errdefs" - "github.com/containerd/imgcrypt" - "github.com/containerd/imgcrypt/images/encryption" + "github.com/containerd/imgcrypt/v2" + "github.com/containerd/imgcrypt/v2/images/encryption" "github.com/containerd/log" "github.com/containerd/platforms" From 4d06e7305c2ad7afc225cd71c659a3a7d4f5acad Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 20 Oct 2024 13:24:45 -0700 Subject: [PATCH 0883/1066] Rewrite container_wait tests Signed-off-by: apostasie --- cmd/nerdctl/container/container_wait_test.go | 35 +++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/cmd/nerdctl/container/container_wait_test.go b/cmd/nerdctl/container/container_wait_test.go index d6a3203480a..9c0c93da3ff 100644 --- a/cmd/nerdctl/container/container_wait_test.go +++ b/cmd/nerdctl/container/container_wait_test.go @@ -20,28 +20,31 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestWait(t *testing.T) { - t.Parallel() - tID := testutil.Identifier(t) - testContainerName1 := tID + "-1" - testContainerName2 := tID + "-2" - testContainerName3 := tID + "-3" + testCase := nerdtest.Setup() - const expected = `0 -0 -123 -` - base := testutil.NewBase(t) - defer base.Cmd("rm", "-f", testContainerName1, testContainerName2, testContainerName3).Run() - - base.Cmd("run", "-d", "--name", testContainerName1, testutil.CommonImage, "sleep", "1").AssertOK() + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier("1"), data.Identifier("2"), data.Identifier("3")) + } - base.Cmd("run", "-d", "--name", testContainerName2, testutil.CommonImage, "sleep", "1").AssertOK() + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "-d", "--name", data.Identifier("1"), testutil.CommonImage) + helpers.Ensure("run", "-d", "--name", data.Identifier("2"), testutil.CommonImage, "sleep", "1") + helpers.Ensure("run", "-d", "--name", data.Identifier("3"), testutil.CommonImage, "sh", "-euxc", "sleep 5; exit 123") + } - base.Cmd("run", "--name", testContainerName3, testutil.CommonImage, "sh", "-euxc", "sleep 5; exit 123").AssertExitCode(123) + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("wait", data.Identifier("1"), data.Identifier("2"), data.Identifier("3")) + } - base.Cmd("wait", testContainerName1, testContainerName2, testContainerName3).AssertOutExactly(expected) + testCase.Expected = test.Expects(0, nil, test.Equals(`0 +0 +123 +`)) + testCase.Run(t) } From a5f487d4849c87137254db750e93d82d9fbcc1b7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 29 Oct 2024 17:59:27 +0100 Subject: [PATCH 0884/1066] Align gitignore and dockerignore Signed-off-by: apostasie --- .dockerignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.dockerignore b/.dockerignore index 33c9733d860..646cd932d8f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,7 +3,7 @@ _output # golangci-lint -build +/build # vagrant /.vagrant From 2336d3d1d0ccbcfc9635ef2a930ab1d8e2bd115d Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 20 Oct 2024 13:27:13 -0700 Subject: [PATCH 0885/1066] Rewrite container diff test Signed-off-by: apostasie --- .../container/container_diff_linux_test.go | 45 -------------- cmd/nerdctl/container/container_diff_test.go | 59 +++++++++++++++++++ 2 files changed, 59 insertions(+), 45 deletions(-) delete mode 100644 cmd/nerdctl/container/container_diff_linux_test.go create mode 100644 cmd/nerdctl/container/container_diff_test.go diff --git a/cmd/nerdctl/container/container_diff_linux_test.go b/cmd/nerdctl/container/container_diff_linux_test.go deleted file mode 100644 index 7de8c302ed5..00000000000 --- a/cmd/nerdctl/container/container_diff_linux_test.go +++ /dev/null @@ -1,45 +0,0 @@ -/* - 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 container - -import ( - "testing" - - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestDiff(t *testing.T) { - // It is unclear why this is failing with docker when run in parallel - // Obviously some other container test is interfering - if testutil.GetTarget() != testutil.Docker { - t.Parallel() - } - base := testutil.NewBase(t) - containerName := testutil.Identifier(t) - defer base.Cmd("rm", containerName).Run() - - base.Cmd("run", "-d", "--name", containerName, testutil.CommonImage, - "sh", "-euxc", "touch /a; touch /bin/b; rm /bin/base64").AssertOK() - // nerdctl contains more output "C /etc", "A /etc/resolv.conf" unlike docker - base.Cmd("diff", containerName).AssertOutContainsAll( - "A /a", - "C /bin", - "A /bin/b", - "D /bin/base64", - ) - base.Cmd("rm", "-f", containerName).AssertOK() -} diff --git a/cmd/nerdctl/container/container_diff_test.go b/cmd/nerdctl/container/container_diff_test.go new file mode 100644 index 00000000000..b47631dd600 --- /dev/null +++ b/cmd/nerdctl/container/container_diff_test.go @@ -0,0 +1,59 @@ +/* + 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 container + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestDiff(t *testing.T) { + testCase := nerdtest.Setup() + + // It is unclear why this is failing with docker when run in parallel + // Obviously some other container test is interfering + if nerdtest.IsDocker() { + testCase.NoParallel = true + } + + testCase.Require = test.Not(test.Windows) + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, + "sh", "-euxc", "touch /a; touch /bin/b; rm /bin/base64") + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + } + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("diff", data.Identifier()) + } + + testCase.Expected = test.Expects(0, nil, test.All( + test.Contains("A /a"), + test.Contains("C /bin"), + test.Contains("A /bin/b"), + test.Contains("D /bin/base64"), + )) + + testCase.Run(t) +} From 38f74400432a5d75a648967c15d072dca2f57c11 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 20 Oct 2024 13:32:16 -0700 Subject: [PATCH 0886/1066] Rewrite container remove test Signed-off-by: apostasie --- .../container/container_remove_test.go | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/cmd/nerdctl/container/container_remove_test.go b/cmd/nerdctl/container/container_remove_test.go index 3f9eecfd679..89028281060 100644 --- a/cmd/nerdctl/container/container_remove_test.go +++ b/cmd/nerdctl/container/container_remove_test.go @@ -20,22 +20,30 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestRemoveContainer(t *testing.T) { - t.Parallel() + testCase := nerdtest.Setup() - base := testutil.NewBase(t) - tID := testutil.Identifier(t) + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "inf") + } - // ignore error - base.Cmd("rm", tID, "-f").AssertOK() + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + } - base.Cmd("run", "-d", "--name", tID, testutil.NginxAlpineImage).AssertOK() - defer base.Cmd("rm", tID, "-f").AssertOK() - base.Cmd("rm", tID).AssertFail() + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + helpers.Fail("rm", data.Identifier()) - // `kill` does return before the container actually stops - base.Cmd("stop", tID).AssertOK() - base.Cmd("rm", tID).AssertOK() + // FIXME: should (re-)evaluate this + // `kill` seems to return before the container actually stops + helpers.Ensure("stop", data.Identifier()) + + return helpers.Command("rm", data.Identifier()) + } + + testCase.Expected = test.Expects(0, nil, nil) } From b722721171f13f1fb7f62413c3db6fe3cedfec2a Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 20 Oct 2024 13:34:54 -0700 Subject: [PATCH 0887/1066] Rewrite container prune test Signed-off-by: apostasie --- .../container/container_prune_linux_test.go | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/cmd/nerdctl/container/container_prune_linux_test.go b/cmd/nerdctl/container/container_prune_linux_test.go index 8912e8fb8dd..84979c780a6 100644 --- a/cmd/nerdctl/container/container_prune_linux_test.go +++ b/cmd/nerdctl/container/container_prune_linux_test.go @@ -20,36 +20,36 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestPruneContainer(t *testing.T) { - base := testutil.NewBase(t) - tID := testutil.Identifier(t) + testCase := nerdtest.Setup() - tearDown := func() { - defer base.Cmd("rm", "-f", tID+"-1").Run() - defer base.Cmd("rm", "-f", tID+"-2").Run() - } + testCase.Require = nerdtest.Private - tearUp := func() { - base.Cmd("run", "-d", "--name", tID+"-1", "-v", "/anonymous", testutil.CommonImage, "sleep", "infinity").AssertOK() - base.Cmd("exec", tID+"-1", "touch", "/anonymous/foo").AssertOK() - base.Cmd("create", "--name", tID+"-2", testutil.CommonImage, "sleep", "infinity").AssertOK() + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier("1")) + helpers.Anyhow("rm", "-f", data.Identifier("2")) } - tearDown() - t.Cleanup(tearDown) - tearUp() - - base.Cmd("container", "prune", "-f").AssertOK() - // tID-1 is still running, tID-2 is not - base.Cmd("inspect", tID+"-1").AssertOK() - base.Cmd("inspect", tID+"-2").AssertFail() + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "-d", "--name", data.Identifier("1"), "-v", "/anonymous", testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("exec", data.Identifier("1"), "touch", "/anonymous/foo") + helpers.Ensure("create", "--name", data.Identifier("2"), testutil.CommonImage, "sleep", "infinity") + } - // https://github.com/containerd/nerdctl/issues/3134 - base.Cmd("exec", tID+"-1", "ls", "-lA", "/anonymous/foo").AssertOK() + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + helpers.Ensure("container", "prune", "-f") + helpers.Ensure("inspect", data.Identifier("1")) + helpers.Fail("inspect", data.Identifier("2")) + // https://github.com/containerd/nerdctl/issues/3134 + helpers.Ensure("exec", data.Identifier("1"), "ls", "-lA", "/anonymous/foo") + helpers.Ensure("kill", data.Identifier("1")) + helpers.Ensure("container", "prune", "-f") + return helpers.Command("inspect", data.Identifier("1")) + } - base.Cmd("kill", tID+"-1").AssertOK() - base.Cmd("container", "prune", "-f").AssertOK() - base.Cmd("inspect", tID+"-1").AssertFail() + testCase.Expected = test.Expects(1, nil, nil) } From 708f17257e47d01b3dd5584cb88f81ebebfa5194 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 30 Oct 2024 18:23:23 +0100 Subject: [PATCH 0888/1066] Fix test leaking tagged Alpine image Signed-off-by: apostasie --- cmd/nerdctl/builder/builder_builder_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/nerdctl/builder/builder_builder_test.go b/cmd/nerdctl/builder/builder_builder_test.go index 9be5e185faa..b7d86c611b4 100644 --- a/cmd/nerdctl/builder/builder_builder_test.go +++ b/cmd/nerdctl/builder/builder_builder_test.go @@ -86,6 +86,7 @@ CMD ["echo", "nerdctl-builder-debug-test-string"]`, testutil.CommonImage) }, { Description: "WithPull", + NoParallel: true, Setup: func(data test.Data, helpers test.Helpers) { // FIXME: this test should be rewritten to dynamically retrieve the ids, and use images // available on all platforms @@ -106,6 +107,9 @@ CMD ["echo", "nerdctl-builder-debug-test-string"]`, testutil.CommonImage) data.Set("oldImageSha", oldImageSha) data.Set("newImageSha", newImageSha) }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", testutil.AlpineImage) + }, SubTests: []*test.Case{ { Description: "pull false", From 40ddd34e3a180844b37eb00aae83748e2ffa2a10 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 30 Oct 2024 17:44:42 +0100 Subject: [PATCH 0889/1066] Update busybox image (support sleep inf) Signed-off-by: apostasie --- cmd/nerdctl/builder/builder_builder_test.go | 2 +- pkg/testutil/testutil_freebsd.go | 2 +- pkg/testutil/testutil_linux.go | 2 +- pkg/testutil/testutil_windows.go | 13 ++++++------- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/cmd/nerdctl/builder/builder_builder_test.go b/cmd/nerdctl/builder/builder_builder_test.go index 9be5e185faa..a7db6c89bb7 100644 --- a/cmd/nerdctl/builder/builder_builder_test.go +++ b/cmd/nerdctl/builder/builder_builder_test.go @@ -90,7 +90,7 @@ CMD ["echo", "nerdctl-builder-debug-test-string"]`, testutil.CommonImage) // FIXME: this test should be rewritten to dynamically retrieve the ids, and use images // available on all platforms oldImage := testutil.BusyboxImage - oldImageSha := "141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47" + oldImageSha := "7b3ccabffc97de872a30dfd234fd972a66d247c8cfc69b0550f276481852627c" newImage := testutil.AlpineImage newImageSha := "ec14c7992a97fc11425907e908340c6c3d6ff602f5f13d899e6b7027c9b4133a" diff --git a/pkg/testutil/testutil_freebsd.go b/pkg/testutil/testutil_freebsd.go index 026c68a3012..63a79f07a02 100644 --- a/pkg/testutil/testutil_freebsd.go +++ b/pkg/testutil/testutil_freebsd.go @@ -30,7 +30,7 @@ const ( ) var ( - BusyboxImage = mirrorOf("busybox:1.28") + BusyboxImage = "ghcr.io/containerd/busybox:1.36" AlpineImage = mirrorOf("alpine:3.13") NginxAlpineImage = mirrorOf("nginx:1.19-alpine") GolangImage = mirrorOf("golang:1.18") diff --git a/pkg/testutil/testutil_linux.go b/pkg/testutil/testutil_linux.go index 8c0cca4fdc8..0086a1465cb 100644 --- a/pkg/testutil/testutil_linux.go +++ b/pkg/testutil/testutil_linux.go @@ -30,7 +30,7 @@ func mirrorOf(s string) string { } var ( - BusyboxImage = "ghcr.io/containerd/busybox:1.28" + BusyboxImage = "ghcr.io/containerd/busybox:1.36" AlpineImage = mirrorOf("alpine:3.13") NginxAlpineImage = mirrorOf("nginx:1.19-alpine") NginxAlpineIndexHTMLSnippet = "Welcome to nginx!" diff --git a/pkg/testutil/testutil_windows.go b/pkg/testutil/testutil_windows.go index 69934ae1a51..868e5df1cd8 100644 --- a/pkg/testutil/testutil_windows.go +++ b/pkg/testutil/testutil_windows.go @@ -29,23 +29,22 @@ import ( ) const ( - WindowsNano = "gcr.io/k8s-staging-e2e-test-images/busybox:1.29-2" - // CommonImage. // // More work needs to be done to support windows containers in test framework // for the tests that are run now this image (used in k8s upstream testing) meets the needs - // use gcr.io/k8s-staging-e2e-test-images/busybox:1.29-2-windows-amd64-ltsc2022 locally on windows 11 + // use gcr.io/k8s-staging-e2e-test-images/busybox:1.36-1-windows-amd64-ltsc2022 locally on windows 11 // https://github.com/microsoft/Windows-Containers/issues/179 - CommonImage = WindowsNano + BusyboxImage = "gcr.io/k8s-staging-e2e-test-images/busybox:1.36.1-1" + WindowsNano = BusyboxImage + CommonImage = WindowsNano // NOTE(aznashwan): the upstream e2e Nginx test image is actually based on BusyBox. NginxAlpineImage = "registry.k8s.io/e2e-test-images/nginx:1.14-2" NginxAlpineIndexHTMLSnippet = "Welcome to nginx!" - GolangImage = "fixme-test-using-this-image-is-disabled-on-windows" - BusyboxImage = "fixme-test-using-this-image-is-disabled-on-windows" - AlpineImage = "fixme-test-using-this-image-is-disabled-on-windows" + GolangImage = "fixme-test-using-this-image-is-disabled-on-windows" + AlpineImage = "fixme-test-using-this-image-is-disabled-on-windows" // This error string is expected when attempting to connect to a TCP socket // for a service which actively refuses the connection. From 6b3d66151dade17a32b5ac71ff27fd96b173729c Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 20 Oct 2024 13:31:19 -0700 Subject: [PATCH 0890/1066] Container create tests cleanup Signed-off-by: apostasie --- .../container/container_create_linux_test.go | 18 +-- .../container/container_create_test.go | 125 ++++++++++++++++++ .../container_create_windows_test.go | 55 -------- 3 files changed, 127 insertions(+), 71 deletions(-) create mode 100644 cmd/nerdctl/container/container_create_test.go delete mode 100644 cmd/nerdctl/container/container_create_windows_test.go diff --git a/cmd/nerdctl/container/container_create_linux_test.go b/cmd/nerdctl/container/container_create_linux_test.go index 2da8ae92302..546fe02c6bc 100644 --- a/cmd/nerdctl/container/container_create_linux_test.go +++ b/cmd/nerdctl/container/container_create_linux_test.go @@ -36,18 +36,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) -func TestCreate(t *testing.T) { - t.Parallel() - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - - base.Cmd("create", "--name", tID, testutil.CommonImage, "echo", "foo").AssertOK() - defer base.Cmd("rm", "-f", tID).Run() - base.Cmd("ps", "-a").AssertOutContains("Created") - base.Cmd("start", tID).AssertOK() - base.Cmd("logs", tID).AssertOutContains("foo") -} - func TestCreateWithLabel(t *testing.T) { t.Parallel() base := testutil.NewBase(t) @@ -217,8 +205,7 @@ func TestIssue2993(t *testing.T) { h := getAddrHash(defaults.DefaultAddress) dataStore := filepath.Join(dataRoot, h) - // FIXME: update with next tooling iteration to retrieve from the command - namespace := "nerdctl-test" + namespace := string(helpers.Read(nerdtest.Namespace)) containersPath := filepath.Join(dataStore, "containers", namespace) containersDirs, err := os.ReadDir(containersPath) @@ -265,8 +252,7 @@ func TestIssue2993(t *testing.T) { h := getAddrHash(defaults.DefaultAddress) dataStore := filepath.Join(dataRoot, h) - // FIXME: update with next tooling iteration to retrieve from the command - namespace := "nerdctl-test" + namespace := string(helpers.Read(nerdtest.Namespace)) containersPath := filepath.Join(dataStore, "containers", namespace) containersDirs, err := os.ReadDir(containersPath) diff --git a/cmd/nerdctl/container/container_create_test.go b/cmd/nerdctl/container/container_create_test.go new file mode 100644 index 00000000000..12b6a8af519 --- /dev/null +++ b/cmd/nerdctl/container/container_create_test.go @@ -0,0 +1,125 @@ +/* + 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 container + +import ( + "encoding/json" + "testing" + "time" + + "gotest.tools/v3/assert" + + "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestCreate(t *testing.T) { + testCase := nerdtest.Setup() + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("create", "--name", data.Identifier("container"), testutil.CommonImage, "echo", "foo") + data.Set("cID", data.Identifier("container")) + } + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier("container")) + } + + testCase.SubTests = []*test.Case{ + { + Description: "ps -a", + NoParallel: true, + Command: test.Command("ps", "-a"), + // FIXME: this might get a false positive if other tests have created a container + Expected: test.Expects(0, nil, test.Contains("Created")), + }, + { + Description: "start", + NoParallel: true, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("start", data.Get("cID")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "logs", + NoParallel: true, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("logs", data.Get("cID")) + }, + Expected: test.Expects(0, nil, test.Contains("foo")), + }, + } + + testCase.Run(t) +} + +func TestCreateHyperVContainer(t *testing.T) { + testCase := nerdtest.Setup() + + testCase.Require = nerdtest.HyperV + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("create", "--isolation", "hyperv", "--name", data.Identifier("container"), testutil.CommonImage, "echo", "foo") + data.Set("cID", data.Identifier("container")) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier("container")) + } + + testCase.SubTests = []*test.Case{ + { + Description: "ps -a", + NoParallel: true, + Command: test.Command("ps", "-a"), + // FIXME: this might get a false positive if other tests have created a container + Expected: test.Expects(0, nil, test.Contains("Created")), + }, + { + Description: "start", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("start", data.Get("cID")) + ran := false + for i := 0; i < 10 && !ran; i++ { + helpers.Command("container", "inspect", data.Get("cID")). + Run(&test.Expected{ + ExitCode: test.ExitCodeNoCheck, + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Container + err := json.Unmarshal([]byte(stdout), &dc) + if err != nil || len(dc) == 0 { + return + } + assert.Equal(t, len(dc), 1, "Unexpectedly got multiple results\n"+info) + ran = dc[0].State.Status == "exited" + }, + }) + time.Sleep(time.Second) + } + assert.Assert(t, ran, "container did not ran after 10 seconds") + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("logs", data.Get("cID")) + }, + Expected: test.Expects(0, nil, test.Contains("foo")), + }, + } + + testCase.Run(t) +} diff --git a/cmd/nerdctl/container/container_create_windows_test.go b/cmd/nerdctl/container/container_create_windows_test.go deleted file mode 100644 index d80f5bb6d1d..00000000000 --- a/cmd/nerdctl/container/container_create_windows_test.go +++ /dev/null @@ -1,55 +0,0 @@ -/* - 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 container - -import ( - "testing" - "time" - - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestCreateProcessContainer(t *testing.T) { - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - - base.Cmd("create", "--name", tID, testutil.CommonImage, "echo", "foo").AssertOK() - defer base.Cmd("rm", "-f", tID).Run() - base.Cmd("ps", "-a").AssertOutContains("Created") - base.Cmd("start", tID).AssertOK() - base.Cmd("logs", tID).AssertOutContains("foo") -} - -func TestCreateHyperVContainer(t *testing.T) { - base := testutil.NewBase(t) - tID := testutil.Identifier(t) - - if !testutil.HyperVSupported() { - t.Skip("HyperV is not enabled, skipping test") - } - - base.Cmd("create", "--isolation", "hyperv", "--name", tID, testutil.CommonImage, "echo", "foo").AssertOK() - defer base.Cmd("rm", "-f", tID).Run() - base.Cmd("ps", "-a").AssertOutContains("Created") - - base.Cmd("start", tID).AssertOK() - // hyperv containers take a few seconds to fire up, the test would fail without the sleep - // EnsureContainerStarted does not work - time.Sleep(10 * time.Second) - - base.Cmd("logs", tID).AssertOutContains("foo") -} From 8f9eccd946d18c6faa5fd5f3988966458bf5131d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:41:13 +0000 Subject: [PATCH 0891/1066] build(deps): bump github.com/Microsoft/hcsshim from 0.12.8 to 0.12.9 Bumps [github.com/Microsoft/hcsshim](https://github.com/Microsoft/hcsshim) from 0.12.8 to 0.12.9. - [Release notes](https://github.com/Microsoft/hcsshim/releases) - [Commits](https://github.com/Microsoft/hcsshim/compare/v0.12.8...v0.12.9) --- updated-dependencies: - dependency-name: github.com/Microsoft/hcsshim dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 3 +-- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 8fc5274b9b9..30619fbf332 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ go 1.22.0 require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 - github.com/Microsoft/hcsshim v0.12.8 + github.com/Microsoft/hcsshim v0.12.9 github.com/compose-spec/compose-go/v2 v2.4.1 github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.3 @@ -81,7 +81,6 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/cilium/ebpf v0.16.0 // indirect - github.com/containerd/containerd v1.7.23 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/go-runc v1.1.0 // indirect github.com/containerd/plugin v0.1.0 // indirect diff --git a/go.sum b/go.sum index a2078cf01b3..207d8f5f7e5 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+ github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= 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.12.8 h1:BtDWYlFMcWhorrvSSo2M7z0csPdw6t7no/C3FsSvqiI= -github.com/Microsoft/hcsshim v0.12.8/go.mod h1:cibQ4BqhJ32FXDwPdQhKhwrwophnh3FuT4nwQZF907w= +github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg= +github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= @@ -31,8 +31,6 @@ github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGD github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= 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.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ= -github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw= github.com/containerd/containerd/api v1.8.0-rc.4 h1:Z650GHP0OxsoTwwii5U2hyTt7eCRQvvDnRM7pEH/DE0= github.com/containerd/containerd/api v1.8.0-rc.4/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/v2 v2.0.0-rc.6 h1:uIUmoiXH770KCkTzzqksSpQg7JZ4tC0eM2qXm5EAuwI= From 20987449b32039576f74f7a221e8fc0684fd8894 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:01:23 +0000 Subject: [PATCH 0892/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.4.1 to 2.4.2. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.4.1...v2.4.2) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 30619fbf332..9ee2178d9cf 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.9 - github.com/compose-spec/compose-go/v2 v2.4.1 + github.com/compose-spec/compose-go/v2 v2.4.2 github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index 207d8f5f7e5..c88be4bf45e 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.4.1 h1:tEg6Qn/9LZnKg42fZlFmxN4lxSqnCvsiG5TXnxzvI4c= -github.com/compose-spec/compose-go/v2 v2.4.1/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.4.2 h1:RaZv+ZKZVNmxi4Cww1EKiJRLSZLiqVxIqhLUdH92dz4= +github.com/compose-spec/compose-go/v2 v2.4.2/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= From 54196647c209de2c096f8b72999a4f5a81327b70 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 31 Oct 2024 12:14:00 +0100 Subject: [PATCH 0893/1066] Remove fixed-bug workaround Fixed in https://github.com/containerd/nerdctl/pull/3618 Signed-off-by: apostasie --- cmd/nerdctl/container/container_commit_test.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/cmd/nerdctl/container/container_commit_test.go b/cmd/nerdctl/container/container_commit_test.go index 144180f79c2..cc3f1f45e0e 100644 --- a/cmd/nerdctl/container/container_commit_test.go +++ b/cmd/nerdctl/container/container_commit_test.go @@ -36,14 +36,7 @@ func TestCommit(t *testing.T) { helpers.Anyhow("rmi", "-f", data.Identifier()) }, Setup: func(data test.Data, helpers test.Helpers) { - // FIXME: short of pulling first, docker will fail to start the container. - // Debugging shows container exited immediately. Nothing in the container logs. Not much in journalctl. - // It is not clear what is happening. - if nerdtest.IsDocker() { - helpers.Ensure("pull", testutil.CommonImage) - } helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") - nerdtest.EnsureContainerStarted(helpers, data.Identifier()) helpers.Ensure("exec", data.Identifier(), "sh", "-euxc", `echo hello-test-commit > /foo`) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { From 4760ee9359752a570020a6ec79e43d344de47b46 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 31 Oct 2024 12:14:45 +0100 Subject: [PATCH 0894/1066] Rewrite container_top tests Signed-off-by: apostasie --- cmd/nerdctl/container/container_top_test.go | 92 +++++++++++++++++++ .../container/container_top_unix_test.go | 43 --------- .../container/container_top_windows_test.go | 47 ---------- 3 files changed, 92 insertions(+), 90 deletions(-) create mode 100644 cmd/nerdctl/container/container_top_test.go delete mode 100644 cmd/nerdctl/container/container_top_unix_test.go delete mode 100644 cmd/nerdctl/container/container_top_windows_test.go diff --git a/cmd/nerdctl/container/container_top_test.go b/cmd/nerdctl/container/container_top_test.go new file mode 100644 index 00000000000..5f7a6e0a4b5 --- /dev/null +++ b/cmd/nerdctl/container/container_top_test.go @@ -0,0 +1,92 @@ +/* + 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 container + +import ( + "runtime" + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestTop(t *testing.T) { + testCase := nerdtest.Setup() + + //more details https://github.com/containerd/nerdctl/pull/223#issuecomment-851395178 + if runtime.GOOS == "linux" { + testCase.Require = nerdtest.CgroupsAccessible + } + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + // FIXME: busybox 1.36 on windows still appears to not support sleep inf. Unclear why. + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "10") + data.Set("cID", data.Identifier()) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + } + + testCase.SubTests = []*test.Case{ + { + Description: "with o pid,user,cmd", + // Docker does not support top -o + Require: test.Not(nerdtest.Docker), + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("top", data.Get("cID"), "-o", "pid,user,cmd") + }, + + Expected: test.Expects(0, nil, nil), + }, + { + Description: "simple", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("top", data.Get("cID")) + }, + + Expected: test.Expects(0, nil, nil), + }, + } + + testCase.Run(t) +} + +func TestTopHyperVContainer(t *testing.T) { + + testCase := nerdtest.Setup() + + testCase.Require = nerdtest.HyperV + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + // FIXME: busybox 1.36 on windows still appears to not support sleep inf. Unclear why. + helpers.Ensure("run", "--isolation", "hyperv", "-d", "--name", data.Identifier("container"), testutil.CommonImage, "sleep", "10") + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier("container")) + } + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("top", data.Identifier("container")) + } + + testCase.Expected = test.Expects(0, nil, nil) + + testCase.Run(t) +} diff --git a/cmd/nerdctl/container/container_top_unix_test.go b/cmd/nerdctl/container/container_top_unix_test.go deleted file mode 100644 index d68d42302ee..00000000000 --- a/cmd/nerdctl/container/container_top_unix_test.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build unix - -/* - 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 container - -import ( - "testing" - - "github.com/containerd/nerdctl/v2/pkg/infoutil" - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestTop(t *testing.T) { - t.Parallel() - //more details https://github.com/containerd/nerdctl/pull/223#issuecomment-851395178 - if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { - t.Skip("test skipped for rootless containers on cgroup v1") - } - testContainerName := testutil.Identifier(t) - - base := testutil.NewBase(t) - defer base.Cmd("rm", "-f", testContainerName).Run() - - base.Cmd("run", "-d", "--name", testContainerName, testutil.AlpineImage, "sleep", "5").AssertOK() - base.Cmd("top", testContainerName, "-o", "pid,user,cmd").AssertOK() - -} diff --git a/cmd/nerdctl/container/container_top_windows_test.go b/cmd/nerdctl/container/container_top_windows_test.go deleted file mode 100644 index 690e52d50f4..00000000000 --- a/cmd/nerdctl/container/container_top_windows_test.go +++ /dev/null @@ -1,47 +0,0 @@ -/* - 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 container - -import ( - "testing" - - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestTopProcessContainer(t *testing.T) { - testContainerName := testutil.Identifier(t) - - base := testutil.NewBase(t) - defer base.Cmd("rm", "-f", testContainerName).Run() - - base.Cmd("run", "-d", "--name", testContainerName, testutil.WindowsNano, "sleep", "5").AssertOK() - base.Cmd("top", testContainerName).AssertOK() -} - -func TestTopHyperVContainer(t *testing.T) { - if !testutil.HyperVSupported() { - t.Skip("HyperV is not enabled, skipping test") - } - - testContainerName := testutil.Identifier(t) - - base := testutil.NewBase(t) - defer base.Cmd("rm", "-f", testContainerName).Run() - - base.Cmd("run", "--isolation", "hyperv", "-d", "--name", testContainerName, testutil.WindowsNano, "sleep", "5").AssertOK() - base.Cmd("top", testContainerName).AssertOK() -} From 75fdc4994f1a738ccdd23202dfce3f34b49984ef Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 31 Oct 2024 20:10:28 +0100 Subject: [PATCH 0895/1066] Fix convert unable to find image Signed-off-by: apostasie --- pkg/cmd/image/convert.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/image/convert.go b/pkg/cmd/image/convert.go index fd6d86f1a52..71a2cca4c54 100644 --- a/pkg/cmd/image/convert.go +++ b/pkg/cmd/image/convert.go @@ -76,7 +76,7 @@ func Convert(ctx context.Context, client *containerd.Client, srcRawRef, targetRa convertOpts = append(convertOpts, converter.WithPlatform(platMC)) // Ensure all the layers are here: https://github.com/containerd/nerdctl/issues/3425 - err = EnsureAllContent(ctx, client, srcRawRef, options.GOptions) + err = EnsureAllContent(ctx, client, srcRef, options.GOptions) if err != nil { return err } From 5862baf7399f6129d0230d7bd9f4856967c6a8df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 22:54:19 +0000 Subject: [PATCH 0896/1066] build(deps): bump github.com/fsnotify/fsnotify from 1.7.0 to 1.8.0 Bumps [github.com/fsnotify/fsnotify](https://github.com/fsnotify/fsnotify) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/fsnotify/fsnotify/releases) - [Changelog](https://github.com/fsnotify/fsnotify/blob/main/CHANGELOG.md) - [Commits](https://github.com/fsnotify/fsnotify/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: github.com/fsnotify/fsnotify dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9ee2178d9cf..1d41153797b 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( github.com/fahedouch/go-logrotate v0.2.1 github.com/fatih/color v1.18.0 github.com/fluent/fluent-logger-golang v1.9.0 - github.com/fsnotify/fsnotify v1.7.0 + github.com/fsnotify/fsnotify v1.8.0 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/ipfs/go-cid v0.4.1 github.com/klauspost/compress v1.17.11 diff --git a/go.sum b/go.sum index c88be4bf45e..d11537c752a 100644 --- a/go.sum +++ b/go.sum @@ -112,8 +112,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= From 04ec4a3c4db182444f0e165accb16fd6d447412e Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 20 Oct 2024 19:20:53 -0700 Subject: [PATCH 0897/1066] Rewrite container_stats tests Signed-off-by: apostasie --- .../container/container_stats_linux_test.go | 75 ------------ cmd/nerdctl/container/container_stats_test.go | 108 ++++++++++++++++++ 2 files changed, 108 insertions(+), 75 deletions(-) delete mode 100644 cmd/nerdctl/container/container_stats_linux_test.go create mode 100644 cmd/nerdctl/container/container_stats_test.go diff --git a/cmd/nerdctl/container/container_stats_linux_test.go b/cmd/nerdctl/container/container_stats_linux_test.go deleted file mode 100644 index 42b2861aec4..00000000000 --- a/cmd/nerdctl/container/container_stats_linux_test.go +++ /dev/null @@ -1,75 +0,0 @@ -/* - 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 container - -import ( - "fmt" - "testing" - - "github.com/containerd/nerdctl/v2/pkg/infoutil" - "github.com/containerd/nerdctl/v2/pkg/rootlessutil" - "github.com/containerd/nerdctl/v2/pkg/testutil" -) - -func TestStats(t *testing.T) { - // this comment is for `nerdctl ps` but it also valid for `nerdctl stats` : - // https://github.com/containerd/nerdctl/pull/223#issuecomment-851395178 - if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { - t.Skip("test skipped for rootless containers on cgroup v1") - } - testContainerName := testutil.Identifier(t)[:12] - exitedTestContainerName := fmt.Sprintf("%s-exited", testContainerName) - - base := testutil.NewBase(t) - defer base.Cmd("rm", "-f", testContainerName).Run() - defer base.Cmd("rm", "-f", exitedTestContainerName).Run() - base.Cmd("run", "--name", exitedTestContainerName, testutil.AlpineImage, "echo", "'exited'").AssertOK() - - base.Cmd("run", "-d", "--name", testContainerName, testutil.AlpineImage, "sleep", "10").AssertOK() - base.Cmd("stats", "--no-stream").AssertOutContains(testContainerName) - base.Cmd("stats", "--no-stream", testContainerName).AssertOK() - base.Cmd("container", "stats", "--no-stream").AssertOutContains(testContainerName) - base.Cmd("container", "stats", "--no-stream", testContainerName).AssertOK() -} - -func TestStatsMemoryLimitNotSet(t *testing.T) { - if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { - t.Skip("test skipped for rootless containers on cgroup v1") - } - testContainerName := testutil.Identifier(t)[:12] - - base := testutil.NewBase(t) - defer base.Cmd("rm", "-f", testContainerName).Run() - - base.Cmd("run", "-d", "--name", testContainerName, testutil.AlpineImage, "sleep", "10").AssertOK() - base.Cmd("stats", "--no-stream").AssertOutNotContains("16EiB") - base.Cmd("stats", "--no-stream", testContainerName).AssertOK() -} - -func TestStatsMemoryLimitSet(t *testing.T) { - if rootlessutil.IsRootless() && infoutil.CgroupsVersion() == "1" { - t.Skip("test skipped for rootless containers on cgroup v1") - } - testContainerName := testutil.Identifier(t)[:12] - - base := testutil.NewBase(t) - defer base.Cmd("rm", "-f", testContainerName).Run() - - base.Cmd("run", "-d", "--name", testContainerName, "--memory", "1g", testutil.AlpineImage, "sleep", "10").AssertOK() - base.Cmd("stats", "--no-stream").AssertOutContains("1GiB") - base.Cmd("stats", "--no-stream", testContainerName).AssertOK() -} diff --git a/cmd/nerdctl/container/container_stats_test.go b/cmd/nerdctl/container/container_stats_test.go new file mode 100644 index 00000000000..e3c9b3a8c2c --- /dev/null +++ b/cmd/nerdctl/container/container_stats_test.go @@ -0,0 +1,108 @@ +/* + 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 container + +import ( + "runtime" + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" +) + +func TestStats(t *testing.T) { + testCase := nerdtest.Setup() + + // FIXME: does not seem to work on windows + testCase.Require = test.Not(test.Windows) + + if runtime.GOOS == "linux" { + // this comment is for `nerdctl ps` but it also valid for `nerdctl stats` : + // https://github.com/containerd/nerdctl/pull/223#issuecomment-851395178 + testCase.Require = test.Require( + testCase.Require, + nerdtest.CgroupsAccessible, + ) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier("container")) + helpers.Anyhow("rm", "-f", data.Identifier("memlimited")) + helpers.Anyhow("rm", "-f", data.Identifier("exited")) + } + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "-d", "--name", data.Identifier("container"), testutil.CommonImage, "sleep", "10") + helpers.Ensure("run", "-d", "--name", data.Identifier("memlimited"), "--memory", "1g", testutil.CommonImage, "sleep", "10") + helpers.Ensure("run", "--name", data.Identifier("exited"), testutil.CommonImage, "echo", "'exited'") + data.Set("id", data.Identifier("container")) + } + + testCase.SubTests = []*test.Case{ + { + Description: "stats", + Command: test.Command("stats", "--no-stream", "--no-trunc"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("id")), + } + }, + }, + { + Description: "container stats", + Command: test.Command("container", "stats", "--no-stream", "--no-trunc"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(data.Get("id")), + } + }, + }, + { + Description: "stats ID", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("stats", "--no-stream", data.Get("id")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "container stats ID", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("container", "stats", "--no-stream", data.Get("id")) + }, + Expected: test.Expects(0, nil, nil), + }, + { + Description: "no mem limit set", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("stats", "--no-stream") + }, + // https://github.com/containerd/nerdctl/issues/1240 + // nerdctl used to print UINT64_MAX as the memory limit, so, ensure it does no more + Expected: test.Expects(0, nil, test.DoesNotContain("16EiB")), + }, + { + Description: "mem limit set", + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("stats", "--no-stream") + }, + Expected: test.Expects(0, nil, test.Contains("1GiB")), + }, + } + + testCase.Run(t) +} From bdc00760e500e9c515970a36f2e0e7c6f869a8be Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 1 Nov 2024 12:24:32 +0100 Subject: [PATCH 0898/1066] Reduce calls to data.Identifier() Signed-off-by: apostasie --- cmd/nerdctl/completion/completion_test.go | 12 ++++--- .../container/container_commit_linux_test.go | 9 +++--- .../container/container_commit_test.go | 32 +++++++++++-------- .../container/container_remove_test.go | 7 ++-- cmd/nerdctl/image/image_load_test.go | 19 ++++++----- cmd/nerdctl/image/image_prune_test.go | 22 +++++++------ cmd/nerdctl/issues/issues_linux_test.go | 15 +++++---- .../network/network_create_linux_test.go | 5 +-- cmd/nerdctl/network/network_inspect_test.go | 5 +-- .../network/network_prune_linux_test.go | 5 +-- .../network/network_remove_linux_test.go | 7 ++-- 11 files changed, 81 insertions(+), 57 deletions(-) diff --git a/cmd/nerdctl/completion/completion_test.go b/cmd/nerdctl/completion/completion_test.go index 8b2626ee38c..84ba1377153 100644 --- a/cmd/nerdctl/completion/completion_test.go +++ b/cmd/nerdctl/completion/completion_test.go @@ -34,14 +34,16 @@ func TestCompletion(t *testing.T) { testCase := &test.Case{ Require: test.Not(nerdtest.Docker), Setup: func(data test.Data, helpers test.Helpers) { + identifier := data.Identifier() helpers.Ensure("pull", "--quiet", testutil.CommonImage) - helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("volume", "create", data.Identifier()) - data.Set("identifier", data.Identifier()) + helpers.Ensure("network", "create", identifier) + helpers.Ensure("volume", "create", identifier) + data.Set("identifier", identifier) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("network", "rm", data.Identifier()) - helpers.Anyhow("volume", "rm", data.Identifier()) + identifier := data.Identifier() + helpers.Anyhow("network", "rm", identifier) + helpers.Anyhow("volume", "rm", identifier) }, SubTests: []*test.Case{ { diff --git a/cmd/nerdctl/container/container_commit_linux_test.go b/cmd/nerdctl/container/container_commit_linux_test.go index 710e37aeef4..b55c2f14daf 100644 --- a/cmd/nerdctl/container/container_commit_linux_test.go +++ b/cmd/nerdctl/container/container_commit_linux_test.go @@ -31,14 +31,15 @@ func TestKubeCommitSave(t *testing.T) { testCase.Require = nerdtest.OnlyKubernetes testCase.Setup = func(data test.Data, helpers test.Helpers) { + identifier := data.Identifier() containerID := "" // NOTE: kubectl namespaces are not the same as containerd namespaces. // We still want kube test objects segregated in their own Kube API namespace. nerdtest.KubeCtlCommand(helpers, "create", "namespace", "nerdctl-test-k8s").Run(&test.Expected{}) - nerdtest.KubeCtlCommand(helpers, "run", "--image", testutil.CommonImage, data.Identifier(), "--", "sleep", "Inf").Run(&test.Expected{}) - nerdtest.KubeCtlCommand(helpers, "wait", "pod", data.Identifier(), "--for=condition=ready", "--timeout=1m").Run(&test.Expected{}) - nerdtest.KubeCtlCommand(helpers, "exec", data.Identifier(), "--", "mkdir", "-p", "/tmp/whatever").Run(&test.Expected{}) - nerdtest.KubeCtlCommand(helpers, "get", "pods", data.Identifier(), "-o", "jsonpath={ .status.containerStatuses[0].containerID }").Run(&test.Expected{ + nerdtest.KubeCtlCommand(helpers, "run", "--image", testutil.CommonImage, identifier, "--", "sleep", "Inf").Run(&test.Expected{}) + nerdtest.KubeCtlCommand(helpers, "wait", "pod", identifier, "--for=condition=ready", "--timeout=1m").Run(&test.Expected{}) + nerdtest.KubeCtlCommand(helpers, "exec", identifier, "--", "mkdir", "-p", "/tmp/whatever").Run(&test.Expected{}) + nerdtest.KubeCtlCommand(helpers, "get", "pods", identifier, "-o", "jsonpath={ .status.containerStatuses[0].containerID }").Run(&test.Expected{ Output: func(stdout string, info string, t *testing.T) { containerID = strings.TrimPrefix(stdout, "containerd://") }, diff --git a/cmd/nerdctl/container/container_commit_test.go b/cmd/nerdctl/container/container_commit_test.go index cc3f1f45e0e..50b4d9a8706 100644 --- a/cmd/nerdctl/container/container_commit_test.go +++ b/cmd/nerdctl/container/container_commit_test.go @@ -32,21 +32,24 @@ func TestCommit(t *testing.T) { Description: "with pause", Require: nerdtest.CGroup, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("rmi", "-f", data.Identifier()) + identifier := data.Identifier() + helpers.Anyhow("rm", "-f", identifier) + helpers.Anyhow("rmi", "-f", identifier) }, Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") - helpers.Ensure("exec", data.Identifier(), "sh", "-euxc", `echo hello-test-commit > /foo`) + identifier := data.Identifier() + helpers.Ensure("run", "-d", "--name", identifier, testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("exec", identifier, "sh", "-euxc", `echo hello-test-commit > /foo`) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + identifier := data.Identifier() helpers.Ensure( "commit", "-c", `CMD ["/foo"]`, "-c", `ENTRYPOINT ["cat"]`, "--pause=true", - data.Identifier(), data.Identifier()) - return helpers.Command("run", "--rm", data.Identifier()) + identifier, identifier) + return helpers.Command("run", "--rm", identifier) }, Expected: test.Expects(0, nil, test.Equals("hello-test-commit\n")), }, @@ -54,26 +57,29 @@ func TestCommit(t *testing.T) { Description: "no pause", Require: test.Not(test.Windows), Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("rmi", "-f", data.Identifier()) + identifier := data.Identifier() + helpers.Anyhow("rm", "-f", identifier) + helpers.Anyhow("rmi", "-f", identifier) }, Setup: func(data test.Data, helpers test.Helpers) { + identifier := data.Identifier() // See note above about docker failing. if nerdtest.IsDocker() { helpers.Ensure("pull", testutil.CommonImage) } - helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") - nerdtest.EnsureContainerStarted(helpers, data.Identifier()) - helpers.Ensure("exec", data.Identifier(), "sh", "-euxc", `echo hello-test-commit > /foo`) + helpers.Ensure("run", "-d", "--name", identifier, testutil.CommonImage, "sleep", "infinity") + nerdtest.EnsureContainerStarted(helpers, identifier) + helpers.Ensure("exec", identifier, "sh", "-euxc", `echo hello-test-commit > /foo`) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + identifier := data.Identifier() helpers.Ensure( "commit", "-c", `CMD ["/foo"]`, "-c", `ENTRYPOINT ["cat"]`, "--pause=false", - data.Identifier(), data.Identifier()) - return helpers.Command("run", "--rm", data.Identifier()) + identifier, identifier) + return helpers.Command("run", "--rm", identifier) }, Expected: test.Expects(0, nil, test.Equals("hello-test-commit\n")), }, diff --git a/cmd/nerdctl/container/container_remove_test.go b/cmd/nerdctl/container/container_remove_test.go index 89028281060..11340d7930a 100644 --- a/cmd/nerdctl/container/container_remove_test.go +++ b/cmd/nerdctl/container/container_remove_test.go @@ -36,13 +36,14 @@ func TestRemoveContainer(t *testing.T) { } testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { - helpers.Fail("rm", data.Identifier()) + containerID := data.Identifier() + helpers.Fail("rm", containerID) // FIXME: should (re-)evaluate this // `kill` seems to return before the container actually stops - helpers.Ensure("stop", data.Identifier()) + helpers.Ensure("stop", containerID) - return helpers.Command("rm", data.Identifier()) + return helpers.Command("rm", containerID) } testCase.Expected = test.Expects(0, nil, nil) diff --git a/cmd/nerdctl/image/image_load_test.go b/cmd/nerdctl/image/image_load_test.go index 23af5415dc6..4a0e170fa3e 100644 --- a/cmd/nerdctl/image/image_load_test.go +++ b/cmd/nerdctl/image/image_load_test.go @@ -37,10 +37,11 @@ func TestLoadStdinFromPipe(t *testing.T) { Description: "TestLoadStdinFromPipe", Require: test.Linux, Setup: func(data test.Data, helpers test.Helpers) { + identifier := data.Identifier() helpers.Ensure("pull", "--quiet", testutil.CommonImage) - helpers.Ensure("tag", testutil.CommonImage, data.Identifier()) - helpers.Ensure("save", data.Identifier(), "-o", filepath.Join(data.TempDir(), "common.tar")) - helpers.Ensure("rmi", "-f", data.Identifier()) + helpers.Ensure("tag", testutil.CommonImage, identifier) + helpers.Ensure("save", identifier, "-o", filepath.Join(data.TempDir(), "common.tar")) + helpers.Ensure("rmi", "-f", identifier) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rmi", "-f", data.Identifier()) @@ -53,11 +54,12 @@ func TestLoadStdinFromPipe(t *testing.T) { return cmd }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + identifier := data.Identifier() return &test.Expected{ Output: test.All( - test.Contains(fmt.Sprintf("Loaded image: %s:latest", data.Identifier())), + test.Contains(fmt.Sprintf("Loaded image: %s:latest", identifier)), func(stdout string, info string, t *testing.T) { - assert.Assert(t, strings.Contains(helpers.Capture("images"), data.Identifier())) + assert.Assert(t, strings.Contains(helpers.Capture("images"), identifier)) }, ), } @@ -86,10 +88,11 @@ func TestLoadQuiet(t *testing.T) { testCase := &test.Case{ Description: "TestLoadQuiet", Setup: func(data test.Data, helpers test.Helpers) { + identifier := data.Identifier() helpers.Ensure("pull", testutil.CommonImage) - helpers.Ensure("tag", testutil.CommonImage, data.Identifier()) - helpers.Ensure("save", data.Identifier(), "-o", filepath.Join(data.TempDir(), "common.tar")) - helpers.Ensure("rmi", "-f", data.Identifier()) + helpers.Ensure("tag", testutil.CommonImage, identifier) + helpers.Ensure("save", identifier, "-o", filepath.Join(data.TempDir(), "common.tar")) + helpers.Ensure("rmi", "-f", identifier) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rmi", "-f", data.Identifier()) diff --git a/cmd/nerdctl/image/image_prune_test.go b/cmd/nerdctl/image/image_prune_test.go index e3c66b8bf10..c4dae8b975e 100644 --- a/cmd/nerdctl/image/image_prune_test.go +++ b/cmd/nerdctl/image/image_prune_test.go @@ -56,6 +56,7 @@ func TestImagePrune(t *testing.T) { helpers.Anyhow("rmi", "-f", data.Identifier()) }, Setup: func(data test.Data, helpers test.Helpers) { + identifier := data.Identifier() dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune"] `, testutil.CommonImage) @@ -64,22 +65,23 @@ func TestImagePrune(t *testing.T) { helpers.Ensure("build", buildCtx) // After we rebuild with tag, docker will no longer show the version from above // Swapping order does not change anything. - helpers.Ensure("build", "-t", data.Identifier(), buildCtx) + helpers.Ensure("build", "-t", identifier, buildCtx) imgList := helpers.Capture("images") assert.Assert(t, strings.Contains(imgList, ""), "Missing ") - assert.Assert(t, strings.Contains(imgList, data.Identifier()), "Missing "+data.Identifier()) + assert.Assert(t, strings.Contains(imgList, identifier), "Missing "+identifier) }, Command: test.Command("image", "prune", "--force"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + identifier := data.Identifier() return &test.Expected{ Output: test.All( func(stdout string, info string, t *testing.T) { - assert.Assert(t, !strings.Contains(stdout, data.Identifier()), info) + assert.Assert(t, !strings.Contains(stdout, identifier), info) }, func(stdout string, info string, t *testing.T) { imgList := helpers.Capture("images") assert.Assert(t, !strings.Contains(imgList, ""), imgList) - assert.Assert(t, strings.Contains(imgList, data.Identifier()), info) + assert.Assert(t, strings.Contains(imgList, identifier), info) }, ), } @@ -95,21 +97,23 @@ func TestImagePrune(t *testing.T) { // Cannot use a custom namespace with buildkitd right now, so, no parallel it is NoParallel: true, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rmi", "-f", data.Identifier()) - helpers.Anyhow("rm", "-f", data.Identifier()) + identifier := data.Identifier() + helpers.Anyhow("rmi", "-f", identifier) + helpers.Anyhow("rm", "-f", identifier) }, Setup: func(data test.Data, helpers test.Helpers) { + identifier := data.Identifier() dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-test-image-prune"] `, testutil.CommonImage) buildCtx := testhelpers.CreateBuildContext(t, dockerfile) helpers.Ensure("build", buildCtx) - helpers.Ensure("build", "-t", data.Identifier(), buildCtx) + helpers.Ensure("build", "-t", identifier, buildCtx) imgList := helpers.Capture("images") assert.Assert(t, strings.Contains(imgList, ""), "Missing ") - assert.Assert(t, strings.Contains(imgList, data.Identifier()), "Missing "+data.Identifier()) - helpers.Ensure("run", "--name", data.Identifier(), data.Identifier()) + assert.Assert(t, strings.Contains(imgList, identifier), "Missing "+identifier) + helpers.Ensure("run", "--name", identifier, identifier) }, Command: test.Command("image", "prune", "--force", "--all"), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { diff --git a/cmd/nerdctl/issues/issues_linux_test.go b/cmd/nerdctl/issues/issues_linux_test.go index a371aaa6c0f..3f9e89ffd89 100644 --- a/cmd/nerdctl/issues/issues_linux_test.go +++ b/cmd/nerdctl/issues/issues_linux_test.go @@ -49,15 +49,17 @@ func TestIssue3425(t *testing.T) { Description: "with tag", Require: nerdtest.Private, Setup: func(data test.Data, helpers test.Helpers) { + identifier := data.Identifier() helpers.Ensure("image", "pull", testutil.CommonImage) - helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage) + helpers.Ensure("run", "-d", "--name", identifier, testutil.CommonImage) helpers.Ensure("image", "rm", "-f", testutil.CommonImage) helpers.Ensure("image", "pull", testutil.CommonImage) - helpers.Ensure("tag", testutil.CommonImage, fmt.Sprintf("localhost:%d/%s", reg.Port, data.Identifier())) + helpers.Ensure("tag", testutil.CommonImage, fmt.Sprintf("localhost:%d/%s", reg.Port, identifier)) }, Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("rm", "-f", data.Identifier()) - helpers.Anyhow("rmi", "-f", fmt.Sprintf("localhost:%d/%s", reg.Port, data.Identifier())) + identifier := data.Identifier() + helpers.Anyhow("rm", "-f", identifier) + helpers.Anyhow("rmi", "-f", fmt.Sprintf("localhost:%d/%s", reg.Port, identifier)) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("push", fmt.Sprintf("localhost:%d/%s", reg.Port, data.Identifier())) @@ -68,11 +70,12 @@ func TestIssue3425(t *testing.T) { Description: "with commit", Require: nerdtest.Private, Setup: func(data test.Data, helpers test.Helpers) { + identifier := data.Identifier() helpers.Ensure("image", "pull", testutil.CommonImage) - helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "touch", "/something") + helpers.Ensure("run", "-d", "--name", identifier, testutil.CommonImage, "touch", "/something") helpers.Ensure("image", "rm", "-f", testutil.CommonImage) helpers.Ensure("image", "pull", testutil.CommonImage) - helpers.Ensure("commit", data.Identifier(), fmt.Sprintf("localhost:%d/%s", reg.Port, data.Identifier())) + helpers.Ensure("commit", identifier, fmt.Sprintf("localhost:%d/%s", reg.Port, identifier)) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) diff --git a/cmd/nerdctl/network/network_create_linux_test.go b/cmd/nerdctl/network/network_create_linux_test.go index 596375f33db..f42c312e699 100644 --- a/cmd/nerdctl/network/network_create_linux_test.go +++ b/cmd/nerdctl/network/network_create_linux_test.go @@ -36,8 +36,9 @@ func TestNetworkCreate(t *testing.T) { { Description: "vanilla", Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - netw := nerdtest.InspectNetwork(helpers, data.Identifier()) + identifier := data.Identifier() + helpers.Ensure("network", "create", identifier) + netw := nerdtest.InspectNetwork(helpers, identifier) assert.Equal(t, len(netw.IPAM.Config), 1) data.Set("subnet", netw.IPAM.Config[0].Subnet) diff --git a/cmd/nerdctl/network/network_inspect_test.go b/cmd/nerdctl/network/network_inspect_test.go index 64d5631e2bf..f7ce5356dca 100644 --- a/cmd/nerdctl/network/network_inspect_test.go +++ b/cmd/nerdctl/network/network_inspect_test.go @@ -200,8 +200,9 @@ func TestNetworkInspect(t *testing.T) { Description: "with namespace", Require: test.Not(nerdtest.Docker), Cleanup: func(data test.Data, helpers test.Helpers) { - helpers.Anyhow("network", "rm", data.Identifier()) - helpers.Anyhow("namespace", "remove", data.Identifier()) + identifier := data.Identifier() + helpers.Anyhow("network", "rm", identifier) + helpers.Anyhow("namespace", "remove", identifier) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("network", "create", data.Identifier()) diff --git a/cmd/nerdctl/network/network_prune_linux_test.go b/cmd/nerdctl/network/network_prune_linux_test.go index 62f6417c736..b4b0ec6bbae 100644 --- a/cmd/nerdctl/network/network_prune_linux_test.go +++ b/cmd/nerdctl/network/network_prune_linux_test.go @@ -34,8 +34,9 @@ func TestNetworkPrune(t *testing.T) { Description: "Prune does not collect started container network", NoParallel: true, Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) + identifier := data.Identifier() + helpers.Ensure("network", "create", identifier) + helpers.Ensure("run", "-d", "--net", identifier, "--name", identifier, testutil.NginxAlpineImage) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) diff --git a/cmd/nerdctl/network/network_remove_linux_test.go b/cmd/nerdctl/network/network_remove_linux_test.go index f890cf13ddb..5d10c9f0f61 100644 --- a/cmd/nerdctl/network/network_remove_linux_test.go +++ b/cmd/nerdctl/network/network_remove_linux_test.go @@ -37,9 +37,10 @@ func TestNetworkRemove(t *testing.T) { { Description: "Simple network remove", Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("network", "create", data.Identifier()) - data.Set("netID", nerdtest.InspectNetwork(helpers, data.Identifier()).ID) - helpers.Ensure("run", "--rm", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage) + identifier := data.Identifier() + helpers.Ensure("network", "create", identifier) + data.Set("netID", nerdtest.InspectNetwork(helpers, identifier).ID) + helpers.Ensure("run", "--rm", "--net", identifier, "--name", identifier, testutil.CommonImage) // Verity the network is here _, err := netlink.LinkByName("br-" + data.Get("netID")[:12]) assert.NilError(t, err, "failed to find network br-"+data.Get("netID")[:12], "%v") From 7b8edba60090b296f2d0f641f8d331d3b7c34baa Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 1 Nov 2024 13:20:34 +0100 Subject: [PATCH 0899/1066] Remove leftover workaround for fixed bug Signed-off-by: apostasie --- cmd/nerdctl/container/container_commit_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmd/nerdctl/container/container_commit_test.go b/cmd/nerdctl/container/container_commit_test.go index 50b4d9a8706..c349b728b3c 100644 --- a/cmd/nerdctl/container/container_commit_test.go +++ b/cmd/nerdctl/container/container_commit_test.go @@ -63,10 +63,6 @@ func TestCommit(t *testing.T) { }, Setup: func(data test.Data, helpers test.Helpers) { identifier := data.Identifier() - // See note above about docker failing. - if nerdtest.IsDocker() { - helpers.Ensure("pull", testutil.CommonImage) - } helpers.Ensure("run", "-d", "--name", identifier, testutil.CommonImage, "sleep", "infinity") nerdtest.EnsureContainerStarted(helpers, identifier) helpers.Ensure("exec", identifier, "sh", "-euxc", `echo hello-test-commit > /foo`) From bfc8e0b961e3362d95a508f56c3a406b23d53da7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 1 Nov 2024 14:57:28 +0100 Subject: [PATCH 0900/1066] Add Infinity constant to enable windows testing compat Signed-off-by: apostasie --- .../container/container_commit_linux_test.go | 2 +- cmd/nerdctl/container/container_commit_test.go | 4 ++-- .../container/container_create_linux_test.go | 6 +++--- .../container/container_exec_linux_test.go | 5 +++-- cmd/nerdctl/container/container_list_test.go | 5 +++-- .../container/container_prune_linux_test.go | 4 ++-- cmd/nerdctl/container/container_remove_test.go | 2 +- .../container/container_rename_linux_test.go | 7 ++++--- .../container/container_rename_windows_test.go | 5 +++-- .../container/container_restart_linux_test.go | 11 ++++++----- .../container_run_cgroup_linux_test.go | 9 +++++---- .../container/container_run_linux_test.go | 17 +++++++++-------- .../container/container_run_mount_linux_test.go | 3 ++- .../container_run_network_linux_test.go | 3 ++- cmd/nerdctl/container/container_run_test.go | 3 ++- cmd/nerdctl/container/container_stats_test.go | 4 ++-- cmd/nerdctl/container/container_top_test.go | 4 ++-- cmd/nerdctl/image/image_remove_test.go | 16 ++++++++-------- .../network/network_remove_linux_test.go | 2 +- pkg/testutil/nerdtest/utilities.go | 8 ++++++++ 20 files changed, 69 insertions(+), 51 deletions(-) diff --git a/cmd/nerdctl/container/container_commit_linux_test.go b/cmd/nerdctl/container/container_commit_linux_test.go index b55c2f14daf..ca9bb15f9fd 100644 --- a/cmd/nerdctl/container/container_commit_linux_test.go +++ b/cmd/nerdctl/container/container_commit_linux_test.go @@ -36,7 +36,7 @@ func TestKubeCommitSave(t *testing.T) { // NOTE: kubectl namespaces are not the same as containerd namespaces. // We still want kube test objects segregated in their own Kube API namespace. nerdtest.KubeCtlCommand(helpers, "create", "namespace", "nerdctl-test-k8s").Run(&test.Expected{}) - nerdtest.KubeCtlCommand(helpers, "run", "--image", testutil.CommonImage, identifier, "--", "sleep", "Inf").Run(&test.Expected{}) + nerdtest.KubeCtlCommand(helpers, "run", "--image", testutil.CommonImage, identifier, "--", "sleep", nerdtest.Infinity).Run(&test.Expected{}) nerdtest.KubeCtlCommand(helpers, "wait", "pod", identifier, "--for=condition=ready", "--timeout=1m").Run(&test.Expected{}) nerdtest.KubeCtlCommand(helpers, "exec", identifier, "--", "mkdir", "-p", "/tmp/whatever").Run(&test.Expected{}) nerdtest.KubeCtlCommand(helpers, "get", "pods", identifier, "-o", "jsonpath={ .status.containerStatuses[0].containerID }").Run(&test.Expected{ diff --git a/cmd/nerdctl/container/container_commit_test.go b/cmd/nerdctl/container/container_commit_test.go index c349b728b3c..22d3a3bf02c 100644 --- a/cmd/nerdctl/container/container_commit_test.go +++ b/cmd/nerdctl/container/container_commit_test.go @@ -38,7 +38,7 @@ func TestCommit(t *testing.T) { }, Setup: func(data test.Data, helpers test.Helpers) { identifier := data.Identifier() - helpers.Ensure("run", "-d", "--name", identifier, testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("run", "-d", "--name", identifier, testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("exec", identifier, "sh", "-euxc", `echo hello-test-commit > /foo`) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { @@ -63,7 +63,7 @@ func TestCommit(t *testing.T) { }, Setup: func(data test.Data, helpers test.Helpers) { identifier := data.Identifier() - helpers.Ensure("run", "-d", "--name", identifier, testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("run", "-d", "--name", identifier, testutil.CommonImage, "sleep", nerdtest.Infinity) nerdtest.EnsureContainerStarted(helpers, identifier) helpers.Ensure("exec", identifier, "sh", "-euxc", `echo hello-test-commit > /foo`) }, diff --git a/cmd/nerdctl/container/container_create_linux_test.go b/cmd/nerdctl/container/container_create_linux_test.go index 546fe02c6bc..a4b3bc64fa2 100644 --- a/cmd/nerdctl/container/container_create_linux_test.go +++ b/cmd/nerdctl/container/container_create_linux_test.go @@ -200,7 +200,7 @@ func TestIssue2993(t *testing.T) { Setup: func(data test.Data, helpers test.Helpers) { dataRoot := data.TempDir() - helpers.Ensure("run", "--data-root", dataRoot, "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") + helpers.Ensure("run", "--data-root", dataRoot, "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", nerdtest.Infinity) h := getAddrHash(defaults.DefaultAddress) dataStore := filepath.Join(dataRoot, h) @@ -224,7 +224,7 @@ func TestIssue2993(t *testing.T) { helpers.Anyhow("rm", "--data-root", data.TempDir(), "-f", data.Identifier()) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - return helpers.Command("run", "--data-root", data.TempDir(), "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") + return helpers.Command("run", "--data-root", data.TempDir(), "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", nerdtest.Infinity) }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ @@ -247,7 +247,7 @@ func TestIssue2993(t *testing.T) { Setup: func(data test.Data, helpers test.Helpers) { dataRoot := data.TempDir() - helpers.Ensure("run", "--data-root", dataRoot, "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", "infinity") + helpers.Ensure("run", "--data-root", dataRoot, "--name", data.Identifier(), "-d", testutil.AlpineImage, "sleep", nerdtest.Infinity) h := getAddrHash(defaults.DefaultAddress) dataStore := filepath.Join(dataRoot, h) diff --git a/cmd/nerdctl/container/container_exec_linux_test.go b/cmd/nerdctl/container/container_exec_linux_test.go index 6e7d5429ede..19113781ebc 100644 --- a/cmd/nerdctl/container/container_exec_linux_test.go +++ b/cmd/nerdctl/container/container_exec_linux_test.go @@ -20,6 +20,7 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" ) func TestExecWithUser(t *testing.T) { @@ -28,7 +29,7 @@ func TestExecWithUser(t *testing.T) { testContainer := testutil.Identifier(t) defer base.Cmd("rm", "-f", testContainer).Run() - base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", nerdtest.Infinity).AssertOK() base.EnsureContainerStarted(testContainer) testCases := map[string]string{ @@ -59,7 +60,7 @@ func TestExecTTY(t *testing.T) { testContainer := testutil.Identifier(t) defer base.Cmd("rm", "-f", testContainer).Run() - base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", nerdtest.Infinity).AssertOK() const sttyPartialOutput = "speed 38400 baud" // unbuffer(1) emulates tty, which is required by `nerdctl run -t`. diff --git a/cmd/nerdctl/container/container_list_test.go b/cmd/nerdctl/container/container_list_test.go index a5bcd65fec7..751cfabc64c 100644 --- a/cmd/nerdctl/container/container_list_test.go +++ b/cmd/nerdctl/container/container_list_test.go @@ -21,6 +21,7 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" ) // https://github.com/containerd/nerdctl/issues/2598 @@ -35,7 +36,7 @@ func TestContainerListWithFormatLabel(t *testing.T) { base.Cmd("run", "-d", "--name", cID, "--label", labelK+"="+labelV, - testutil.CommonImage, "sleep", "infinity").AssertOK() + testutil.CommonImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", cID).AssertOK() base.Cmd("ps", "-a", "--filter", "label="+labelK, @@ -53,7 +54,7 @@ func TestContainerListWithJsonFormatLabel(t *testing.T) { base.Cmd("run", "-d", "--name", cID, "--label", labelK+"="+labelV, - testutil.CommonImage, "sleep", "infinity").AssertOK() + testutil.CommonImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", cID).AssertOK() base.Cmd("ps", "-a", "--filter", "label="+labelK, diff --git a/cmd/nerdctl/container/container_prune_linux_test.go b/cmd/nerdctl/container/container_prune_linux_test.go index 84979c780a6..4ff48954385 100644 --- a/cmd/nerdctl/container/container_prune_linux_test.go +++ b/cmd/nerdctl/container/container_prune_linux_test.go @@ -35,9 +35,9 @@ func TestPruneContainer(t *testing.T) { } testCase.Setup = func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "-d", "--name", data.Identifier("1"), "-v", "/anonymous", testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("run", "-d", "--name", data.Identifier("1"), "-v", "/anonymous", testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("exec", data.Identifier("1"), "touch", "/anonymous/foo") - helpers.Ensure("create", "--name", data.Identifier("2"), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("create", "--name", data.Identifier("2"), testutil.CommonImage, "sleep", nerdtest.Infinity) } testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { diff --git a/cmd/nerdctl/container/container_remove_test.go b/cmd/nerdctl/container/container_remove_test.go index 11340d7930a..36c81c2c6ab 100644 --- a/cmd/nerdctl/container/container_remove_test.go +++ b/cmd/nerdctl/container/container_remove_test.go @@ -28,7 +28,7 @@ func TestRemoveContainer(t *testing.T) { testCase := nerdtest.Setup() testCase.Setup = func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "inf") + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) } testCase.Cleanup = func(data test.Data, helpers test.Helpers) { diff --git a/cmd/nerdctl/container/container_rename_linux_test.go b/cmd/nerdctl/container/container_rename_linux_test.go index 9018cc429dd..cc8a6733d5f 100644 --- a/cmd/nerdctl/container/container_rename_linux_test.go +++ b/cmd/nerdctl/container/container_rename_linux_test.go @@ -20,6 +20,7 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" ) func TestRename(t *testing.T) { @@ -28,7 +29,7 @@ func TestRename(t *testing.T) { base := testutil.NewBase(t) defer base.Cmd("rm", "-f", testContainerName).Run() - base.Cmd("run", "-d", "--name", testContainerName, testutil.CommonImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", testContainerName, testutil.CommonImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", testContainerName+"_new").Run() base.Cmd("rename", testContainerName, testContainerName+"_new").AssertOK() @@ -44,11 +45,11 @@ func TestRenameUpdateHosts(t *testing.T) { base := testutil.NewBase(t) defer base.Cmd("rm", "-f", testContainerName).Run() - base.Cmd("run", "-d", "--name", testContainerName, testutil.CommonImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", testContainerName, testutil.CommonImage, "sleep", nerdtest.Infinity).AssertOK() base.EnsureContainerStarted(testContainerName) defer base.Cmd("rm", "-f", testContainerName+"_1").Run() - base.Cmd("run", "-d", "--name", testContainerName+"_1", testutil.CommonImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", testContainerName+"_1", testutil.CommonImage, "sleep", nerdtest.Infinity).AssertOK() base.EnsureContainerStarted(testContainerName + "_1") defer base.Cmd("rm", "-f", testContainerName+"_new").Run() diff --git a/cmd/nerdctl/container/container_rename_windows_test.go b/cmd/nerdctl/container/container_rename_windows_test.go index 6ebd2796049..7532b22573f 100644 --- a/cmd/nerdctl/container/container_rename_windows_test.go +++ b/cmd/nerdctl/container/container_rename_windows_test.go @@ -20,6 +20,7 @@ import ( "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" ) func TestRenameProcessContainer(t *testing.T) { @@ -27,7 +28,7 @@ func TestRenameProcessContainer(t *testing.T) { base := testutil.NewBase(t) defer base.Cmd("rm", "-f", testContainerName).Run() - base.Cmd("run", "--isolation", "process", "-d", "--name", testContainerName, testutil.CommonImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "--isolation", "process", "-d", "--name", testContainerName, testutil.CommonImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", testContainerName+"_new").Run() base.Cmd("rename", testContainerName, testContainerName+"_new").AssertOK() @@ -45,7 +46,7 @@ func TestRenameHyperVContainer(t *testing.T) { } defer base.Cmd("rm", "-f", testContainerName).Run() - base.Cmd("run", "--isolation", "hyperv", "-d", "--name", testContainerName, testutil.CommonImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "--isolation", "hyperv", "-d", "--name", testContainerName, testutil.CommonImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", testContainerName+"_new").Run() base.Cmd("rename", testContainerName, testContainerName+"_new").AssertOK() diff --git a/cmd/nerdctl/container/container_restart_linux_test.go b/cmd/nerdctl/container/container_restart_linux_test.go index cd9f7754473..3565f9f11ad 100644 --- a/cmd/nerdctl/container/container_restart_linux_test.go +++ b/cmd/nerdctl/container/container_restart_linux_test.go @@ -25,6 +25,7 @@ import ( "gotest.tools/v3/assert" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" ) func TestRestart(t *testing.T) { @@ -52,11 +53,11 @@ func TestRestartPIDContainer(t *testing.T) { base := testutil.NewBase(t) baseContainerName := testutil.Identifier(t) - base.Cmd("run", "-d", "--name", baseContainerName, testutil.AlpineImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", baseContainerName, testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", baseContainerName).Run() sharedContainerName := fmt.Sprintf("%s-shared", baseContainerName) - base.Cmd("run", "-d", "--name", sharedContainerName, fmt.Sprintf("--pid=container:%s", baseContainerName), testutil.AlpineImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", sharedContainerName, fmt.Sprintf("--pid=container:%s", baseContainerName), testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", sharedContainerName).Run() base.Cmd("restart", baseContainerName).AssertOK() @@ -79,11 +80,11 @@ func TestRestartIPCContainer(t *testing.T) { const shmSize = "32m" baseContainerName := testutil.Identifier(t) defer base.Cmd("rm", "-f", baseContainerName).Run() - base.Cmd("run", "-d", "--shm-size", shmSize, "--ipc", "shareable", "--name", baseContainerName, testutil.AlpineImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--shm-size", shmSize, "--ipc", "shareable", "--name", baseContainerName, testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() sharedContainerName := fmt.Sprintf("%s-shared", baseContainerName) defer base.Cmd("rm", "-f", sharedContainerName).Run() - base.Cmd("run", "-d", "--name", sharedContainerName, fmt.Sprintf("--ipc=container:%s", baseContainerName), testutil.AlpineImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", sharedContainerName, fmt.Sprintf("--ipc=container:%s", baseContainerName), testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() base.Cmd("stop", baseContainerName).Run() base.Cmd("stop", sharedContainerName).Run() @@ -104,7 +105,7 @@ func TestRestartWithTime(t *testing.T) { base := testutil.NewBase(t) tID := testutil.Identifier(t) - base.Cmd("run", "-d", "--name", tID, testutil.AlpineImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", tID, testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", tID).AssertOK() inspect := base.InspectContainer(tID) diff --git a/cmd/nerdctl/container/container_run_cgroup_linux_test.go b/cmd/nerdctl/container/container_run_cgroup_linux_test.go index a856bb5f732..8b423d970ba 100644 --- a/cmd/nerdctl/container/container_run_cgroup_linux_test.go +++ b/cmd/nerdctl/container/container_run_cgroup_linux_test.go @@ -31,6 +31,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/cmd/container" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" ) func TestRunCgroupV2(t *testing.T) { @@ -96,7 +97,7 @@ func TestRunCgroupV2(t *testing.T) { "cpu.weight", "cpuset.cpus", "cpuset.mems").AssertOutExactly(expected2) base.Cmd("run", "--name", testutil.Identifier(t)+"-testUpdate1", "-w", "/sys/fs/cgroup", "-d", - testutil.AlpineImage, "sleep", "infinity").AssertOK() + testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", testutil.Identifier(t)+"-testUpdate1").Run() update := []string{"update", "--cpu-quota", "42000", "--cpuset-mems", "0", "--cpu-period", "100000", "--memory", "42m", @@ -115,7 +116,7 @@ func TestRunCgroupV2(t *testing.T) { defer base.Cmd("rm", "-f", testutil.Identifier(t)+"-testUpdate2").Run() base.Cmd("run", "--name", testutil.Identifier(t)+"-testUpdate2", "-w", "/sys/fs/cgroup", "-d", - testutil.AlpineImage, "sleep", "infinity").AssertOK() + testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() base.EnsureContainerStarted(testutil.Identifier(t) + "-testUpdate2") base.Cmd("update", "--cpu-quota", "42000", "--cpuset-mems", "0", "--cpu-period", "100000", @@ -199,7 +200,7 @@ func TestRunDevice(t *testing.T) { "--name", containerName, "--device", lo[0].Device+":r", "--device", lo[1].Device, - testutil.AlpineImage, "sleep", "infinity").Run() + testutil.AlpineImage, "sleep", nerdtest.Infinity).Run() base.Cmd("exec", containerName, "cat", lo[0].Device).AssertOutContains(loContent[0]) base.Cmd("exec", containerName, "cat", lo[1].Device).AssertOutContains(loContent[1]) @@ -364,7 +365,7 @@ func TestRunBlkioWeightCgroupV2(t *testing.T) { containerName := testutil.Identifier(t) defer base.Cmd("rm", "-f", containerName).AssertOK() // when bfq io scheduler is used, the io.weight knob is exposed as io.bfq.weight - base.Cmd("run", "--name", containerName, "--blkio-weight", "300", "-w", "/sys/fs/cgroup", testutil.AlpineImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "--name", containerName, "--blkio-weight", "300", "-w", "/sys/fs/cgroup", testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() base.Cmd("exec", containerName, "cat", "io.bfq.weight").AssertOutExactly("default 300\n") base.Cmd("update", containerName, "--blkio-weight", "400").AssertOK() base.Cmd("exec", containerName, "cat", "io.bfq.weight").AssertOutExactly("default 400\n") diff --git a/cmd/nerdctl/container/container_run_linux_test.go b/cmd/nerdctl/container/container_run_linux_test.go index aca549d9446..0b16d2363df 100644 --- a/cmd/nerdctl/container/container_run_linux_test.go +++ b/cmd/nerdctl/container/container_run_linux_test.go @@ -39,6 +39,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" ) func TestRunCustomRootfs(t *testing.T) { @@ -108,7 +109,7 @@ func TestRunIPCContainerNotExists(t *testing.T) { base := testutil.NewBase(t) container := testutil.Identifier(t) - result := base.Cmd("run", "--name", container, "--ipc", "container:abcd1234", testutil.AlpineImage, "sleep", "infinity").Run() + result := base.Cmd("run", "--name", container, "--ipc", "container:abcd1234", testutil.AlpineImage, "sleep", nerdtest.Infinity).Run() defer base.Cmd("rm", "-f", container) combined := result.Combined() if !strings.Contains(strings.ToLower(combined), "no such container: abcd1234") { @@ -121,7 +122,7 @@ func TestRunShmSizeIPCContainer(t *testing.T) { base := testutil.NewBase(t) const shmSize = "32m" - sharedContainerResult := base.Cmd("run", "-d", "--ipc", "shareable", "--shm-size", shmSize, testutil.AlpineImage, "sleep", "infinity").Run() + sharedContainerResult := base.Cmd("run", "-d", "--ipc", "shareable", "--shm-size", shmSize, testutil.AlpineImage, "sleep", nerdtest.Infinity).Run() baseContainerID := strings.TrimSpace(sharedContainerResult.Stdout()) defer base.Cmd("rm", "-f", baseContainerID).Run() @@ -134,7 +135,7 @@ func TestRunIPCContainer(t *testing.T) { base := testutil.NewBase(t) const shmSize = "32m" - victimContainerResult := base.Cmd("run", "-d", "--ipc", "shareable", "--shm-size", shmSize, testutil.AlpineImage, "sleep", "infinity").Run() + victimContainerResult := base.Cmd("run", "-d", "--ipc", "shareable", "--shm-size", shmSize, testutil.AlpineImage, "sleep", nerdtest.Infinity).Run() victimContainerID := strings.TrimSpace(victimContainerResult.Stdout()) defer base.Cmd("rm", "-f", victimContainerID).Run() @@ -169,12 +170,12 @@ func TestRunPidContainer(t *testing.T) { t.Parallel() base := testutil.NewBase(t) - sharedContainerResult := base.Cmd("run", "-d", testutil.AlpineImage, "sleep", "infinity").Run() + sharedContainerResult := base.Cmd("run", "-d", testutil.AlpineImage, "sleep", nerdtest.Infinity).Run() baseContainerID := strings.TrimSpace(sharedContainerResult.Stdout()) defer base.Cmd("rm", "-f", baseContainerID).Run() base.Cmd("run", "--rm", fmt.Sprintf("--pid=container:%s", baseContainerID), - testutil.AlpineImage, "ps", "ax").AssertOutContains("sleep infinity") + testutil.AlpineImage, "ps", "ax").AssertOutContains("sleep " + nerdtest.Infinity) } func TestRunIpcHost(t *testing.T) { @@ -278,7 +279,7 @@ func TestRunWithInit(t *testing.T) { base := testutil.NewBase(t) container := testutil.Identifier(t) - base.Cmd("run", "-d", "--name", container, testutil.AlpineImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", container, testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", container).Run() base.Cmd("stop", "--time=3", container).AssertOK() @@ -288,7 +289,7 @@ func TestRunWithInit(t *testing.T) { // Test with --init-path container1 := container + "-1" base.Cmd("run", "-d", "--name", container1, "--init-binary", "tini-custom", - testutil.AlpineImage, "sleep", "infinity").AssertOK() + testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", container1).Run() base.Cmd("stop", "--time=3", container1).AssertOK() @@ -297,7 +298,7 @@ func TestRunWithInit(t *testing.T) { // Test with --init container2 := container + "-2" base.Cmd("run", "-d", "--name", container2, "--init", - testutil.AlpineImage, "sleep", "infinity").AssertOK() + testutil.AlpineImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("rm", "-f", container2).Run() base.Cmd("stop", "--time=3", container2).AssertOK() diff --git a/cmd/nerdctl/container/container_run_mount_linux_test.go b/cmd/nerdctl/container/container_run_mount_linux_test.go index 3f4c1972ee9..1b3f651cef2 100644 --- a/cmd/nerdctl/container/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container/container_run_mount_linux_test.go @@ -31,6 +31,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" ) func TestRunVolume(t *testing.T) { @@ -242,7 +243,7 @@ RUN echo -n "rev0" > /mnt/file base.Cmd("volume", "create", volumeName) runContainer := func() { - base.Cmd("run", "-d", "--name", containerName, "-v", volumeName+":/mnt", imageName, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--name", containerName, "-v", volumeName+":/mnt", imageName, "sleep", nerdtest.Infinity).AssertOK() } runContainer() base.EnsureContainerStarted(containerName) diff --git a/cmd/nerdctl/container/container_run_network_linux_test.go b/cmd/nerdctl/container/container_run_network_linux_test.go index 15c92e7c03b..b946947fc01 100644 --- a/cmd/nerdctl/container/container_run_network_linux_test.go +++ b/cmd/nerdctl/container/container_run_network_linux_test.go @@ -39,6 +39,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" ) @@ -492,7 +493,7 @@ func TestSharedNetworkStack(t *testing.T) { "--name", containerNameJoin, "--network=container:"+containerName, testutil.CommonImage, - "sleep", "infinity").AssertOK() + "sleep", nerdtest.Infinity).AssertOK() base.Cmd("exec", containerNameJoin, "wget", "-qO-", "http://127.0.0.1:80"). AssertOutContains(testutil.NginxAlpineIndexHTMLSnippet) diff --git a/cmd/nerdctl/container/container_run_test.go b/cmd/nerdctl/container/container_run_test.go index b7054c77722..a727a68ea45 100644 --- a/cmd/nerdctl/container/container_run_test.go +++ b/cmd/nerdctl/container/container_run_test.go @@ -36,6 +36,7 @@ import ( "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" ) func TestRunEntrypointWithBuild(t *testing.T) { @@ -470,7 +471,7 @@ func TestRunAddHostRemainsWhenAnotherContainerCreated(t *testing.T) { containerName := testutil.Identifier(t) hostMapping := "test-add-host:10.0.0.1" - base.Cmd("run", "-d", "--add-host", hostMapping, "--name", containerName, testutil.CommonImage, "sleep", "infinity").AssertOK() + base.Cmd("run", "-d", "--add-host", hostMapping, "--name", containerName, testutil.CommonImage, "sleep", nerdtest.Infinity).AssertOK() defer base.Cmd("container", "rm", "-f", containerName).Run() checkEtcHosts := func(stdout string) error { diff --git a/cmd/nerdctl/container/container_stats_test.go b/cmd/nerdctl/container/container_stats_test.go index e3c9b3a8c2c..9522e73e009 100644 --- a/cmd/nerdctl/container/container_stats_test.go +++ b/cmd/nerdctl/container/container_stats_test.go @@ -47,8 +47,8 @@ func TestStats(t *testing.T) { } testCase.Setup = func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "-d", "--name", data.Identifier("container"), testutil.CommonImage, "sleep", "10") - helpers.Ensure("run", "-d", "--name", data.Identifier("memlimited"), "--memory", "1g", testutil.CommonImage, "sleep", "10") + helpers.Ensure("run", "-d", "--name", data.Identifier("container"), testutil.CommonImage, "sleep", nerdtest.Infinity) + helpers.Ensure("run", "-d", "--name", data.Identifier("memlimited"), "--memory", "1g", testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("run", "--name", data.Identifier("exited"), testutil.CommonImage, "echo", "'exited'") data.Set("id", data.Identifier("container")) } diff --git a/cmd/nerdctl/container/container_top_test.go b/cmd/nerdctl/container/container_top_test.go index 5f7a6e0a4b5..8042b32a8b4 100644 --- a/cmd/nerdctl/container/container_top_test.go +++ b/cmd/nerdctl/container/container_top_test.go @@ -35,7 +35,7 @@ func TestTop(t *testing.T) { testCase.Setup = func(data test.Data, helpers test.Helpers) { // FIXME: busybox 1.36 on windows still appears to not support sleep inf. Unclear why. - helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "10") + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) data.Set("cID", data.Identifier()) } @@ -75,7 +75,7 @@ func TestTopHyperVContainer(t *testing.T) { testCase.Setup = func(data test.Data, helpers test.Helpers) { // FIXME: busybox 1.36 on windows still appears to not support sleep inf. Unclear why. - helpers.Ensure("run", "--isolation", "hyperv", "-d", "--name", data.Identifier("container"), testutil.CommonImage, "sleep", "10") + helpers.Ensure("run", "--isolation", "hyperv", "-d", "--name", data.Identifier("container"), testutil.CommonImage, "sleep", nerdtest.Infinity) } testCase.Cleanup = func(data test.Data, helpers test.Helpers) { diff --git a/cmd/nerdctl/image/image_remove_test.go b/cmd/nerdctl/image/image_remove_test.go index 5e48372332c..da80fb5eeb5 100644 --- a/cmd/nerdctl/image/image_remove_test.go +++ b/cmd/nerdctl/image/image_remove_test.go @@ -94,7 +94,7 @@ func TestRemove(t *testing.T) { test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) @@ -125,7 +125,7 @@ func TestRemove(t *testing.T) { test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) @@ -148,7 +148,7 @@ func TestRemove(t *testing.T) { NoParallel: true, Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("create", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("create", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) @@ -170,7 +170,7 @@ func TestRemove(t *testing.T) { Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("pull", "--quiet", testutil.NginxAlpineImage) - helpers.Ensure("create", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("create", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("rmi", testutil.NginxAlpineImage) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -200,7 +200,7 @@ func TestRemove(t *testing.T) { nerdtest.CGroup, ), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("pause", data.Identifier()) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -233,7 +233,7 @@ func TestRemove(t *testing.T) { test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("pause", data.Identifier()) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -260,7 +260,7 @@ func TestRemove(t *testing.T) { test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("kill", data.Identifier()) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -284,7 +284,7 @@ func TestRemove(t *testing.T) { NoParallel: true, Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { - helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("kill", data.Identifier()) }, Cleanup: func(data test.Data, helpers test.Helpers) { diff --git a/cmd/nerdctl/network/network_remove_linux_test.go b/cmd/nerdctl/network/network_remove_linux_test.go index 5d10c9f0f61..f1d6e2e5876 100644 --- a/cmd/nerdctl/network/network_remove_linux_test.go +++ b/cmd/nerdctl/network/network_remove_linux_test.go @@ -65,7 +65,7 @@ func TestNetworkRemove(t *testing.T) { Description: "Network remove when linked to container", Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage, "sleep", "infinity") + helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("network", "rm", data.Identifier()) diff --git a/pkg/testutil/nerdtest/utilities.go b/pkg/testutil/nerdtest/utilities.go index f23ce2b2c9a..18f34a8af7c 100644 --- a/pkg/testutil/nerdtest/utilities.go +++ b/pkg/testutil/nerdtest/utilities.go @@ -29,6 +29,14 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) +const ( + // It seems that at this moment, the busybox on windows image we are using has an outdated version of sleep + // that does not support inf/infinity. + // This constant is provided as a mean for tests to express the intention of sleep infinity without having to + // worry about that and get windows compatibility. + Infinity = "3600" +) + func IsDocker() bool { return testutil.GetTarget() == "docker" } From f6d36c402b9414be1f5ceb320d344c25139275f8 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 1 Nov 2024 15:36:51 +0100 Subject: [PATCH 0901/1066] Move from AlpineImage to CommonImage to enable windows tests Signed-off-by: apostasie --- cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go | 6 +++--- cmd/nerdctl/ipfs/ipfs_registry_linux_test.go | 8 ++++---- cmd/nerdctl/ipfs/ipfs_simple_linux_test.go | 12 ++++++------ cmd/nerdctl/issues/main_linux_test.go | 4 ++-- cmd/nerdctl/network/network_create_linux_test.go | 6 +++--- cmd/nerdctl/network/network_prune_linux_test.go | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go b/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go index c65883e7681..cb21a839779 100644 --- a/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_kubo_linux_test.go @@ -43,7 +43,7 @@ func TestIPFSAddrWithKubo(t *testing.T) { ) testCase.Setup = func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", "--quiet", testutil.AlpineImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) ipfsRegistry = registry.NewKuboRegistry(data, helpers, t, nil, 0, nil) ipfsRegistry.Setup(data, helpers) @@ -62,7 +62,7 @@ func TestIPFSAddrWithKubo(t *testing.T) { Description: "with default snapshotter", NoParallel: true, Setup: func(data test.Data, helpers test.Helpers) { - ipfsCID := pushToIPFS(helpers, testutil.AlpineImage, fmt.Sprintf("--ipfs-address=%s", data.Get(ipfsAddrKey))) + ipfsCID := pushToIPFS(helpers, testutil.CommonImage, fmt.Sprintf("--ipfs-address=%s", data.Get(ipfsAddrKey))) helpers.Ensure("pull", "--ipfs-address", data.Get(ipfsAddrKey), "ipfs://"+ipfsCID) data.Set(mainImageCIDKey, ipfsCID) }, @@ -85,7 +85,7 @@ func TestIPFSAddrWithKubo(t *testing.T) { nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3475"), ), Setup: func(data test.Data, helpers test.Helpers) { - ipfsCID := pushToIPFS(helpers, testutil.AlpineImage, fmt.Sprintf("--ipfs-address=%s", data.Get(ipfsAddrKey)), "--estargz") + ipfsCID := pushToIPFS(helpers, testutil.CommonImage, fmt.Sprintf("--ipfs-address=%s", data.Get(ipfsAddrKey)), "--estargz") helpers.Ensure("pull", "--ipfs-address", data.Get(ipfsAddrKey), "ipfs://"+ipfsCID) data.Set(mainImageCIDKey, ipfsCID) }, diff --git a/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go index 72b9b135d38..a4be0b01aa5 100644 --- a/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go @@ -62,7 +62,7 @@ func TestIPFSNerdctlRegistry(t *testing.T) { ) testCase.Setup = func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", "--quiet", testutil.AlpineImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) // Start a local ipfs backed registry ipfsServer = helpers.Command("ipfs", "registry", "serve", "--listen-registry", listenAddr) @@ -84,7 +84,7 @@ func TestIPFSNerdctlRegistry(t *testing.T) { Description: "with default snapshotter", NoParallel: true, Setup: func(data test.Data, helpers test.Helpers) { - data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.AlpineImage)) + data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.CommonImage)) helpers.Ensure("pull", "--quiet", data.Get(ipfsImageURLKey)) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -102,7 +102,7 @@ func TestIPFSNerdctlRegistry(t *testing.T) { NoParallel: true, Require: nerdtest.Stargz, Setup: func(data test.Data, helpers test.Helpers) { - data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.AlpineImage, "--estargz")) + data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.CommonImage, "--estargz")) helpers.Ensure("pull", "--quiet", data.Get(ipfsImageURLKey)) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -126,7 +126,7 @@ func TestIPFSNerdctlRegistry(t *testing.T) { } }, Setup: func(data test.Data, helpers test.Helpers) { - data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.AlpineImage)) + data.Set(ipfsImageURLKey, listenAddr+"/ipfs/"+pushToIPFS(helpers, testutil.CommonImage)) dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-test-string"] diff --git a/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go b/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go index 5c7b5697464..f2d59a15618 100644 --- a/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go @@ -42,7 +42,7 @@ func TestIPFSSimple(t *testing.T) { ) testCase.Setup = func(data test.Data, helpers test.Helpers) { - helpers.Ensure("pull", "--quiet", testutil.AlpineImage) + helpers.Ensure("pull", "--quiet", testutil.CommonImage) } testCase.SubTests = []*test.Case{ @@ -50,7 +50,7 @@ func TestIPFSSimple(t *testing.T) { Description: "with default snapshotter", NoParallel: true, Setup: func(data test.Data, helpers test.Helpers) { - data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.AlpineImage)) + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.CommonImage)) helpers.Ensure("pull", "ipfs://"+data.Get(mainImageCIDKey)) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -71,7 +71,7 @@ func TestIPFSSimple(t *testing.T) { nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3475"), ), Setup: func(data test.Data, helpers test.Helpers) { - data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.AlpineImage, "--estargz")) + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.CommonImage, "--estargz")) helpers.Ensure("pull", "ipfs://"+data.Get(mainImageCIDKey)) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -88,7 +88,7 @@ func TestIPFSSimple(t *testing.T) { Description: "with commit and push", NoParallel: true, Setup: func(data test.Data, helpers test.Helpers) { - data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.AlpineImage)) + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.CommonImage)) helpers.Ensure("pull", "ipfs://"+data.Get(mainImageCIDKey)) // Run a container that does modify something, then commit and push it @@ -126,7 +126,7 @@ func TestIPFSSimple(t *testing.T) { nerdtest.NerdctlNeedsFixing("https://github.com/containerd/nerdctl/issues/3475"), ), Setup: func(data test.Data, helpers test.Helpers) { - data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.AlpineImage, "--estargz")) + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.CommonImage, "--estargz")) helpers.Ensure("pull", "ipfs://"+data.Get(mainImageCIDKey)) // Run a container that does modify something, then commit and push it @@ -161,7 +161,7 @@ func TestIPFSSimple(t *testing.T) { NoParallel: true, Require: test.Binary("openssl"), Setup: func(data test.Data, helpers test.Helpers) { - data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.AlpineImage)) + data.Set(mainImageCIDKey, pushToIPFS(helpers, testutil.CommonImage)) helpers.Ensure("pull", "ipfs://"+data.Get(mainImageCIDKey)) // Prep a key pair diff --git a/cmd/nerdctl/issues/main_linux_test.go b/cmd/nerdctl/issues/main_linux_test.go index e6735f02c14..c67fa8eb1c1 100644 --- a/cmd/nerdctl/issues/main_linux_test.go +++ b/cmd/nerdctl/issues/main_linux_test.go @@ -39,7 +39,7 @@ func TestIssue108(t *testing.T) { { Description: "-it --net=host", Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - cmd := helpers.Command("run", "-it", "--rm", "--net=host", testutil.AlpineImage, "echo", "this was always working") + cmd := helpers.Command("run", "-it", "--rm", "--net=host", testutil.CommonImage, "echo", "this was always working") cmd.WithPseudoTTY() return cmd }, @@ -48,7 +48,7 @@ func TestIssue108(t *testing.T) { { Description: "--net=host -it", Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - cmd := helpers.Command("run", "--rm", "--net=host", "-it", testutil.AlpineImage, "echo", "this was not working due to issue #108") + cmd := helpers.Command("run", "--rm", "--net=host", "-it", testutil.CommonImage, "echo", "this was not working due to issue #108") cmd.WithPseudoTTY() return cmd }, diff --git a/cmd/nerdctl/network/network_create_linux_test.go b/cmd/nerdctl/network/network_create_linux_test.go index f42c312e699..15012eabe88 100644 --- a/cmd/nerdctl/network/network_create_linux_test.go +++ b/cmd/nerdctl/network/network_create_linux_test.go @@ -49,8 +49,8 @@ func TestNetworkCreate(t *testing.T) { helpers.Anyhow("network", "rm", data.Identifier("1")) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - data.Set("container2", helpers.Capture("run", "--rm", "--net", data.Identifier("1"), testutil.AlpineImage, "ip", "route")) - return helpers.Command("run", "--rm", "--net", data.Identifier(), testutil.AlpineImage, "ip", "route") + data.Set("container2", helpers.Capture("run", "--rm", "--net", data.Identifier("1"), testutil.CommonImage, "ip", "route")) + return helpers.Command("run", "--rm", "--net", data.Identifier(), testutil.CommonImage, "ip", "route") }, Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ @@ -72,7 +72,7 @@ func TestNetworkCreate(t *testing.T) { helpers.Anyhow("network", "rm", data.Identifier()) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - return helpers.Command("run", "--rm", "--net", data.Identifier(), testutil.AlpineImage, "ifconfig", "eth0") + return helpers.Command("run", "--rm", "--net", data.Identifier(), testutil.CommonImage, "ifconfig", "eth0") }, Expected: test.Expects(0, nil, test.Contains("MTU:9216")), }, diff --git a/cmd/nerdctl/network/network_prune_linux_test.go b/cmd/nerdctl/network/network_prune_linux_test.go index b4b0ec6bbae..5c1fc0bfb17 100644 --- a/cmd/nerdctl/network/network_prune_linux_test.go +++ b/cmd/nerdctl/network/network_prune_linux_test.go @@ -36,7 +36,7 @@ func TestNetworkPrune(t *testing.T) { Setup: func(data test.Data, helpers test.Helpers) { identifier := data.Identifier() helpers.Ensure("network", "create", identifier) - helpers.Ensure("run", "-d", "--net", identifier, "--name", identifier, testutil.NginxAlpineImage) + helpers.Ensure("run", "-d", "--net", identifier, "--name", identifier, testutil.CommonImage, "sleep", nerdtest.Infinity) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) @@ -54,7 +54,7 @@ func TestNetworkPrune(t *testing.T) { NoParallel: true, Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("network", "create", data.Identifier()) - helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.NginxAlpineImage) + helpers.Ensure("run", "-d", "--net", data.Identifier(), "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("stop", data.Identifier()) }, Cleanup: func(data test.Data, helpers test.Helpers) { From b1e82268ad425d73ae6c8a740665aa86583d8a95 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 1 Nov 2024 15:37:22 +0100 Subject: [PATCH 0902/1066] Fix prior test-porting not aligned with description Signed-off-by: apostasie --- cmd/nerdctl/image/image_remove_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/nerdctl/image/image_remove_test.go b/cmd/nerdctl/image/image_remove_test.go index da80fb5eeb5..f94b0e71e57 100644 --- a/cmd/nerdctl/image/image_remove_test.go +++ b/cmd/nerdctl/image/image_remove_test.go @@ -153,12 +153,14 @@ func TestRemove(t *testing.T) { Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) }, - Command: test.Command("rmi", "-f", testutil.CommonImage), + Command: test.Command("rmi", testutil.CommonImage), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("image is being used")}, Output: func(stdout string, info string, t *testing.T) { helpers.Command("images").Run(&test.Expected{ - Output: test.DoesNotContain(repoName), + Output: test.Contains(repoName), }) }, } From de193b39594fb8c4cd2f00f85609ff4bf719d0b7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 1 Nov 2024 13:40:16 +0100 Subject: [PATCH 0903/1066] Enable GHA cache for image build dependencies Signed-off-by: apostasie --- .github/workflows/test.yml | 111 ++++++++++++++++++++++++++++++------- Dockerfile | 37 +++++++------ 2 files changed, 111 insertions(+), 37 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c2faa76231a..57a09ce86ee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,47 @@ env: LONG_TIMEOUT: 60 jobs: + # This job builds the dependency target of the test docker image for all supported architectures and cache it in GHA + build-dependencies: + timeout-minutes: 10 + name: dependencies | ${{ matrix.containerd }} | ${{ matrix.arch }} + runs-on: "${{ matrix.runner }}" + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-24.04 + containerd: v1.6.36 + arch: amd64 + - runner: ubuntu-24.04 + containerd: v1.7.23 + arch: amd64 + - runner: ubuntu-24.04 + containerd: v2.0.0-rc.5 + arch: amd64 + - runner: arm64-8core-32gb + containerd: v2.0.0-rc.5 + arch: arm64 + env: + CONTAINERD_VERSION: "${{ matrix.containerd }}" + ARCH: "${{ matrix.arch }}" + steps: + - uses: actions/checkout@v4.2.1 + with: + fetch-depth: 1 + - name: "Expose GitHub Runtime variables for gha" + uses: crazy-max/ghaction-github-runtime@v3 + - name: "Build dependencies for the integration test environment image" + run: | + docker buildx create --name with-gha --use + docker buildx build \ + --output=type=docker \ + --cache-to type=gha,mode=max,scope=${ARCH}-${CONTAINERD_VERSION} \ + --cache-from type=gha,scope=${ARCH}-${CONTAINERD_VERSION} \ + --target build-dependencies --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . + test-unit: + # FIXME: # Supposed to work: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#example-returning-a-json-data-type # Apparently does not # timeout-minutes: ${{ fromJSON(env.SHORT_TIMEOUT) }} @@ -56,7 +96,8 @@ jobs: run: make test-unit test-integration: - timeout-minutes: 60 + needs: build-dependencies + timeout-minutes: 30 name: rootful | ${{ matrix.containerd }} | ${{ matrix.runner }} runs-on: "${{ matrix.runner }}" strategy: @@ -67,24 +108,36 @@ jobs: - ubuntu: 20.04 containerd: v1.6.36 runner: "ubuntu-20.04" + arch: amd64 - ubuntu: 22.04 containerd: v1.7.23 runner: "ubuntu-22.04" + arch: amd64 - ubuntu: 24.04 containerd: v2.0.0-rc.5 runner: "ubuntu-24.04" + arch: amd64 - ubuntu: 24.04 containerd: v2.0.0-rc.5 - runner: github-arm64-2c-8gb + runner: arm64-8core-32gb + arch: arm64 env: - UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" + ARCH: "${{ matrix.arch }}" + UBUNTU_VERSION: "${{ matrix.ubuntu }}" steps: - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 + - name: "Expose GitHub Runtime variables for gha" + uses: crazy-max/ghaction-github-runtime@v3 - name: "Prepare integration test environment" - run: docker build -t test-integration --target test-integration --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . + run: | + docker buildx create --name with-gha --use + docker buildx build \ + --output=type=docker \ + --cache-from type=gha,scope=${ARCH}-${CONTAINERD_VERSION} \ + -t test-integration --target test-integration --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . - name: "Remove snap loopback devices (conflicts with our loopback devices in TestRunDevice)" run: | sudo systemctl disable --now snapd.service snapd.socket @@ -106,19 +159,21 @@ jobs: run: docker run -t --rm --privileged test-integration ./hack/test-integration.sh -test.only-flaky=true test-integration-ipv6: - timeout-minutes: 60 + needs: build-dependencies + timeout-minutes: 10 name: ipv6 | ${{ matrix.containerd }} | ${{ matrix.ubuntu }} runs-on: "ubuntu-${{ matrix.ubuntu }}" strategy: fail-fast: false matrix: - # ubuntu-20.04: cgroup v1, ubuntu-22.04 and later: cgroup v2 include: - ubuntu: 24.04 containerd: v2.0.0-rc.5 + arch: amd64 env: - UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" + ARCH: "${{ matrix.arch }}" + UBUNTU_VERSION: "${{ matrix.ubuntu }}" steps: - uses: actions/checkout@v4.2.2 with: @@ -127,13 +182,20 @@ jobs: run: | sudo sysctl -w net.ipv6.conf.all.forwarding=1 sudo sysctl -w net.ipv4.ip_forward=1 - - name: Enable IPv6 for Docker + - name: "Expose GitHub Runtime variables for gha" + uses: crazy-max/ghaction-github-runtime@v3 + - name: Enable IPv6 for Docker, and configure docker to use containerd for gha run: | sudo mkdir -p /etc/docker echo '{"ipv6": true, "fixed-cidr-v6": "2001:db8:1::/64", "experimental": true, "ip6tables": true}' | sudo tee /etc/docker/daemon.json sudo systemctl restart docker - name: "Prepare integration test environment" - run: docker build -t test-integration --target test-integration --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . + run: | + docker buildx create --name with-gha --use + docker buildx build \ + --output=type=docker \ + --cache-from type=gha,scope=${ARCH}-${CONTAINERD_VERSION} \ + -t test-integration --target test-integration --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} . - name: "Remove snap loopback devices (conflicts with our loopback devices in TestRunDevice)" run: | sudo systemctl disable --now snapd.service snapd.socket @@ -158,7 +220,8 @@ jobs: run: docker run --network host -t --rm --privileged test-integration ./hack/test-integration.sh -test.only-ipv6 test-integration-rootless: - timeout-minutes: 60 + needs: build-dependencies + timeout-minutes: 30 name: "${{ matrix.target }} | ${{ matrix.containerd }} | ${{ matrix.rootlesskit }} | ${{ matrix.ubuntu }}" runs-on: "ubuntu-${{ matrix.ubuntu }}" strategy: @@ -170,21 +233,26 @@ jobs: containerd: v1.6.36 rootlesskit: v1.1.1 # Deprecated target: rootless + arch: amd64 - ubuntu: 22.04 containerd: v1.7.23 rootlesskit: v2.3.1 target: rootless + arch: amd64 - ubuntu: 24.04 containerd: v2.0.0-rc.5 rootlesskit: v2.3.1 target: rootless + arch: amd64 - ubuntu: 24.04 containerd: v1.7.23 rootlesskit: v2.3.1 target: rootless-port-slirp4netns + arch: amd64 env: - UBUNTU_VERSION: "${{ matrix.ubuntu }}" CONTAINERD_VERSION: "${{ matrix.containerd }}" + ARCH: "${{ matrix.arch }}" + UBUNTU_VERSION: "${{ matrix.ubuntu }}" ROOTLESSKIT_VERSION: "${{ matrix.rootlesskit }}" TEST_TARGET: "test-integration-${{ matrix.target }}" steps: @@ -215,8 +283,15 @@ jobs: docker run --privileged --rm tonistiigi/binfmt --install linux/amd64 docker run --privileged --rm tonistiigi/binfmt --install linux/arm64 docker run --privileged --rm tonistiigi/binfmt --install linux/arm/v7 + - name: "Expose GitHub Runtime variables for gha" + uses: crazy-max/ghaction-github-runtime@v3 - name: "Prepare (network driver=slirp4netns, port driver=builtin)" - run: docker build -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} --build-arg ROOTLESSKIT_VERSION=${ROOTLESSKIT_VERSION} . + run: | + docker buildx create --name with-gha --use + docker buildx build \ + --output=type=docker \ + --cache-from type=gha,scope=${ARCH}-${CONTAINERD_VERSION} \ + -t ${TEST_TARGET} --target ${TEST_TARGET} --build-arg UBUNTU_VERSION=${UBUNTU_VERSION} --build-arg CONTAINERD_VERSION=${CONTAINERD_VERSION} --build-arg ROOTLESSKIT_VERSION=${ROOTLESSKIT_VERSION} . - name: "Disable BuildKit for RootlessKit v1 (workaround for issue #622)" run: | # https://github.com/containerd/nerdctl/issues/622 @@ -250,7 +325,7 @@ jobs: run: GO_VERSION="$(echo ${{ matrix.go-version }} | sed -e s/.x//)" make binaries test-integration-docker-compatibility: - timeout-minutes: 60 + timeout-minutes: 30 name: docker runs-on: ubuntu-24.04 steps: @@ -262,11 +337,6 @@ jobs: go-version: ${{ env.GO_VERSION }} cache: true check-latest: true - - name: "Print docker info" - run: | - set -eux -o pipefail - docker info - docker version - name: "Register QEMU (tonistiigi/binfmt)" run: | # `--install all` will only install emulation for architectures that cannot be natively executed @@ -324,13 +394,14 @@ jobs: run: ./hack/test-integration.sh -test.only-flaky=true test-integration-freebsd: - timeout-minutes: 60 + timeout-minutes: 30 name: FreeBSD # ubuntu-24.04 lacks the vagrant package runs-on: ubuntu-22.04 - steps: - uses: actions/checkout@v4.2.2 + with: + fetch-depth: 1 - uses: actions/cache@v4 with: path: /root/.vagrant.d diff --git a/Dockerfile b/Dockerfile index 6099e85352f..71ec06a0ea3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -69,6 +69,7 @@ RUN xx-apt-get update -qq && xx-apt-get install -qq --no-install-recommends \ libbtrfs-dev \ libseccomp-dev \ pkg-config +RUN git config --global advice.detachedHead false FROM build-base-debian AS build-containerd ARG TARGETARCH @@ -117,25 +118,19 @@ RUN xx-go --wrap && \ FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS build-base RUN apk add --no-cache make git curl -COPY . /go/src/github.com/containerd/nerdctl -WORKDIR /go/src/github.com/containerd/nerdctl +RUN git config --global advice.detachedHead false FROM build-base AS build-minimal RUN BINDIR=/out/bin make binaries install # We do not set CMD to `go test` here, because it requires systemd -FROM build-base AS build-full +FROM build-base AS build-dependencies ARG TARGETARCH ENV GOARCH=${TARGETARCH} -RUN BINDIR=/out/bin make binaries install -WORKDIR /nowhere COPY ./Dockerfile.d/SHA256SUMS.d/ /SHA256SUMS.d -COPY README.md /out/share/doc/nerdctl/ -COPY docs /out/share/doc/nerdctl/docs +WORKDIR /nowhere RUN echo "${TARGETARCH:-amd64}" | sed -e s/amd64/x86_64/ -e s/arm64/aarch64/ | tee /target_uname_m -RUN mkdir -p /out/share/doc/nerdctl-full && \ - echo "# nerdctl (full distribution)" > /out/share/doc/nerdctl-full/README.md && \ - echo "- nerdctl: $(cd /go/src/github.com/containerd/nerdctl && git describe --tags)" >> /out/share/doc/nerdctl-full/README.md +RUN mkdir -p /out/share/doc/nerdctl-full && touch /out/share/doc/nerdctl-full/README.md ARG CONTAINERD_VERSION COPY --from=build-containerd /out/${TARGETARCH:-amd64}/* /out/bin/ COPY --from=build-containerd /out/containerd.service /out/lib/systemd/system/containerd.service @@ -181,13 +176,6 @@ RUN git clone https://github.com/containerd/imgcrypt.git /go/src/github.com/cont git checkout "${IMGCRYPT_VERSION}" && \ CGO_ENABLED=0 make && DESTDIR=/out make install && \ echo "- imgcrypt: ${IMGCRYPT_VERSION}" >> /out/share/doc/nerdctl-full/README.md -ARG ROOTLESSKIT_VERSION -RUN fname="rootlesskit-$(cat /target_uname_m).tar.gz" && \ - curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/rootless-containers/rootlesskit/releases/download/${ROOTLESSKIT_VERSION}/${fname}" && \ - grep "${fname}" "/SHA256SUMS.d/rootlesskit-${ROOTLESSKIT_VERSION}" | sha256sum -c && \ - tar xzf "${fname}" -C /out/bin && \ - rm -f "${fname}" /out/bin/rootlesskit-docker-proxy && \ - echo "- RootlessKit: ${ROOTLESSKIT_VERSION}" >> /out/share/doc/nerdctl-full/README.md ARG SLIRP4NETNS_VERSION RUN fname="slirp4netns-$(cat /target_uname_m)" && \ curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/rootless-containers/slirp4netns/releases/download/${SLIRP4NETNS_VERSION}/${fname}" && \ @@ -225,6 +213,13 @@ RUN fname="buildg-${BUILDG_VERSION}-${TARGETOS:-linux}-${TARGETARCH:-amd64}.tar. tar xzf "${fname}" -C /out/bin && \ rm -f "${fname}" && \ echo "- buildg: ${BUILDG_VERSION}" >> /out/share/doc/nerdctl-full/README.md +ARG ROOTLESSKIT_VERSION +RUN fname="rootlesskit-$(cat /target_uname_m).tar.gz" && \ + curl -o "${fname}" -fsSL --proto '=https' --tlsv1.2 "https://github.com/rootless-containers/rootlesskit/releases/download/${ROOTLESSKIT_VERSION}/${fname}" && \ + grep "${fname}" "/SHA256SUMS.d/rootlesskit-${ROOTLESSKIT_VERSION}" | sha256sum -c && \ + tar xzf "${fname}" -C /out/bin && \ + rm -f "${fname}" /out/bin/rootlesskit-docker-proxy && \ + echo "- RootlessKit: ${ROOTLESSKIT_VERSION}" >> /out/share/doc/nerdctl-full/README.md RUN echo "" >> /out/share/doc/nerdctl-full/README.md && \ echo "## License" >> /out/share/doc/nerdctl-full/README.md && \ @@ -237,6 +232,14 @@ RUN echo "" >> /out/share/doc/nerdctl-full/README.md && \ mv /tmp/SHA256SUMS /out/share/doc/nerdctl-full/SHA256SUMS && \ chown -R 0:0 /out +FROM build-dependencies AS build-full +COPY . /go/src/github.com/containerd/nerdctl +RUN { echo "# nerdctl (full distribution)"; echo "- nerdctl: $(cd /go/src/github.com/containerd/nerdctl && git describe --tags)"; cat /out/share/doc/nerdctl-full/README.md; } > /out/share/doc/nerdctl-full/README.md.new; mv /out/share/doc/nerdctl-full/README.md.new /out/share/doc/nerdctl-full/README.md +WORKDIR /go/src/github.com/containerd/nerdctl +RUN BINDIR=/out/bin make binaries install +COPY README.md /out/share/doc/nerdctl/ +COPY docs /out/share/doc/nerdctl/docs + FROM scratch AS out-full COPY --from=build-full /out / From 58318d517b552ef7d197b0bde0cd4ea55556d1d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 22:02:29 +0000 Subject: [PATCH 0904/1066] build(deps): bump github.com/containerd/typeurl/v2 from 2.2.0 to 2.2.1 Bumps [github.com/containerd/typeurl/v2](https://github.com/containerd/typeurl) from 2.2.0 to 2.2.1. - [Release notes](https://github.com/containerd/typeurl/releases) - [Commits](https://github.com/containerd/typeurl/compare/v2.2.0...v2.2.1) --- updated-dependencies: - dependency-name: github.com/containerd/typeurl/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1d41153797b..a6960035f4f 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319 github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319 - github.com/containerd/typeurl/v2 v2.2.0 + github.com/containerd/typeurl/v2 v2.2.1 github.com/containernetworking/cni v1.2.3 github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.8.0 diff --git a/go.sum b/go.sum index d11537c752a..28a9f9228f1 100644 --- a/go.sum +++ b/go.sum @@ -65,8 +65,8 @@ github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89 github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:L/J/O36DzcGxq3drHM45sJRr/pEQTG5u+tbffVhP6r8= github.com/containerd/ttrpc v1.2.6-0.20240827082320-b5cd6e4b3287 h1:zwv64tCdT888KxuXQuv5i36cEdljoXq3sVqLmOEbCQI= github.com/containerd/ttrpc v1.2.6-0.20240827082320-b5cd6e4b3287/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= -github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso= -github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g= +github.com/containerd/typeurl/v2 v2.2.1 h1:/X1Kgcz4sKS/NTKQvvRS0pEVpUYqmPTwGQontm9pl0w= +github.com/containerd/typeurl/v2 v2.2.1/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= From 4254a1fee7ff3e93a3f8ee920c4224905005fd42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 22:02:35 +0000 Subject: [PATCH 0905/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.4.2 to 2.4.3. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.4.2...v2.4.3) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1d41153797b..005464c75ca 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.9 - github.com/compose-spec/compose-go/v2 v2.4.2 + github.com/compose-spec/compose-go/v2 v2.4.3 github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index d11537c752a..e1f42e56b8f 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.4.2 h1:RaZv+ZKZVNmxi4Cww1EKiJRLSZLiqVxIqhLUdH92dz4= -github.com/compose-spec/compose-go/v2 v2.4.2/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.4.3 h1:4+Nd9IqIGobbPles9ZuRS5uJfFfRgBo4Wdcv+8VNex8= +github.com/compose-spec/compose-go/v2 v2.4.3/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= From 465b52caab645032ed0c599c09ea4cea196c4b90 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 31 Oct 2024 12:55:25 +0100 Subject: [PATCH 0906/1066] Enable image_remove tests to run on windows Signed-off-by: apostasie --- cmd/nerdctl/image/image_remove_test.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cmd/nerdctl/image/image_remove_test.go b/cmd/nerdctl/image/image_remove_test.go index f94b0e71e57..5771ac4c07c 100644 --- a/cmd/nerdctl/image/image_remove_test.go +++ b/cmd/nerdctl/image/image_remove_test.go @@ -43,7 +43,6 @@ func TestRemove(t *testing.T) { Description: "Remove image with stopped container - without -f", NoParallel: true, Require: test.Require( - test.Not(test.Windows), test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { @@ -68,7 +67,6 @@ func TestRemove(t *testing.T) { { Description: "Remove image with stopped container - with -f", NoParallel: true, - Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("run", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage) }, @@ -90,7 +88,6 @@ func TestRemove(t *testing.T) { Description: "Remove image with running container - without -f", NoParallel: true, Require: test.Require( - test.Not(test.Windows), test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { @@ -121,7 +118,6 @@ func TestRemove(t *testing.T) { // untags `imageName` (left a `` image) without deletion; `docker rmi -rf imageID` fails. // In both cases, `nerdctl rmi -f` will fail. Require: test.Require( - test.Not(test.Windows), test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { @@ -146,7 +142,6 @@ func TestRemove(t *testing.T) { { Description: "Remove image with created container - without -f", NoParallel: true, - Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("create", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) }, @@ -169,7 +164,6 @@ func TestRemove(t *testing.T) { { Description: "Remove image with created container - with -f", NoParallel: true, - Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("pull", "--quiet", testutil.NginxAlpineImage) helpers.Ensure("create", "--pull", "always", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) @@ -197,7 +191,6 @@ func TestRemove(t *testing.T) { Description: "Remove image with paused container - without -f", NoParallel: true, Require: test.Require( - test.Not(test.Windows), test.Not(nerdtest.Docker), nerdtest.CGroup, ), @@ -225,7 +218,6 @@ func TestRemove(t *testing.T) { Description: "Remove image with paused container - with -f", NoParallel: true, Require: test.Require( - test.Not(test.Windows), nerdtest.CGroup, // FIXME: nerdctl is broken // https://github.com/containerd/nerdctl/issues/3454 @@ -258,7 +250,6 @@ func TestRemove(t *testing.T) { Description: "Remove image with killed container - without -f", NoParallel: true, Require: test.Require( - test.Not(test.Windows), test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { @@ -284,7 +275,6 @@ func TestRemove(t *testing.T) { { Description: "Remove image with killed container - with -f", NoParallel: true, - Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("kill", data.Identifier()) From 4623930836c23816cad9ae320494528ceb2021c3 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 31 Oct 2024 13:55:45 +0100 Subject: [PATCH 0907/1066] Enable issues tests to run on Windows Signed-off-by: apostasie --- cmd/nerdctl/issues/main_linux_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/nerdctl/issues/main_linux_test.go b/cmd/nerdctl/issues/main_linux_test.go index c67fa8eb1c1..a1af21d8ff5 100644 --- a/cmd/nerdctl/issues/main_linux_test.go +++ b/cmd/nerdctl/issues/main_linux_test.go @@ -33,8 +33,6 @@ func TestMain(m *testing.M) { func TestIssue108(t *testing.T) { testCase := nerdtest.Setup() - testCase.Require = test.Linux - testCase.SubTests = []*test.Case{ { Description: "-it --net=host", From 93189e13fa0db738ded2c743854520e40c1ca7e6 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 31 Oct 2024 13:59:03 +0100 Subject: [PATCH 0908/1066] Annotate non-windows compatible image tests Signed-off-by: apostasie --- cmd/nerdctl/image/image_convert_linux_test.go | 1 + cmd/nerdctl/image/image_inspect_test.go | 1 + cmd/nerdctl/image/image_save_test.go | 1 + 3 files changed, 3 insertions(+) diff --git a/cmd/nerdctl/image/image_convert_linux_test.go b/cmd/nerdctl/image/image_convert_linux_test.go index 3a202a818ef..6968e5ab7a5 100644 --- a/cmd/nerdctl/image/image_convert_linux_test.go +++ b/cmd/nerdctl/image/image_convert_linux_test.go @@ -31,6 +31,7 @@ func TestImageConvert(t *testing.T) { testCase := &test.Case{ Require: test.Require( + // FIXME: windows does not support stargz test.Not(test.Windows), test.Not(nerdtest.Docker), ), diff --git a/cmd/nerdctl/image/image_inspect_test.go b/cmd/nerdctl/image/image_inspect_test.go index 816b163abbd..4ac86996bd8 100644 --- a/cmd/nerdctl/image/image_inspect_test.go +++ b/cmd/nerdctl/image/image_inspect_test.go @@ -87,6 +87,7 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { testCase := &test.Case{ Require: test.Require( test.Not(nerdtest.Docker), + // FIXME: this test depends on hub images that do not have windows versions test.Not(test.Windows), // We need a clean slate nerdtest.Private, diff --git a/cmd/nerdctl/image/image_save_test.go b/cmd/nerdctl/image/image_save_test.go index 90aa59909d2..3fcb9b8ceef 100644 --- a/cmd/nerdctl/image/image_save_test.go +++ b/cmd/nerdctl/image/image_save_test.go @@ -35,6 +35,7 @@ func TestSaveContent(t *testing.T) { nerdtest.Setup() testCase := &test.Case{ + // FIXME: move to busybox for windows? Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("pull", "--quiet", testutil.CommonImage) From dc2c7b93f7a947463f91bcc6dd0001bd56794371 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 31 Oct 2024 14:02:24 +0100 Subject: [PATCH 0909/1066] Enable network_inspect tests to run on windows Signed-off-by: apostasie --- cmd/nerdctl/network/network_inspect_test.go | 78 +++++++++++++++------ 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/cmd/nerdctl/network/network_inspect_test.go b/cmd/nerdctl/network/network_inspect_test.go index f7ce5356dca..d493db498fd 100644 --- a/cmd/nerdctl/network/network_inspect_test.go +++ b/cmd/nerdctl/network/network_inspect_test.go @@ -38,6 +38,15 @@ func TestNetworkInspect(t *testing.T) { testIPRange = "10.24.24.0/25" ) + testCase.Setup = func(data test.Data, helpers test.Helpers) { + helpers.Ensure("network", "create", data.Identifier("basenet")) + data.Set("basenet", data.Identifier("basenet")) + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("network", "rm", data.Identifier("basenet")) + } + testCase.SubTests = []*test.Case{ { Description: "non existent network", @@ -87,6 +96,18 @@ func TestNetworkInspect(t *testing.T) { assert.Equal(t, dc[0].Name, "bridge") }), }, + { + Description: "nat", + Require: test.Windows, + Command: test.Command("network", "inspect", "nat"), + Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Equal(t, dc[0].Name, "nat") + }), + }, { Description: "custom", Setup: func(data test.Data, helpers test.Helpers) { @@ -106,45 +127,56 @@ func TestNetworkInspect(t *testing.T) { }, { Description: "match exact id", - Require: test.Not(test.Windows), + // See notes below Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) + id := strings.TrimSpace(helpers.Capture("network", "inspect", data.Get("basenet"), "--format", "{{ .Id }}")) return helpers.Command("network", "inspect", id) }, - Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { - var dc []dockercompat.Network - err := json.Unmarshal([]byte(stdout), &dc) - assert.NilError(t, err, "Unable to unmarshal output\n"+info) - assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) - assert.Equal(t, dc[0].Name, "bridge") - }), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Equal(t, dc[0].Name, data.Get("basenet")) + }, + } + }, }, { Description: "match part of id", - Require: test.Not(test.Windows), + // FIXME: for windows, network inspect testnetworkinspect-basenet-468cf999 --format {{ .Id }} MAY fail here + // This is bizarre, as it is working in the match exact id test - and there does not seem to be a particular reason for that + Require: test.Not(test.Windows), Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { - id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) + id := strings.TrimSpace(helpers.Capture("network", "inspect", data.Get("basenet"), "--format", "{{ .Id }}")) return helpers.Command("network", "inspect", id[0:25]) }, - Expected: test.Expects(0, nil, func(stdout string, info string, t *testing.T) { - var dc []dockercompat.Network - err := json.Unmarshal([]byte(stdout), &dc) - assert.NilError(t, err, "Unable to unmarshal output\n"+info) - assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) - assert.Equal(t, dc[0].Name, "bridge") - }), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var dc []dockercompat.Network + err := json.Unmarshal([]byte(stdout), &dc) + assert.NilError(t, err, "Unable to unmarshal output\n"+info) + assert.Equal(t, 1, len(dc), "Unexpectedly got multiple results\n"+info) + assert.Equal(t, dc[0].Name, data.Get("basenet")) + }, + } + }, }, { Description: "using another net short id", - Require: test.Not(test.Windows), + // FIXME: for windows, network inspect testnetworkinspect-basenet-468cf999 --format {{ .Id }} MAY fail here + // This is bizarre, as it is working in the match exact id test - and there does not seem to be a particular reason for that + Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { - id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) + id := strings.TrimSpace(helpers.Capture("network", "inspect", data.Get("basenet"), "--format", "{{ .Id }}")) helpers.Ensure("network", "create", id[0:12]) data.Set("netname", id[0:12]) }, Cleanup: func(data test.Data, helpers test.Helpers) { - id := strings.TrimSpace(helpers.Capture("network", "inspect", "bridge", "--format", "{{ .Id }}")) - helpers.Anyhow("network", "remove", id[0:12]) + helpers.Anyhow("network", "remove", data.Get("netname")) }, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { return helpers.Command("network", "inspect", data.Get("netname")) @@ -163,7 +195,7 @@ func TestNetworkInspect(t *testing.T) { }, { Description: "basic", - // IPAMConfig is not implemented on Windows yet + // FIXME: IPAMConfig is not implemented on Windows yet Require: test.Not(test.Windows), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("network", "create", "--label", "tag=testNetwork", "--subnet", testSubnet, From b776706a4a9c1e47a31a5d106c7b4b4a6bef60d9 Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Thu, 24 Oct 2024 23:25:28 +0900 Subject: [PATCH 0910/1066] fix: Allow to untag images associated with running or paused containers by nerdctl rmi -f In Docker, running `docker rmi -f ` on images associated with running or stopped containers will untag the images, leaving images. The specific behavior in Docker is as follows. ``` > docker images REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest 91ef0af61f39 6 weeks ago 7.8MB > docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fe4caab5cf42 alpine "sleep infinity" 4 minutes ago Up 4 minutes test > docker rmi -f alpine Untagged: alpine:latest Untagged: alpine@sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d > docker images REPOSITORY TAG IMAGE ID CREATED SIZE 91ef0af61f39 6 weeks ago 7.8MB ``` On the other hand, the same operation described above with nerdctl will result in the following error. ``` > nerdctl rmi -f alpine FATA[0000] 1 errors: conflict: unable to delete alpine (cannot be forced) - image is being used by running container 59261bebc8113ca1ea102203137c32406742c2ec43ca3b108a314e9bfb4657fb ``` This befavior is reported in the following: - https://github.com/containerd/nerdctl/issues/3454 Therefore, this commit fixes it so that `nerdctl rmi -f ` can be performed on images associated with running or stopped containers. The behaviour in nerdctl after this modification is as follows. ``` > nerdctl images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE alpine latest beefdbd8a1da 5 seconds ago linux/amd64 8.458MB 3.626MB > nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 28c9db821576 docker.io/library/alpine:latest "sleep infinity" 6 seconds ago Up alpine-28c9d > nerdctl rmi -f alpine Untagged: docker.io/library/alpine:latest Untagged: sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d > nerdctl images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE beefdbd8a1da 3 seconds ago linux/amd64 8.458MB 3.626MB ``` Signed-off-by: Hayato Kiwata --- cmd/nerdctl/image/image_remove_test.go | 40 +++++++++++++++----------- pkg/cmd/image/remove.go | 13 +++++++++ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/cmd/nerdctl/image/image_remove_test.go b/cmd/nerdctl/image/image_remove_test.go index 5771ac4c07c..ff3d33cbb71 100644 --- a/cmd/nerdctl/image/image_remove_test.go +++ b/cmd/nerdctl/image/image_remove_test.go @@ -32,6 +32,10 @@ import ( func TestRemove(t *testing.T) { testCase := nerdtest.Setup() + const ( + imgShortIDKey = "imgShortID" + ) + repoName, _ := imgutil.ParseRepoTag(testutil.CommonImage) nginxRepoName, _ := imgutil.ParseRepoTag(testutil.NginxAlpineImage) // NOTES: @@ -112,28 +116,30 @@ func TestRemove(t *testing.T) { { Description: "Remove image with running container - with -f", NoParallel: true, - // FIXME: nerdctl is broken - // https://github.com/containerd/nerdctl/issues/3454 - // If an image is associated with a running/paused containers, `docker rmi -f imageName` - // untags `imageName` (left a `` image) without deletion; `docker rmi -rf imageID` fails. - // In both cases, `nerdctl rmi -f` will fail. Require: test.Require( test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) + + img := nerdtest.InspectImage(helpers, testutil.CommonImage) + repoName, _ := imgutil.ParseRepoTag(testutil.CommonImage) + imgShortID := strings.TrimPrefix(img.RepoDigests[0], repoName+"@sha256:")[0:8] + + data.Set(imgShortIDKey, imgShortID) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Get(imgShortIDKey)) }, Command: test.Command("rmi", "-f", testutil.CommonImage), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ - ExitCode: 1, - Errors: []error{errors.New("image is being used")}, + ExitCode: 0, + Errors: []error{}, Output: func(stdout string, info string, t *testing.T) { helpers.Command("images").Run(&test.Expected{ - Output: test.Contains(repoName), + Output: test.Contains(""), }) }, } @@ -219,28 +225,30 @@ func TestRemove(t *testing.T) { NoParallel: true, Require: test.Require( nerdtest.CGroup, - // FIXME: nerdctl is broken - // https://github.com/containerd/nerdctl/issues/3454 - // If an image is associated with a running/paused containers, `docker rmi -f imageName` - // untags `imageName` (left a `` image) without deletion; `docker rmi -rf imageID` fails. - // In both cases, `nerdctl rmi -f` will fail. test.Not(nerdtest.Docker), ), Setup: func(data test.Data, helpers test.Helpers) { helpers.Ensure("run", "--pull", "always", "-d", "--name", data.Identifier(), testutil.CommonImage, "sleep", nerdtest.Infinity) helpers.Ensure("pause", data.Identifier()) + + img := nerdtest.InspectImage(helpers, testutil.CommonImage) + repoName, _ := imgutil.ParseRepoTag(testutil.CommonImage) + imgShortID := strings.TrimPrefix(img.RepoDigests[0], repoName+"@sha256:")[0:8] + + data.Set(imgShortIDKey, imgShortID) }, Cleanup: func(data test.Data, helpers test.Helpers) { helpers.Anyhow("rm", "-f", data.Identifier()) + helpers.Anyhow("rmi", "-f", data.Get(imgShortIDKey)) }, Command: test.Command("rmi", "-f", testutil.CommonImage), Expected: func(data test.Data, helpers test.Helpers) *test.Expected { return &test.Expected{ - ExitCode: 1, - Errors: []error{errors.New("image is being used")}, + ExitCode: 0, + Errors: []error{}, Output: func(stdout string, info string, t *testing.T) { helpers.Command("images").Run(&test.Expected{ - Output: test.Contains(repoName), + Output: test.Contains(""), }) }, } diff --git a/pkg/cmd/image/remove.go b/pkg/cmd/image/remove.go index 3afa2bff80b..8075a928659 100644 --- a/pkg/cmd/image/remove.go +++ b/pkg/cmd/image/remove.go @@ -78,6 +78,19 @@ func Remove(ctx context.Context, client *containerd.Client, args []string, optio } if cid, ok := runningImages[found.Image.Name]; ok { + if options.Force { + if err = is.Delete(ctx, found.Image.Name); err != nil { + return err + } + fmt.Fprintf(options.Stdout, "Untagged: %s\n", found.Image.Name) + fmt.Fprintf(options.Stdout, "Untagged: %s\n", found.Image.Target.Digest.String()) + + found.Image.Name = ":" + if _, err = is.Create(ctx, found.Image); err != nil { + return err + } + return nil + } return fmt.Errorf("conflict: unable to delete %s (cannot be forced) - image is being used by running container %s", found.Req, cid) } if cid, ok := usedImages[found.Image.Name]; ok && !options.Force { From 718e7cd2bc9a6f62197ea0b5c84e0a0edb915481 Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Mon, 4 Nov 2024 18:48:57 +0900 Subject: [PATCH 0911/1066] fix: not to be deleted a container created with --rm when detaching In the current implementation, detaching from a container started with `nerdctl run --rm ...` unexpectedly removes it. The behaviour before this modification is as follows. ``` > nerdctl run --rm -it --detach-keys=ctrl-a,ctrl-b --name test alpine / # INFO[0002] read detach keys > nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ``` When the same operation is performed in the Docker CLI, the container will not be deleted. This issue is reported in the following: - https://github.com/containerd/nerdctl/issues/3568 Therefore, this commit resolves this behaviour of a container not being deleted on detachment. Note that the behaviour after this modification is as follows. ``` > nerdctl run --rm -it --detach-keys=ctrl-a,ctrl-b --name test alpine / # INFO[0010] read detach keys > nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 46f4c829e5cc docker.io/library/alpine:latest "/bin/sh" 15 seconds ago Up test ``` This PR has also been modified to remove a container when detaching and attaching a container started with the --rm option. The detailed behaviour is as follows. ``` > nerdctl attach test / # exit > nerdctl ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ``` Signed-off-by: Hayato Kiwata --- .../container/container_attach_linux_test.go | 55 +++++++++++++++++++ cmd/nerdctl/container/container_run.go | 8 ++- .../container/container_run_linux_test.go | 47 ++++++++++++++++ pkg/cmd/container/attach.go | 26 +++++++++ pkg/cmd/container/create.go | 8 +++ pkg/containerutil/containerutil.go | 10 ++++ pkg/labels/labels.go | 3 + 7 files changed, 156 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/container/container_attach_linux_test.go b/cmd/nerdctl/container/container_attach_linux_test.go index cdd4e689981..8d90897230e 100644 --- a/cmd/nerdctl/container/container_attach_linux_test.go +++ b/cmd/nerdctl/container/container_attach_linux_test.go @@ -24,6 +24,8 @@ import ( "gotest.tools/v3/assert" "github.com/containerd/nerdctl/v2/pkg/testutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) // skipAttachForDocker should be called by attach-related tests that assert 'read detach keys' in stdout. @@ -104,3 +106,56 @@ func TestAttachDetachKeys(t *testing.T) { container := base.InspectContainer(containerName) assert.Equal(base.T, container.State.Running, true) } + +// TestIssue3568 tests https://github.com/containerd/nerdctl/issues/3568 +func TestDetachAttachKeysForAutoRemovedContainer(t *testing.T) { + testCase := nerdtest.Setup() + + testCase.SubTests = []*test.Case{ + { + Description: "Issue #3568 - A container should be deleted when detaching and attaching a container started with the --rm option.", + // In nerdctl the detach return code from the container is 0, but in docker the return code is 1. + // This behaviour is reported in https://github.com/containerd/nerdctl/issues/3571 so this test is skipped for Docker. + Require: test.Require( + test.Not(nerdtest.Docker), + ), + Setup: func(data test.Data, helpers test.Helpers) { + cmd := helpers.Command("run", "--rm", "-it", "--detach-keys=ctrl-a,ctrl-b", "--name", data.Identifier(), testutil.CommonImage) + // unbuffer(1) can be installed with `apt-get install expect`. + // + // "-p" is needed because we need unbuffer to read from stdin, and from [1]: + // "Normally, unbuffer does not read from stdin. This simplifies use of unbuffer in some situations. + // To use unbuffer in a pipeline, use the -p flag." + // + // [1] https://linux.die.net/man/1/unbuffer + cmd.WithWrapper("unbuffer", "-p") + cmd.WithStdin(testutil.NewDelayOnceReader(bytes.NewReader([]byte{1, 2}))) // https://www.physics.udel.edu/~watson/scen103/ascii.html + cmd.Run(&test.Expected{ + ExitCode: 0, + }) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command("attach", data.Identifier()) + cmd.WithWrapper("unbuffer", "-p") + cmd.WithStdin(testutil.NewDelayOnceReader(strings.NewReader("exit\n"))) + return cmd + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Errors: []error{}, + Output: test.All( + func(stdout string, info string, t *testing.T) { + assert.Assert(t, !strings.Contains(helpers.Capture("ps", "-a"), data.Identifier())) + }, + ), + } + }, + }, + } + + testCase.Run(t) +} diff --git a/cmd/nerdctl/container/container_run.go b/cmd/nerdctl/container/container_run.go index f608a915f6c..855d1512cdf 100644 --- a/cmd/nerdctl/container/container_run.go +++ b/cmd/nerdctl/container/container_run.go @@ -334,6 +334,8 @@ func processCreateCommandFlagsInRun(cmd *cobra.Command) (types.ContainerCreateOp // runAction is heavily based on ctr implementation: // https://github.com/containerd/containerd/blob/v1.4.3/cmd/ctr/commands/run/run.go func runAction(cmd *cobra.Command, args []string) error { + var isDetached bool + createOpt, err := processCreateCommandFlagsInRun(cmd) if err != nil { return err @@ -378,8 +380,11 @@ func runAction(cmd *cobra.Command, args []string) error { }() id := c.ID() - if createOpt.Rm && !createOpt.Detach { + if createOpt.Rm { defer func() { + if isDetached { + return + } if err := netManager.CleanupNetworking(ctx, c); err != nil { log.L.Warnf("failed to clean up container networking: %s", err) } @@ -449,6 +454,7 @@ func runAction(cmd *cobra.Command, args []string) error { return errors.New("got a nil IO from the task") } io.Wait() + isDetached = true case status := <-statusC: if createOpt.Rm { if _, taskDeleteErr := task.Delete(ctx); taskDeleteErr != nil { diff --git a/cmd/nerdctl/container/container_run_linux_test.go b/cmd/nerdctl/container/container_run_linux_test.go index 0b16d2363df..dc33702e1bd 100644 --- a/cmd/nerdctl/container/container_run_linux_test.go +++ b/cmd/nerdctl/container/container_run_linux_test.go @@ -40,6 +40,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestRunCustomRootfs(t *testing.T) { @@ -520,3 +521,49 @@ func TestRunWithTtyAndDetached(t *testing.T) { withTtyContainer := base.InspectContainer(withTtyContainerName) assert.Equal(base.T, 0, withTtyContainer.State.ExitCode) } + +// TestIssue3568 tests https://github.com/containerd/nerdctl/issues/3568 +func TestIssue3568(t *testing.T) { + testCase := nerdtest.Setup() + + testCase.SubTests = []*test.Case{ + { + Description: "Issue #3568 - Detaching from a container started by using --rm option causes the container to be deleted.", + // When detaching from a container, for a session started with 'docker attach', it prints 'read escape sequence', but for one started with 'docker (run|start)', it prints nothing. + // However, the flag is called '--detach-keys' in all cases, so nerdctl prints 'read detach keys' for all cases, and that's why this test is skipped for Docker. + Require: test.Require( + test.Not(nerdtest.Docker), + ), + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + cmd := helpers.Command("run", "--rm", "-it", "--detach-keys=ctrl-a,ctrl-b", "--name", data.Identifier(), testutil.CommonImage) + // unbuffer(1) can be installed with `apt-get install expect`. + // + // "-p" is needed because we need unbuffer to read from stdin, and from [1]: + // "Normally, unbuffer does not read from stdin. This simplifies use of unbuffer in some situations. + // To use unbuffer in a pipeline, use the -p flag." + // + // [1] https://linux.die.net/man/1/unbuffer + cmd.WithWrapper("unbuffer", "-p") + cmd.WithStdin(testutil.NewDelayOnceReader(bytes.NewReader([]byte{1, 2}))) // https://www.physics.udel.edu/~watson/scen103/ascii.html + return cmd + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Errors: []error{}, + Output: test.All( + test.Contains("read detach keys"), + func(stdout string, info string, t *testing.T) { + assert.Assert(t, strings.Contains(helpers.Capture("ps"), data.Identifier())) + }, + ), + } + }, + }, + } + + testCase.Run(t) +} diff --git a/pkg/cmd/container/attach.go b/pkg/cmd/container/attach.go index fbbddafcb40..177a9fd03db 100644 --- a/pkg/cmd/container/attach.go +++ b/pkg/cmd/container/attach.go @@ -28,8 +28,10 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/consoleutil" + "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/errutil" "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" + "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/signalutil" ) @@ -37,6 +39,8 @@ import ( func Attach(ctx context.Context, client *containerd.Client, req string, options types.ContainerAttachOptions) error { // Find the container. var container containerd.Container + var cStatus containerd.Status + walker := &containerwalker.ContainerWalker{ Client: client, OnFound: func(ctx context.Context, found containerwalker.Found) error { @@ -54,6 +58,24 @@ func Attach(ctx context.Context, client *containerd.Client, req string, options return fmt.Errorf("more than one containers are found given the string: %s", req) } + defer func() { + containerLabels, err := container.Labels(ctx) + if err != nil { + log.G(ctx).WithError(err).Errorf("failed to getting container labels: %s", err) + return + } + rm, err := containerutil.DecodeContainerRmOptLabel(containerLabels[labels.ContainerAutoRemove]) + if err != nil { + log.G(ctx).WithError(err).Errorf("failed to decode string to bool value: %s", err) + return + } + if rm && cStatus.Status == containerd.Stopped { + if err = RemoveContainer(ctx, container, options.GOptions, true, true, client); err != nil { + log.L.WithError(err).Warnf("failed to remove container %s: %s", req, err) + } + } + }() + // Attach to the container. var task containerd.Task detachC := make(chan struct{}) @@ -129,6 +151,10 @@ func Attach(ctx context.Context, client *containerd.Client, req string, options } io.Wait() case status := <-statusC: + cStatus, err = task.Status(ctx) + if err != nil { + return err + } code, _, err := status.Result() if err != nil { return err diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index b0effcff12d..c5c6e222820 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -340,6 +340,8 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa } } + internalLabels.rm = containerutil.EncodeContainerRmOptLabel(options.Rm) + // TODO: abolish internal labels and only use annotations ilOpt, err := withInternalLabels(internalLabels) if err != nil { @@ -655,6 +657,8 @@ type internalLabels struct { ipc string // log logURI string + // a label to check whether the --rm option is specified. + rm string } // WithInternalLabels sets the internal labels for a container. @@ -732,6 +736,10 @@ func withInternalLabels(internalLabels internalLabels) (containerd.NewContainerO m[labels.IPC] = internalLabels.ipc } + if internalLabels.rm != "" { + m[labels.ContainerAutoRemove] = internalLabels.rm + } + return containerd.WithAdditionalContainerLabels(m), nil } diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 814156117fc..8f215ecf679 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -600,3 +600,13 @@ func GetContainerName(containerLabels map[string]string) string { } return "" } + +// EncodeContainerRmOptLabel encodes bool value for the --rm option into string value for a label. +func EncodeContainerRmOptLabel(rmOpt bool) string { + return fmt.Sprintf("%t", rmOpt) +} + +// DecodeContainerRmOptLabel decodes bool value for the --rm option from string value for a label. +func DecodeContainerRmOptLabel(rmOptLabel string) (bool, error) { + return strconv.ParseBool(rmOptLabel) +} diff --git a/pkg/labels/labels.go b/pkg/labels/labels.go index d88aee02a7d..e470c7230dc 100644 --- a/pkg/labels/labels.go +++ b/pkg/labels/labels.go @@ -100,4 +100,7 @@ const ( // Boolean value which can be parsed with strconv.ParseBool() is required. // (like "nerdctl/default-network=true" or "nerdctl/default-network=false") NerdctlDefaultNetwork = Prefix + "default-network" + + // ContainerAutoRemove is to check whether the --rm option is specified. + ContainerAutoRemove = Prefix + "auto-remove" ) From c607537eb75d5373091b820767440ade3224c283 Mon Sep 17 00:00:00 2001 From: Arjun Raja Yogidas Date: Fri, 1 Nov 2024 16:39:44 +0000 Subject: [PATCH 0912/1066] add 'none' logger Signed-off-by: Arjun Raja Yogidas --- pkg/logging/log_viewer.go | 4 ++ pkg/logging/logging.go | 3 ++ pkg/logging/none_logger.go | 45 +++++++++++++++++++++ pkg/logging/none_logger_test.go | 72 +++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+) create mode 100644 pkg/logging/none_logger.go create mode 100644 pkg/logging/none_logger_test.go diff --git a/pkg/logging/log_viewer.go b/pkg/logging/log_viewer.go index b2741273450..7cbc0292edf 100644 --- a/pkg/logging/log_viewer.go +++ b/pkg/logging/log_viewer.go @@ -135,6 +135,10 @@ func InitContainerLogViewer(containerLabels map[string]string, lvopts LogViewOpt return nil, fmt.Errorf("the `cri` log viewer requires nerdctl to be running in experimental mode") } + if lcfg.Driver == "none" { + return nil, fmt.Errorf("log type `none` was selected, nothing to log") + } + lv := &ContainerLogViewer{ loggingConfig: lcfg, logViewingOptions: lvopts, diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index 0a42cbb21be..318e3496e6b 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -90,6 +90,9 @@ func GetDriver(name string, opts map[string]string) (Driver, error) { } func init() { + RegisterDriver("none", func(opts map[string]string) (Driver, error) { + return &NoneLogger{}, nil + }, NoneLogOptsValidate) RegisterDriver("json-file", func(opts map[string]string) (Driver, error) { return &JSONLogger{Opts: opts}, nil }, JSONFileLogOptsValidate) diff --git a/pkg/logging/none_logger.go b/pkg/logging/none_logger.go new file mode 100644 index 00000000000..57d7e1c1b34 --- /dev/null +++ b/pkg/logging/none_logger.go @@ -0,0 +1,45 @@ +/* + 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 logging + +import ( + "github.com/containerd/containerd/v2/core/runtime/v2/logging" +) + +type NoneLogger struct { + Opts map[string]string +} + +func (n *NoneLogger) Init(dataStore, ns, id string) error { + return nil +} + +func (n *NoneLogger) PreProcess(dataStore string, config *logging.Config) error { + return nil +} + +func (n *NoneLogger) Process(stdout <-chan string, stderr <-chan string) error { + return nil +} + +func (n *NoneLogger) PostProcess() error { + return nil +} + +func NoneLogOptsValidate(_ map[string]string) error { + return nil +} diff --git a/pkg/logging/none_logger_test.go b/pkg/logging/none_logger_test.go new file mode 100644 index 00000000000..88e35b72d3c --- /dev/null +++ b/pkg/logging/none_logger_test.go @@ -0,0 +1,72 @@ +/* + 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 logging + +import ( + "os" + "testing" + "time" + + "gotest.tools/v3/assert" + + "github.com/containerd/containerd/v2/core/runtime/v2/logging" +) + +func TestNoneLogger(t *testing.T) { + // Create a temporary directory for potential log files + tmpDir := t.TempDir() + + logger := &NoneLogger{ + Opts: map[string]string{}, + } + + t.Run("NoLoggingOccurs", func(t *testing.T) { + initialFiles, err := os.ReadDir(tmpDir) + assert.NilError(t, err, "Failed to read temp dir") + + // Run all logger methods + logger.Init(tmpDir, "namespace", "id") + logger.PreProcess(tmpDir, &logging.Config{}) + + stdout := make(chan string) + stderr := make(chan string) + + go func() { + for i := 0; i < 10; i++ { + stdout <- "test stdout" + stderr <- "test stderr" + } + close(stdout) + close(stderr) + }() + + err = logger.Process(stdout, stderr) + assert.NilError(t, err, "Process() returned unexpected error") + + logger.PostProcess() + + // Wait a bit to ensure any potential writes would have occurred + time.Sleep(100 * time.Millisecond) + + // Check if any new files were created + afterFiles, err := os.ReadDir(tmpDir) + assert.NilError(t, err, "Failed to read temp dir after operations") + + assert.Equal(t, len(afterFiles), len(initialFiles), "Expected no new files, but directory content changed") + + }) +} From 83088ef88f243771867638de3c5c9432c4807d92 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 22:10:43 +0000 Subject: [PATCH 0913/1066] build(deps): bump github.com/containerd/errdefs from 0.3.0 to 1.0.0 Bumps [github.com/containerd/errdefs](https://github.com/containerd/errdefs) from 0.3.0 to 1.0.0. - [Release notes](https://github.com/containerd/errdefs/releases) - [Commits](https://github.com/containerd/errdefs/compare/v0.3.0...v1.0.0) --- updated-dependencies: - dependency-name: github.com/containerd/errdefs dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 583b9f1c560..3712c8b3a48 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/containerd/containerd/api v1.8.0-rc.4 github.com/containerd/containerd/v2 v2.0.0-rc.6 github.com/containerd/continuity v0.4.4 - github.com/containerd/errdefs v0.3.0 + github.com/containerd/errdefs v1.0.0 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.10 github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 diff --git a/go.sum b/go.sum index a699d084d32..1af897e07da 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ github.com/containerd/containerd/v2 v2.0.0-rc.6 h1:uIUmoiXH770KCkTzzqksSpQg7JZ4t github.com/containerd/containerd/v2 v2.0.0-rc.6/go.mod h1:O+llF4jv6jUxQC6J44UMzpeKI30yhdwkcsL7kUlCyek= github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= -github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4= -github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= +github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= +github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= From 68bd32d7ac964be0d798685fc472e5ae480eafad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 22:43:41 +0000 Subject: [PATCH 0914/1066] build(deps): bump actions/checkout from 4.2.1 to 4.2.2 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.1 to 4.2.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.1...v4.2.2) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 57a09ce86ee..6a491d555e4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: CONTAINERD_VERSION: "${{ matrix.containerd }}" ARCH: "${{ matrix.arch }}" steps: - - uses: actions/checkout@v4.2.1 + - uses: actions/checkout@v4.2.2 with: fetch-depth: 1 - name: "Expose GitHub Runtime variables for gha" From 8ea1d0ac9e22a8c7f11a7720c4ea3f484cc0ff4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 01:32:49 +0000 Subject: [PATCH 0915/1066] build(deps): bump github.com/containerd/containerd/api Bumps the containerd group with 1 update: [github.com/containerd/containerd/api](https://github.com/containerd/containerd). Updates `github.com/containerd/containerd/api` from 1.8.0-rc.4 to 1.8.0 - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/api/v1.8.0-rc.4...api/v1.8.0) --- updated-dependencies: - dependency-name: github.com/containerd/containerd/api dependency-type: direct:production update-type: version-update:semver-patch dependency-group: containerd ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3712c8b3a48..8c91ce95e24 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 - github.com/containerd/containerd/api v1.8.0-rc.4 + github.com/containerd/containerd/api v1.8.0 github.com/containerd/containerd/v2 v2.0.0-rc.6 github.com/containerd/continuity v0.4.4 github.com/containerd/errdefs v1.0.0 diff --git a/go.sum b/go.sum index 1af897e07da..06a3bbe8d7f 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGD github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= 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/api v1.8.0-rc.4 h1:Z650GHP0OxsoTwwii5U2hyTt7eCRQvvDnRM7pEH/DE0= -github.com/containerd/containerd/api v1.8.0-rc.4/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= +github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= +github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/v2 v2.0.0-rc.6 h1:uIUmoiXH770KCkTzzqksSpQg7JZ4tC0eM2qXm5EAuwI= github.com/containerd/containerd/v2 v2.0.0-rc.6/go.mod h1:O+llF4jv6jUxQC6J44UMzpeKI30yhdwkcsL7kUlCyek= github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= From b006beb55e2344e2d02d7c6788b1a67ef536a2c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:43:23 +0000 Subject: [PATCH 0916/1066] build(deps): bump github.com/containerd/typeurl/v2 from 2.2.1 to 2.2.2 Bumps [github.com/containerd/typeurl/v2](https://github.com/containerd/typeurl) from 2.2.1 to 2.2.2. - [Release notes](https://github.com/containerd/typeurl/releases) - [Commits](https://github.com/containerd/typeurl/compare/v2.2.1...v2.2.2) --- updated-dependencies: - dependency-name: github.com/containerd/typeurl/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8c91ce95e24..14ce28b09ac 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319 github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319 - github.com/containerd/typeurl/v2 v2.2.1 + github.com/containerd/typeurl/v2 v2.2.2 github.com/containernetworking/cni v1.2.3 github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.8.0 diff --git a/go.sum b/go.sum index 06a3bbe8d7f..ff1a68574d5 100644 --- a/go.sum +++ b/go.sum @@ -65,8 +65,8 @@ github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89 github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:L/J/O36DzcGxq3drHM45sJRr/pEQTG5u+tbffVhP6r8= github.com/containerd/ttrpc v1.2.6-0.20240827082320-b5cd6e4b3287 h1:zwv64tCdT888KxuXQuv5i36cEdljoXq3sVqLmOEbCQI= github.com/containerd/ttrpc v1.2.6-0.20240827082320-b5cd6e4b3287/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= -github.com/containerd/typeurl/v2 v2.2.1 h1:/X1Kgcz4sKS/NTKQvvRS0pEVpUYqmPTwGQontm9pl0w= -github.com/containerd/typeurl/v2 v2.2.1/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= +github.com/containerd/typeurl/v2 v2.2.2 h1:3jN/k2ysKuPCsln5Qv8bzR9cxal8XjkxPogJfSNO31k= +github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= From ccbaf82a70d825f9e92c2cee185b686cb994ac9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:22:48 +0000 Subject: [PATCH 0917/1066] build(deps): bump github.com/containerd/containerd/v2 Bumps [github.com/containerd/containerd/v2](https://github.com/containerd/containerd) from 2.0.0-rc.6 to 2.0.0. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v2.0.0-rc.6...v2.0.0) --- updated-dependencies: - dependency-name: github.com/containerd/containerd/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 14ce28b09ac..f3e0e8bcbb3 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0 - github.com/containerd/containerd/v2 v2.0.0-rc.6 + github.com/containerd/containerd/v2 v2.0.0 github.com/containerd/continuity v0.4.4 github.com/containerd/errdefs v1.0.0 github.com/containerd/fifo v1.1.0 @@ -24,7 +24,7 @@ require ( github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.14.1-0.20240806063146-8fa319bfe9c5 - github.com/containerd/platforms v0.2.1 + github.com/containerd/platforms v1.0.0-rc.0 github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319 github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319 @@ -83,8 +83,8 @@ require ( github.com/cilium/ebpf v0.16.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/go-runc v1.1.0 // indirect - github.com/containerd/plugin v0.1.0 // indirect - github.com/containerd/ttrpc v1.2.6-0.20240827082320-b5cd6e4b3287 // indirect + github.com/containerd/plugin v1.0.0 // indirect + github.com/containerd/ttrpc v1.2.6 // indirect github.com/containers/ocicrypt v1.2.0 // indirect github.com/djherbis/times v1.6.0 // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect diff --git a/go.sum b/go.sum index ff1a68574d5..d65c2649553 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,8 @@ github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= -github.com/containerd/containerd/v2 v2.0.0-rc.6 h1:uIUmoiXH770KCkTzzqksSpQg7JZ4tC0eM2qXm5EAuwI= -github.com/containerd/containerd/v2 v2.0.0-rc.6/go.mod h1:O+llF4jv6jUxQC6J44UMzpeKI30yhdwkcsL7kUlCyek= +github.com/containerd/containerd/v2 v2.0.0 h1:qLDdFaAykQrIyLiqwQrNLLz95wiC36bAZVwioUwqShM= +github.com/containerd/containerd/v2 v2.0.0/go.mod h1:j25kDy9P48/ngb1sxWIFfK6GsnqOHoSqo1EpAod20VQ= github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -53,18 +53,18 @@ 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.14.1-0.20240806063146-8fa319bfe9c5 h1:NpscnGdkmWwlb0o2Q+rDO/kfoLObfY2sHwB6M5uF58Q= github.com/containerd/nydus-snapshotter v0.14.1-0.20240806063146-8fa319bfe9c5/go.mod h1:t7X6QEMNSz69fl5e2pF56ibd4XJ6KH9dEBrLnSwyYQk= -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/plugin v0.1.0 h1:CYMyZk9beRAIe1FEKItbMLLAz/z16aXrGc+B+nv0fU4= -github.com/containerd/plugin v0.1.0/go.mod h1:j6HlpMtkiZMgT4UsfVNxPBUkwdw9KQGU6nCLfRxnq+w= +github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA= +github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= +github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= +github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 h1:Td/dlhRp/kIk9W1rjXHSL87zZZiBQaKPV18OnoEREUA= github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:dgo5lVziOOnWX8SxxHqYuc8ShsQou54eKLdahxFlHVc= github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319 h1:BRxgmkGWi5vAvajiCwEK+xit4FeFU3GRjbiX4DKTLtM= github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:9WSor0wu2swhtYoFkrjy3GHt7aNgKR2A7FhnpP+CH5o= github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319 h1:WdmIerlurjZSoLI2w8014yzJY+q4qdO/A3ZJBEK7LQA= github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:L/J/O36DzcGxq3drHM45sJRr/pEQTG5u+tbffVhP6r8= -github.com/containerd/ttrpc v1.2.6-0.20240827082320-b5cd6e4b3287 h1:zwv64tCdT888KxuXQuv5i36cEdljoXq3sVqLmOEbCQI= -github.com/containerd/ttrpc v1.2.6-0.20240827082320-b5cd6e4b3287/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= +github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= +github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl/v2 v2.2.2 h1:3jN/k2ysKuPCsln5Qv8bzR9cxal8XjkxPogJfSNO31k= github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= From 75be32df7e7359fbbcd2376a9038eead0ca1f6d8 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 6 Nov 2024 08:27:23 +0900 Subject: [PATCH 0918/1066] update containerd (2.0.0) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 12 ++++++------ Dockerfile | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6a491d555e4..b9a1f3c4f83 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,10 +31,10 @@ jobs: containerd: v1.7.23 arch: amd64 - runner: ubuntu-24.04 - containerd: v2.0.0-rc.5 + containerd: v2.0.0 arch: amd64 - runner: arm64-8core-32gb - containerd: v2.0.0-rc.5 + containerd: v2.0.0 arch: arm64 env: CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -114,11 +114,11 @@ jobs: runner: "ubuntu-22.04" arch: amd64 - ubuntu: 24.04 - containerd: v2.0.0-rc.5 + containerd: v2.0.0 runner: "ubuntu-24.04" arch: amd64 - ubuntu: 24.04 - containerd: v2.0.0-rc.5 + containerd: v2.0.0 runner: arm64-8core-32gb arch: arm64 env: @@ -168,7 +168,7 @@ jobs: matrix: include: - ubuntu: 24.04 - containerd: v2.0.0-rc.5 + containerd: v2.0.0 arch: amd64 env: CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -240,7 +240,7 @@ jobs: target: rootless arch: amd64 - ubuntu: 24.04 - containerd: v2.0.0-rc.5 + containerd: v2.0.0 rootlesskit: v2.3.1 target: rootless arch: amd64 diff --git a/Dockerfile b/Dockerfile index 71ec06a0ea3..9fd0a129e5e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v2.0.0-rc.6 +ARG CONTAINERD_VERSION=v2.0.0 ARG RUNC_VERSION=v1.2.0 ARG CNI_PLUGINS_VERSION=v1.6.0 From 4f64af98db880e57d7c5088b07ce4f15f736c2b2 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 6 Nov 2024 08:28:00 +0900 Subject: [PATCH 0919/1066] update runc (1.2.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9fd0a129e5e..74a73823356 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v2.0.0 -ARG RUNC_VERSION=v1.2.0 +ARG RUNC_VERSION=v1.2.1 ARG CNI_PLUGINS_VERSION=v1.6.0 # Extra deps: Build From 2380710b3b6e5711cbdd2005f05ea4046b63790c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 6 Nov 2024 08:29:52 +0900 Subject: [PATCH 0920/1066] update BuildKit (0.17.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.16.0 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.0 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.16.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.0 diff --git a/Dockerfile b/Dockerfile index 74a73823356..1f9176c5b28 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.2.1 ARG CNI_PLUGINS_VERSION=v1.6.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.16.0 +ARG BUILDKIT_VERSION=v0.17.0 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.16.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.16.0 deleted file mode 100644 index d150cc6c876..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.16.0 +++ /dev/null @@ -1,2 +0,0 @@ -a07a01da821d39bdb6e03a2f98ee407bb861cc61ece2e69e2ea4d61b3a4ab7f1 buildkit-v0.16.0.linux-amd64.tar.gz -1b70bb7955ddda66537d4bf9aa540e79e79e19aa989901613da58f5f133a53ef buildkit-v0.16.0.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.0 new file mode 100644 index 00000000000..7209867ca99 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.0 @@ -0,0 +1,2 @@ +3a9fea5977df76e9008fa5fb3d9b5dd581729e8adced2180a45bd3c12a4d1331 buildkit-v0.17.0.linux-amd64.tar.gz +5ec19fe78eeef2c03bef216d6890f05901fc117e7a66f88b423268dfcf5cf4af buildkit-v0.17.0.linux-arm64.tar.gz From 29f3ff63653856a475f6730a1a339461ecabc3bf Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 6 Nov 2024 08:32:51 +0900 Subject: [PATCH 0921/1066] update containerd-fuse-overlayfs (2.0.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.8 | 6 ------ Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.0.0 | 6 ++++++ 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.8 create mode 100644 Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.0.0 diff --git a/Dockerfile b/Dockerfile index 1f9176c5b28..d2c303c2e5f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ ARG SLIRP4NETNS_VERSION=v1.3.1 ARG BYPASS4NETNS_VERSION=v0.4.1 # Extra deps: FUSE-OverlayFS ARG FUSE_OVERLAYFS_VERSION=v1.14 -ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v1.0.8 +ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v2.0.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug diff --git a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.8 b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.8 deleted file mode 100644 index 1a5d72b95dc..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v1.0.8 +++ /dev/null @@ -1,6 +0,0 @@ -a831f236299007bd1078e49df2e45ad0aeee47c5ed099852ad5f6791b091d536 containerd-fuse-overlayfs-1.0.8-linux-amd64.tar.gz -d0fd1fd92ee9ef03050aa759f197b50c46bca81a75bed65b4433b6213a145022 containerd-fuse-overlayfs-1.0.8-linux-arm-v7.tar.gz -17a3a83ae92002dce8ebe41e6a10877ac5d417550d63939c74fc22b0be6ca04a containerd-fuse-overlayfs-1.0.8-linux-arm64.tar.gz -dddaea552594166eb4edef8adabe765b2fae099574b7afe47657fc87674c81db containerd-fuse-overlayfs-1.0.8-linux-ppc64le.tar.gz -d6846b4bf1500cc2dbd29e382ba8b1f2268bdbfc5358a48d17131b8108f97aa9 containerd-fuse-overlayfs-1.0.8-linux-riscv64.tar.gz -492ce81ed25a9b8b3c64d807d3e0f7de6011e70dc11915df8aef64a77fa67fb9 containerd-fuse-overlayfs-1.0.8-linux-s390x.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.0.0 b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.0.0 new file mode 100644 index 00000000000..b6912d6b20b --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.0.0 @@ -0,0 +1,6 @@ +dc20341234be8fa44e1308c9f38e30d7239c12350a046c83f4d1c804b682fe6c containerd-fuse-overlayfs-2.0.0-linux-amd64.tar.gz +acfaa3a2caa6316b2c409bcb1c2600b6faee504188c412df8261024435dbfefc containerd-fuse-overlayfs-2.0.0-linux-arm-v7.tar.gz +8b8032a4e0d16aedf7797818944147cebefad32e6657e0b7089501bcfc732e57 containerd-fuse-overlayfs-2.0.0-linux-arm64.tar.gz +b4603139b2a532ac9ed8df3197669d3df5dfd9bebda2aa5f507ad6e6dbb1ed77 containerd-fuse-overlayfs-2.0.0-linux-ppc64le.tar.gz +9e169b401e063cfb0b7b192f911dcb2532ec86a64844d8c052e076fe692017c3 containerd-fuse-overlayfs-2.0.0-linux-riscv64.tar.gz +e8dfe8e2aff5b32f2f5698909baadd0cb36aa85704ff8c568f6bcae186e0ccc5 containerd-fuse-overlayfs-2.0.0-linux-s390x.tar.gz From 7103b54b2fa14a5087a21449322db07a13266a73 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Wed, 6 Nov 2024 08:33:43 +0900 Subject: [PATCH 0922/1066] update SOCI snapshotter (0.8.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d2c303c2e5f..4892f0b911e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ ARG UBUNTU_VERSION=24.04 ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.12.0 ARG NYDUS_VERSION=v2.3.0 -ARG SOCI_SNAPSHOTTER_VERSION=0.7.0 +ARG SOCI_SNAPSHOTTER_VERSION=0.8.0 ARG KUBO_VERSION=v0.31.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0 AS xx From 84cea6590d22e5dc65e8411fa28a603a907efe26 Mon Sep 17 00:00:00 2001 From: xyz-li Date: Wed, 6 Nov 2024 11:06:22 +0800 Subject: [PATCH 0923/1066] [fix] avoid escaping '<', '>', '&' json.Encode will escase characters like '<', '>', '&' Signed-off-by: xyz-li --- pkg/formatter/common.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/formatter/common.go b/pkg/formatter/common.go index 60d550dc44e..18cd6e6ca45 100644 --- a/pkg/formatter/common.go +++ b/pkg/formatter/common.go @@ -42,11 +42,16 @@ func FormatSlice(format string, writer io.Writer, x []interface{}) error { var tmpl *template.Template switch format { case "": - b, err := json.MarshalIndent(x, "", " ") + // Avoid escaping "<", ">", "&" + // https://pkg.go.dev/encoding/json + encoder := json.NewEncoder(writer) + encoder.SetIndent("", " ") + encoder.SetEscapeHTML(false) + err := encoder.Encode(x) if err != nil { return err } - fmt.Fprintln(writer, string(b)) + fmt.Fprint(writer, "\n") case "raw", "table", "wide": return errors.New("unsupported format: \"raw\", \"table\", and \"wide\"") default: From 7e89bd3df9e57e949220f66e8f19f938d5e4a8d6 Mon Sep 17 00:00:00 2001 From: qiaohao Date: Wed, 6 Nov 2024 16:41:46 +0800 Subject: [PATCH 0924/1066] typo: remove extra colons and whitespaces #3650 Signed-off-by: qiaohao --- pkg/cmd/system/info.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/system/info.go b/pkg/cmd/system/info.go index 50d65c63dea..1dea6482e12 100644 --- a/pkg/cmd/system/info.go +++ b/pkg/cmd/system/info.go @@ -154,7 +154,7 @@ func prettyPrintInfoDockerCompat(stdout io.Writer, stderr io.Writer, info *docke // Storage Driver is not really Server concept for nerdctl, but mimics `docker info` output fmt.Fprintf(w, " Storage Driver: %s\n", info.Driver) fmt.Fprintf(w, " Logging Driver: %s\n", info.LoggingDriver) - printF(w, " Cgroup Driver: ", info.CgroupDriver) + printF(w, " Cgroup Driver: ", info.CgroupDriver) printF(w, " Cgroup Version: ", info.CgroupVersion) fmt.Fprintf(w, " Plugins:\n") fmt.Fprintf(w, " Log: %s\n", strings.Join(info.Plugins.Log, " ")) @@ -183,7 +183,7 @@ func printF(w io.Writer, label string, dockerCompatInfo string) { if dockerCompatInfo == "" { return } - fmt.Fprintf(w, " %s: %s\n", label, dockerCompatInfo) + fmt.Fprintf(w, " %s%s\n", label, dockerCompatInfo) } func printSecurityOptions(w io.Writer, securityOptions []string) { @@ -208,7 +208,7 @@ func printSecurityOptions(w io.Writer, securityOptions []string) { if k == "name" { continue } - fmt.Fprintf(w, " %s:\t%s\n", cases.Title(language.English).String(k), v) + fmt.Fprintf(w, " %s: %s\n", cases.Title(language.English).String(k), v) } } } From 417b61703b4069caa96bde924e0fa25142b0f0f9 Mon Sep 17 00:00:00 2001 From: qiaohao Date: Thu, 7 Nov 2024 08:46:32 +0800 Subject: [PATCH 0925/1066] typo: remove extra spaces at the lead #3650 #3651 Signed-off-by: qiaohao --- pkg/cmd/system/info.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/system/info.go b/pkg/cmd/system/info.go index 1dea6482e12..2d3e6e194b1 100644 --- a/pkg/cmd/system/info.go +++ b/pkg/cmd/system/info.go @@ -183,7 +183,7 @@ func printF(w io.Writer, label string, dockerCompatInfo string) { if dockerCompatInfo == "" { return } - fmt.Fprintf(w, " %s%s\n", label, dockerCompatInfo) + fmt.Fprintf(w, "%s%s\n", label, dockerCompatInfo) } func printSecurityOptions(w io.Writer, securityOptions []string) { From 6f2e032641731cdd6231cc3689821e49180c98b2 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 7 Nov 2024 11:10:07 +0900 Subject: [PATCH 0926/1066] Mark `nerdctl builder debug` as incompatible with Docker Close issue 3652 Signed-off-by: Akihiro Suda --- cmd/nerdctl/builder/builder_builder_test.go | 4 +++- docs/command-reference.md | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/nerdctl/builder/builder_builder_test.go b/cmd/nerdctl/builder/builder_builder_test.go index 9cb34d5e886..f1092680a40 100644 --- a/cmd/nerdctl/builder/builder_builder_test.go +++ b/cmd/nerdctl/builder/builder_builder_test.go @@ -71,7 +71,9 @@ CMD ["echo", "nerdctl-test-builder-prune"]`, testutil.CommonImage) }, { Description: "Debug", - NoParallel: true, + // `nerdctl builder debug` is currently incompatible with `docker buildx debug`. + Require: test.Require(test.Not(nerdtest.Docker)), + NoParallel: true, Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-builder-debug-test-string"]`, testutil.CommonImage) diff --git a/docs/command-reference.md b/docs/command-reference.md index 1bd141aecc1..95dfddcfd45 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1260,6 +1260,8 @@ This is an [experimental](./experimental.md) feature. :warning: This command currently doesn't use the host's `buildkitd` daemon but uses the patched version of BuildKit provided by buildg. This should be fixed in the future. +:warning: This command is currently incompatible with `docker buildx debug`. + Usage: `nerdctl builder debug PATH` Flags: From d30f66e190dfaed4ecf59ca472ac122777076213 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Nov 2024 05:06:01 +0000 Subject: [PATCH 0927/1066] build(deps): bump github.com/vishvananda/netns from 0.0.4 to 0.0.5 Bumps [github.com/vishvananda/netns](https://github.com/vishvananda/netns) from 0.0.4 to 0.0.5. - [Release notes](https://github.com/vishvananda/netns/releases) - [Commits](https://github.com/vishvananda/netns/compare/v0.0.4...v0.0.5) --- updated-dependencies: - dependency-name: github.com/vishvananda/netns dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index f3e0e8bcbb3..41d93cb9e7b 100644 --- a/go.mod +++ b/go.mod @@ -62,7 +62,7 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/vishvananda/netlink v1.3.0 - github.com/vishvananda/netns v0.0.4 + github.com/vishvananda/netns v0.0.5 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.5.0 golang.org/x/crypto v0.28.0 diff --git a/go.sum b/go.sum index d65c2649553..e0b357fc69f 100644 --- a/go.sum +++ b/go.sum @@ -306,8 +306,9 @@ github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinC github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= -github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= +github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= +github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= From 7d116bf1fd6279bb9d2c3bae03cb66967e0b2fcc Mon Sep 17 00:00:00 2001 From: Swagat Bora Date: Wed, 30 Oct 2024 00:15:05 +0000 Subject: [PATCH 0928/1066] feat: configure custom IP for default bridge network Signed-off-by: Swagat Bora --- cmd/nerdctl/helpers/flagutil.go | 5 + cmd/nerdctl/internal/internal_oci_hook.go | 2 + cmd/nerdctl/main.go | 1 + docs/config.md | 1 + pkg/cmd/compose/compose.go | 2 +- pkg/cmd/container/kill.go | 2 +- pkg/config/config.go | 1 + .../container_network_manager_linux.go | 2 +- .../container_network_manager_windows.go | 4 +- pkg/netutil/netutil.go | 26 +++-- pkg/netutil/netutil_linux_test.go | 1 + pkg/netutil/netutil_test.go | 110 +++++++++++++++++- pkg/ocihook/ocihook.go | 8 +- 13 files changed, 145 insertions(+), 20 deletions(-) diff --git a/cmd/nerdctl/helpers/flagutil.go b/cmd/nerdctl/helpers/flagutil.go index 8e87839b2f9..ef3dd22aada 100644 --- a/cmd/nerdctl/helpers/flagutil.go +++ b/cmd/nerdctl/helpers/flagutil.go @@ -99,6 +99,10 @@ func ProcessRootCmdFlags(cmd *cobra.Command) (types.GlobalCommandOptions, error) if err != nil { return types.GlobalCommandOptions{}, err } + bridgeIP, err := cmd.Flags().GetString("bridge-ip") + if err != nil { + return types.GlobalCommandOptions{}, err + } return types.GlobalCommandOptions{ Debug: debug, DebugFull: debugFull, @@ -113,6 +117,7 @@ func ProcessRootCmdFlags(cmd *cobra.Command) (types.GlobalCommandOptions, error) HostsDir: hostsDir, Experimental: experimental, HostGatewayIP: hostGatewayIP, + BridgeIP: bridgeIP, }, nil } diff --git a/cmd/nerdctl/internal/internal_oci_hook.go b/cmd/nerdctl/internal/internal_oci_hook.go index 404c865804b..31c8e5b910d 100644 --- a/cmd/nerdctl/internal/internal_oci_hook.go +++ b/cmd/nerdctl/internal/internal_oci_hook.go @@ -56,9 +56,11 @@ func internalOCIHookAction(cmd *cobra.Command, args []string) error { } cniPath := globalOptions.CNIPath cniNetconfpath := globalOptions.CNINetConfPath + bridgeIP := globalOptions.BridgeIP return ocihook.Run(os.Stdin, os.Stderr, event, dataStore, cniPath, cniNetconfpath, + bridgeIP, ) } diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 1e086b910d6..50797e5b804 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -183,6 +183,7 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, // Experimental enable experimental feature, see in https://github.com/containerd/nerdctl/blob/main/docs/experimental.md helpers.AddPersistentBoolFlag(rootCmd, "experimental", nil, nil, cfg.Experimental, "NERDCTL_EXPERIMENTAL", "Control experimental: https://github.com/containerd/nerdctl/blob/main/docs/experimental.md") helpers.AddPersistentStringFlag(rootCmd, "host-gateway-ip", nil, nil, nil, aliasToBeInherited, cfg.HostGatewayIP, "NERDCTL_HOST_GATEWAY_IP", "IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the host. It has no effect without setting --add-host") + helpers.AddPersistentStringFlag(rootCmd, "bridge-ip", nil, nil, nil, aliasToBeInherited, cfg.BridgeIP, "NERDCTL_BRIDGE_IP", "IP address for the default nerdctl bridge network") return aliasToBeInherited, nil } diff --git a/docs/config.md b/docs/config.md index 2aca5dbce2c..5820562e176 100644 --- a/docs/config.md +++ b/docs/config.md @@ -45,6 +45,7 @@ experimental = true | `hosts_dir` | `--hosts-dir` | | `certs.d` directory | Since 0.16.0 | | `experimental` | `--experimental` | `NERDCTL_EXPERIMENTAL` | Enable [experimental features](experimental.md) | Since 0.22.3 | | `host_gateway_ip` | `--host-gateway-ip` | `NERDCTL_HOST_GATEWAY_IP` | IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the host. It has no effect without setting --add-host | Since 1.3.0 | +| `bridge_ip` | `--bridge-ip` | `NERDCTL_BRIDGE_IP` | IP address for the default nerdctl bridge network, e.g., 10.1.100.1/24 | Since 2.1.0 | The properties are parsed in the following precedence: 1. CLI flag diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 5dde0b825e4..116858fa8b5 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -65,7 +65,7 @@ func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, op return nil, err } - cniEnv, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath, netutil.WithNamespace(globalOptions.Namespace), netutil.WithDefaultNetwork()) + cniEnv, err := netutil.NewCNIEnv(globalOptions.CNIPath, globalOptions.CNINetConfPath, netutil.WithNamespace(globalOptions.Namespace), netutil.WithDefaultNetwork(globalOptions.BridgeIP)) if err != nil { return nil, err } diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index b077589473d..f986bf184ac 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -154,7 +154,7 @@ func cleanupNetwork(ctx context.Context, container containerd.Container, globalO case nettype.Host, nettype.None, nettype.Container, nettype.Namespace: // NOP case nettype.CNI: - e, err := netutil.NewCNIEnv(globalOpts.CNIPath, globalOpts.CNINetConfPath, netutil.WithNamespace(globalOpts.Namespace), netutil.WithDefaultNetwork()) + e, err := netutil.NewCNIEnv(globalOpts.CNIPath, globalOpts.CNINetConfPath, netutil.WithNamespace(globalOpts.Namespace), netutil.WithDefaultNetwork(globalOpts.BridgeIP)) if err != nil { return err } diff --git a/pkg/config/config.go b/pkg/config/config.go index 7aacfcd0764..e37e9e0134c 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -39,6 +39,7 @@ type Config struct { HostsDir []string `toml:"hosts_dir"` Experimental bool `toml:"experimental"` HostGatewayIP string `toml:"host_gateway_ip"` + BridgeIP string `toml:"bridge_ip, omitempty"` } // New creates a default Config object statically, diff --git a/pkg/containerutil/container_network_manager_linux.go b/pkg/containerutil/container_network_manager_linux.go index 0afe793781e..8b535715ba7 100644 --- a/pkg/containerutil/container_network_manager_linux.go +++ b/pkg/containerutil/container_network_manager_linux.go @@ -40,7 +40,7 @@ type cniNetworkManagerPlatform struct { // Verifies that the internal network settings are correct. func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { - e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork()) + e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork(m.globalOptions.BridgeIP)) if err != nil { return err } diff --git a/pkg/containerutil/container_network_manager_windows.go b/pkg/containerutil/container_network_manager_windows.go index 6d85ca8fc68..45128d8bfe9 100644 --- a/pkg/containerutil/container_network_manager_windows.go +++ b/pkg/containerutil/container_network_manager_windows.go @@ -36,7 +36,7 @@ type cniNetworkManagerPlatform struct { // Verifies that the internal network settings are correct. func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { - e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork()) + e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork(m.globalOptions.BridgeIP)) if err != nil { return err } @@ -67,7 +67,7 @@ func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { } func (m *cniNetworkManager) getCNI() (gocni.CNI, error) { - e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork()) + e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork(m.globalOptions.BridgeIP)) if err != nil { return nil, fmt.Errorf("failed to instantiate CNI env: %s", err) } diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index a53490fec9a..abab2b5ab61 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -180,9 +180,9 @@ func namespaceUsedNetworks(ctx context.Context, containers []containerd.Containe return used, nil } -func WithDefaultNetwork() CNIEnvOpt { +func WithDefaultNetwork(bridgeIP string) CNIEnvOpt { return func(e *CNIEnv) error { - return e.ensureDefaultNetworkConfig() + return e.ensureDefaultNetworkConfig(bridgeIP) } } @@ -323,7 +323,6 @@ func (e *CNIEnv) CreateNetwork(opts types.NetworkCreateOptions) (*NetworkConfig, if _, ok := netMap[opts.Name]; ok { return errdefs.ErrAlreadyExists } - ipam, err := e.generateIPAM(opts.IPAMDriver, opts.Subnets, opts.Gateway, opts.IPRange, opts.IPAMOptions, opts.IPv6) if err != nil { return err @@ -406,31 +405,44 @@ func (e *CNIEnv) GetDefaultNetworkConfig() (*NetworkConfig, error) { return nil, nil } -func (e *CNIEnv) ensureDefaultNetworkConfig() error { +func (e *CNIEnv) ensureDefaultNetworkConfig(bridgeIP string) error { defaultNet, err := e.GetDefaultNetworkConfig() if err != nil { return fmt.Errorf("failed to check for default network: %s", err) } if defaultNet == nil { - if err := e.createDefaultNetworkConfig(); err != nil { + if err := e.createDefaultNetworkConfig(bridgeIP); err != nil { return fmt.Errorf("failed to create default network: %s", err) } } return nil } -func (e *CNIEnv) createDefaultNetworkConfig() error { +func (e *CNIEnv) createDefaultNetworkConfig(bridgeIP string) error { filename := e.getConfigPathForNetworkName(DefaultNetworkName) if _, err := os.Stat(filename); err == nil { return fmt.Errorf("already found existing network config at %q, cannot create new network named %q", filename, DefaultNetworkName) } + + bridgeCIDR := DefaultCIDR + bridgeGatewayIP := "" + if bridgeIP != "" { + bIP, bCIDR, err := net.ParseCIDR(bridgeIP) + if err != nil { + return fmt.Errorf("invalid bridge ip %s: %s", bridgeIP, err) + } + bridgeGatewayIP = bIP.String() + bridgeCIDR = bCIDR.String() + } opts := types.NetworkCreateOptions{ Name: DefaultNetworkName, Driver: DefaultNetworkName, - Subnets: []string{DefaultCIDR}, + Subnets: []string{bridgeCIDR}, + Gateway: bridgeGatewayIP, IPAMDriver: "default", Labels: []string{fmt.Sprintf("%s=true", labels.NerdctlDefaultNetwork)}, } + _, err := e.CreateNetwork(opts) if err != nil && !errdefs.IsAlreadyExists(err) { return err diff --git a/pkg/netutil/netutil_linux_test.go b/pkg/netutil/netutil_linux_test.go index 4e370baba9b..b547c5dfcc9 100644 --- a/pkg/netutil/netutil_linux_test.go +++ b/pkg/netutil/netutil_linux_test.go @@ -30,4 +30,5 @@ func TestDefaultNetworkCreation(t *testing.T) { } testDefaultNetworkCreation(t) + testDefaultNetworkCreationWithBridgeIP(t) } diff --git a/pkg/netutil/netutil_test.go b/pkg/netutil/netutil_test.go index 512dfe226c5..a17f4cb6197 100644 --- a/pkg/netutil/netutil_test.go +++ b/pkg/netutil/netutil_test.go @@ -18,6 +18,7 @@ package netutil import ( "bytes" + "encoding/json" "fmt" "net" "os" @@ -33,6 +34,8 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil" ) +const testBridgeIP = "10.1.100.1/24" // nolint:unused + const preExistingNetworkConfigTemplate = ` { "cniVersion": "0.2.0", @@ -160,10 +163,77 @@ func testDefaultNetworkCreation(t *testing.T) { assert.Assert(t, defaultNetConf == nil) // Attempt to create the default network. - err = cniEnv.ensureDefaultNetworkConfig() + err = cniEnv.ensureDefaultNetworkConfig("") + assert.NilError(t, err) + + // Ensure default network config is present now. + defaultNetConf, err = cniEnv.GetDefaultNetworkConfig() + assert.NilError(t, err) + assert.Assert(t, defaultNetConf != nil) + + // Check network config file present. + stat, err := os.Stat(defaultNetConf.File) + assert.NilError(t, err) + firstConfigModTime := stat.ModTime() + + // Check default network label present. + assert.Assert(t, defaultNetConf.NerdctlLabels != nil) + lstr, ok := (*defaultNetConf.NerdctlLabels)[labels.NerdctlDefaultNetwork] + assert.Assert(t, ok) + boolv, err := strconv.ParseBool(lstr) + assert.NilError(t, err) + assert.Assert(t, boolv) + + // Ensure network isn't created twice or accidentally re-created. + err = cniEnv.ensureDefaultNetworkConfig("") + assert.NilError(t, err) + + // Check for any other network config files. + files := []os.FileInfo{} + walkF := func(p string, info os.FileInfo, err error) error { + files = append(files, info) + return nil + } + err = filepath.Walk(cniConfTestDir, walkF) + assert.NilError(t, err) + assert.Assert(t, len(files) == 2) // files[0] is the entry for '.' + assert.Assert(t, filepath.Join(cniConfTestDir, files[1].Name()) == defaultNetConf.File) + assert.Assert(t, firstConfigModTime == files[1].ModTime()) +} + +// Tests whether nerdctl properly creates the default network +// with a custom bridge IP and subnet. +// nolint:unused +func testDefaultNetworkCreationWithBridgeIP(t *testing.T) { + // To prevent subnet collisions when attempting to recreate the default network + // in the isolated CNI config dir we'll be using, we must first delete + // the network in the default CNI config dir. + defaultCniEnv := CNIEnv{ + Path: ncdefaults.CNIPath(), + NetconfPath: ncdefaults.CNINetConfPath(), + } + defaultNet, err := defaultCniEnv.GetDefaultNetworkConfig() assert.NilError(t, err) + if defaultNet != nil { + assert.NilError(t, defaultCniEnv.RemoveNetwork(defaultNet)) + } - // Ensure no default network config is present now. + // We create a tempdir for the CNI conf path to ensure an empty env for this test. + cniConfTestDir := t.TempDir() + cniEnv := CNIEnv{ + Path: ncdefaults.CNIPath(), + NetconfPath: cniConfTestDir, + } + // Ensure no default network config is not present. + defaultNetConf, err := cniEnv.GetDefaultNetworkConfig() + assert.NilError(t, err) + assert.Assert(t, defaultNetConf == nil) + + // Attempt to create the default network with a test bridgeIP + err = cniEnv.ensureDefaultNetworkConfig(testBridgeIP) + assert.NilError(t, err) + + // Ensure default network config is present now. defaultNetConf, err = cniEnv.GetDefaultNetworkConfig() assert.NilError(t, err) assert.Assert(t, defaultNetConf != nil) @@ -181,8 +251,40 @@ func testDefaultNetworkCreation(t *testing.T) { assert.NilError(t, err) assert.Assert(t, boolv) + // Check bridge IP is set. + assert.Assert(t, defaultNetConf.Plugins != nil) + assert.Assert(t, len(defaultNetConf.Plugins) > 0) + bridgePlugin := defaultNetConf.Plugins[0] + var bridgeConfig struct { + Type string `json:"type"` + Bridge string `json:"bridge"` + IPAM struct { + Ranges [][]struct { + Gateway string `json:"gateway"` + Subnet string `json:"subnet"` + } `json:"ranges"` + Routes []struct { + Dst string `json:"dst"` + } `json:"routes"` + Type string `json:"type"` + } `json:"ipam"` + } + + err = json.Unmarshal(bridgePlugin.Bytes, &bridgeConfig) + if err != nil { + t.Fatalf("Failed to parse bridge plugin config: %v", err) + } + + // Assert on bridge plugin configuration + assert.Equal(t, "bridge", bridgeConfig.Type) + // Assert on IPAM configuration + assert.Equal(t, "10.1.100.1", bridgeConfig.IPAM.Ranges[0][0].Gateway) + assert.Equal(t, "10.1.100.0/24", bridgeConfig.IPAM.Ranges[0][0].Subnet) + assert.Equal(t, "0.0.0.0/0", bridgeConfig.IPAM.Routes[0].Dst) + assert.Equal(t, "host-local", bridgeConfig.IPAM.Type) + // Ensure network isn't created twice or accidentally re-created. - err = cniEnv.ensureDefaultNetworkConfig() + err = cniEnv.ensureDefaultNetworkConfig(testBridgeIP) assert.NilError(t, err) // Check for any other network config files. @@ -249,7 +351,7 @@ func TestNetworkWithDefaultNameAlreadyExists(t *testing.T) { assert.Assert(t, defaultNetConf != nil) assert.Assert(t, defaultNetConf.File == testConfFile) - err = cniEnv.ensureDefaultNetworkConfig() + err = cniEnv.ensureDefaultNetworkConfig("") assert.NilError(t, err) netConfs, err = cniEnv.NetworkList() diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index b1b1068c1bb..7e31eb1c1a5 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -61,7 +61,7 @@ const ( NetworkNamespace = labels.Prefix + "network-namespace" ) -func Run(stdin io.Reader, stderr io.Writer, event, dataStore, cniPath, cniNetconfPath string) error { +func Run(stdin io.Reader, stderr io.Writer, event, dataStore, cniPath, cniNetconfPath, bridgeIP string) error { if stdin == nil || event == "" || dataStore == "" || cniPath == "" || cniNetconfPath == "" { return errors.New("got insufficient args") } @@ -113,7 +113,7 @@ func Run(stdin io.Reader, stderr io.Writer, event, dataStore, cniPath, cniNetcon } defer lockutil.Unlock(lock) - opts, err := newHandlerOpts(&state, dataStore, cniPath, cniNetconfPath) + opts, err := newHandlerOpts(&state, dataStore, cniPath, cniNetconfPath, bridgeIP) if err != nil { return err } @@ -128,7 +128,7 @@ func Run(stdin io.Reader, stderr io.Writer, event, dataStore, cniPath, cniNetcon } } -func newHandlerOpts(state *specs.State, dataStore, cniPath, cniNetconfPath string) (*handlerOpts, error) { +func newHandlerOpts(state *specs.State, dataStore, cniPath, cniNetconfPath, bridgeIP string) (*handlerOpts, error) { o := &handlerOpts{ state: state, dataStore: dataStore, @@ -173,7 +173,7 @@ func newHandlerOpts(state *specs.State, dataStore, cniPath, cniNetconfPath strin case nettype.Host, nettype.None, nettype.Container, nettype.Namespace: // NOP case nettype.CNI: - e, err := netutil.NewCNIEnv(cniPath, cniNetconfPath, netutil.WithNamespace(namespace), netutil.WithDefaultNetwork()) + e, err := netutil.NewCNIEnv(cniPath, cniNetconfPath, netutil.WithNamespace(namespace), netutil.WithDefaultNetwork(bridgeIP)) if err != nil { return nil, err } From b5a117317a04d02bcb1eb88cc61f5b4e9ad863e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Nov 2024 22:49:36 +0000 Subject: [PATCH 0929/1066] build(deps): bump the golang-x group with 4 updates Bumps the golang-x group with 4 updates: [golang.org/x/sync](https://github.com/golang/sync), [golang.org/x/sys](https://github.com/golang/sys), [golang.org/x/term](https://github.com/golang/term) and [golang.org/x/text](https://github.com/golang/text). Updates `golang.org/x/sync` from 0.8.0 to 0.9.0 - [Commits](https://github.com/golang/sync/compare/v0.8.0...v0.9.0) Updates `golang.org/x/sys` from 0.26.0 to 0.27.0 - [Commits](https://github.com/golang/sys/compare/v0.26.0...v0.27.0) Updates `golang.org/x/term` from 0.25.0 to 0.26.0 - [Commits](https://github.com/golang/term/compare/v0.25.0...v0.26.0) Updates `golang.org/x/text` from 0.19.0 to 0.20.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.19.0...v0.20.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 41d93cb9e7b..bb9c01d20ab 100644 --- a/go.mod +++ b/go.mod @@ -67,10 +67,10 @@ require ( go.uber.org/mock v0.5.0 golang.org/x/crypto v0.28.0 golang.org/x/net v0.30.0 - golang.org/x/sync v0.8.0 - golang.org/x/sys v0.26.0 - golang.org/x/term v0.25.0 - golang.org/x/text v0.19.0 + golang.org/x/sync v0.9.0 + golang.org/x/sys v0.27.0 + golang.org/x/term v0.26.0 + golang.org/x/text v0.20.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) diff --git a/go.sum b/go.sum index e0b357fc69f..fdb2b81875e 100644 --- a/go.sum +++ b/go.sum @@ -368,8 +368,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -385,14 +385,14 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From a82ae7bb22ec9575a97aedd9ee452ac24d98f801 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Nov 2024 22:49:49 +0000 Subject: [PATCH 0930/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.4.3 to 2.4.4. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.4.3...v2.4.4) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 41d93cb9e7b..a354b4e69ec 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.0 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.9 - github.com/compose-spec/compose-go/v2 v2.4.3 + github.com/compose-spec/compose-go/v2 v2.4.4 github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.3 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index e0b357fc69f..8478abe70b1 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.4.3 h1:4+Nd9IqIGobbPles9ZuRS5uJfFfRgBo4Wdcv+8VNex8= -github.com/compose-spec/compose-go/v2 v2.4.3/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.4.4 h1:cvHBl5Jf1iNBmRrZCICmHvaoskYc1etTPEMLKVwokAY= +github.com/compose-spec/compose-go/v2 v2.4.4/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= From d1ea2d7b6d17876f734d22823b2c92818495eba3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Nov 2024 22:49:55 +0000 Subject: [PATCH 0931/1066] build(deps): bump github.com/containerd/typeurl/v2 from 2.2.2 to 2.2.3 Bumps [github.com/containerd/typeurl/v2](https://github.com/containerd/typeurl) from 2.2.2 to 2.2.3. - [Release notes](https://github.com/containerd/typeurl/releases) - [Commits](https://github.com/containerd/typeurl/compare/v2.2.2...v2.2.3) --- updated-dependencies: - dependency-name: github.com/containerd/typeurl/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 41d93cb9e7b..b06ef9cf21f 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319 github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319 - github.com/containerd/typeurl/v2 v2.2.2 + github.com/containerd/typeurl/v2 v2.2.3 github.com/containernetworking/cni v1.2.3 github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.8.0 diff --git a/go.sum b/go.sum index e0b357fc69f..32179c392e2 100644 --- a/go.sum +++ b/go.sum @@ -65,8 +65,8 @@ github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89 github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:L/J/O36DzcGxq3drHM45sJRr/pEQTG5u+tbffVhP6r8= github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= -github.com/containerd/typeurl/v2 v2.2.2 h1:3jN/k2ysKuPCsln5Qv8bzR9cxal8XjkxPogJfSNO31k= -github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= +github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= +github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= From 130397dd9847a6803652a6427b3bb3fd4c1507fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2024 22:23:14 +0000 Subject: [PATCH 0932/1066] build(deps): bump the golang-x group with 2 updates Bumps the golang-x group with 2 updates: [golang.org/x/crypto](https://github.com/golang/crypto) and [golang.org/x/net](https://github.com/golang/net). Updates `golang.org/x/crypto` from 0.28.0 to 0.29.0 - [Commits](https://github.com/golang/crypto/compare/v0.28.0...v0.29.0) Updates `golang.org/x/net` from 0.30.0 to 0.31.0 - [Commits](https://github.com/golang/net/compare/v0.30.0...v0.31.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3e8e0cc59ec..4a363f35ea5 100644 --- a/go.mod +++ b/go.mod @@ -65,8 +65,8 @@ require ( github.com/vishvananda/netns v0.0.5 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.5.0 - golang.org/x/crypto v0.28.0 - golang.org/x/net v0.30.0 + golang.org/x/crypto v0.29.0 + golang.org/x/net v0.31.0 golang.org/x/sync v0.9.0 golang.org/x/sys v0.27.0 golang.org/x/term v0.26.0 diff --git a/go.sum b/go.sum index cdbda10b718..9c47290e73c 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= @@ -360,8 +360,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 9c3513833ba39a4b25cd945b5945f9514228fd86 Mon Sep 17 00:00:00 2001 From: pinglanlu Date: Tue, 12 Nov 2024 14:30:05 +0800 Subject: [PATCH 0933/1066] Use a more direct and less error-prone return value Signed-off-by: pinglanlu --- pkg/netutil/subnet/subnet.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/netutil/subnet/subnet.go b/pkg/netutil/subnet/subnet.go index 02c3a8b2bd4..190c7dd4f81 100644 --- a/pkg/netutil/subnet/subnet.go +++ b/pkg/netutil/subnet/subnet.go @@ -111,12 +111,12 @@ func LastIPInSubnet(addr *net.IPNet) (net.IP, error) { } ones, bits := cidr.Mask.Size() if ones == bits { - return cidr.IP, err + return cidr.IP, nil } for i := range cidr.IP { cidr.IP[i] = cidr.IP[i] | ^cidr.Mask[i] } - return cidr.IP, err + return cidr.IP, nil } // firstIPInSubnet gets the first IP in a subnet @@ -129,8 +129,8 @@ func FirstIPInSubnet(addr *net.IPNet) (net.IP, error) { } ones, bits := cidr.Mask.Size() if ones == bits { - return cidr.IP, err + return cidr.IP, nil } cidr.IP[len(cidr.IP)-1]++ - return cidr.IP, err + return cidr.IP, nil } From 7dce7c7894057afd51601b70195d4cdc72494719 Mon Sep 17 00:00:00 2001 From: Manjusaka Date: Tue, 12 Nov 2024 21:05:13 +0800 Subject: [PATCH 0934/1066] refactor: Fix golanglint action error Signed-off-by: Manjusaka --- cmd/nerdctl/container/container_diff.go | 8 ++++---- pkg/imgutil/filtering.go | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/nerdctl/container/container_diff.go b/cmd/nerdctl/container/container_diff.go index 279c1aa2c79..9b3e5be47eb 100644 --- a/cmd/nerdctl/container/container_diff.go +++ b/cmd/nerdctl/container/container_diff.go @@ -197,8 +197,8 @@ func getChanges(ctx context.Context, client *containerd.Client, container contai return changes, err } -func appendChanges(changes []fs.Change, new fs.Change) []fs.Change { - newDir, _ := filepath.Split(new.Path) +func appendChanges(changes []fs.Change, fsChange fs.Change) []fs.Change { + newDir, _ := filepath.Split(fsChange.Path) newDirPath := filepath.SplitList(newDir) if len(changes) == 0 { @@ -208,7 +208,7 @@ func appendChanges(changes []fs.Change, new fs.Change) []fs.Change { Path: filepath.Join(newDirPath[:i+1]...), }) } - return append(changes, new) + return append(changes, fsChange) } last := changes[len(changes)-1] lastDir, _ := filepath.Split(last.Path) @@ -222,7 +222,7 @@ func appendChanges(changes []fs.Change, new fs.Change) []fs.Change { Path: filepath.Join(newDirPath[:i+1]...), }) } - return append(changes, new) + return append(changes, fsChange) } func diffShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index fb76980eca1..5555380ba4c 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -302,12 +302,12 @@ func filter[T any](items []T, f func(item T) (bool, error)) ([]T, error) { return filteredItems, nil } -func imageCreatedBetween(image images.Image, min time.Time, max time.Time) bool { - return image.CreatedAt.After(min) && image.CreatedAt.Before(max) +func imageCreatedBetween(image images.Image, minTime time.Time, maxTime time.Time) bool { + return image.CreatedAt.After(minTime) && image.CreatedAt.Before(maxTime) } -func imageCreatedBefore(image images.Image, max time.Time) bool { - return image.CreatedAt.Before(max) +func imageCreatedBefore(image images.Image, maxTime time.Time) bool { + return image.CreatedAt.Before(maxTime) } func matchesAllLabels(imageCfgLabels map[string]string, filterLabels map[string]string) bool { From 32de57ba7a6831c0d33b9714a329689e5d888ea8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 22:34:57 +0000 Subject: [PATCH 0935/1066] build(deps): bump github.com/containerd/continuity from 0.4.4 to 0.4.5 Bumps [github.com/containerd/continuity](https://github.com/containerd/continuity) from 0.4.4 to 0.4.5. - [Release notes](https://github.com/containerd/continuity/releases) - [Commits](https://github.com/containerd/continuity/compare/v0.4.4...v0.4.5) --- updated-dependencies: - dependency-name: github.com/containerd/continuity dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4a363f35ea5..ee5eda97a14 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0 github.com/containerd/containerd/v2 v2.0.0 - github.com/containerd/continuity v0.4.4 + github.com/containerd/continuity v0.4.5 github.com/containerd/errdefs v1.0.0 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.10 diff --git a/go.sum b/go.sum index 9c47290e73c..c7f09eb0d43 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVM github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/containerd/v2 v2.0.0 h1:qLDdFaAykQrIyLiqwQrNLLz95wiC36bAZVwioUwqShM= github.com/containerd/containerd/v2 v2.0.0/go.mod h1:j25kDy9P48/ngb1sxWIFfK6GsnqOHoSqo1EpAod20VQ= -github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= -github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= +github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= +github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= From ae50153a1f54e01775498bfe1ec54c2f1eb8725c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 22:35:07 +0000 Subject: [PATCH 0936/1066] build(deps): bump the stargz group across 1 directory with 3 updates Bumps the stargz group with 2 updates in the / directory: [github.com/containerd/stargz-snapshotter](https://github.com/containerd/stargz-snapshotter) and [github.com/containerd/stargz-snapshotter/ipfs](https://github.com/containerd/stargz-snapshotter). Updates `github.com/containerd/stargz-snapshotter` from 0.15.2-0.20240709063920-1dac5ef89319 to 0.16.1 - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/commits/v0.16.1) Updates `github.com/containerd/stargz-snapshotter/estargz` from 0.15.2-0.20240709063920-1dac5ef89319 to 0.16.1 - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/commits/v0.16.1) Updates `github.com/containerd/stargz-snapshotter/ipfs` from 0.15.2-0.20240709063920-1dac5ef89319 to 0.16.1 - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/commits/v0.16.1) --- updated-dependencies: - dependency-name: github.com/containerd/stargz-snapshotter dependency-type: direct:production update-type: version-update:semver-minor dependency-group: stargz - dependency-name: github.com/containerd/stargz-snapshotter/estargz dependency-type: direct:production update-type: version-update:semver-minor dependency-group: stargz - dependency-name: github.com/containerd/stargz-snapshotter/ipfs dependency-type: direct:production update-type: version-update:semver-minor dependency-group: stargz ... Signed-off-by: dependabot[bot] fix CI Signed-off-by: Jin Dong --- go.mod | 12 ++++++------ go.sum | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 4a363f35ea5..9af81558a56 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/containerd/nerdctl/v2 -go 1.22.0 +go 1.22.7 // FIXME: // github.com/docker/docker/pkg/sysinfo has been replaced by a fork kept under ./pkg2/sysinfo @@ -25,9 +25,9 @@ require ( github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.14.1-0.20240806063146-8fa319bfe9c5 github.com/containerd/platforms v1.0.0-rc.0 - github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 - github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319 - github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319 + github.com/containerd/stargz-snapshotter v0.16.1 + github.com/containerd/stargz-snapshotter/estargz v0.16.1 + github.com/containerd/stargz-snapshotter/ipfs v0.16.1 github.com/containerd/typeurl/v2 v2.2.3 github.com/containernetworking/cni v1.2.3 github.com/containernetworking/plugins v1.5.1 @@ -125,7 +125,7 @@ require ( github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/tinylib/msgp v1.2.0 // indirect - github.com/vbatts/tar-split v0.11.5 // indirect + github.com/vbatts/tar-split v0.11.6 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -138,7 +138,7 @@ require ( golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect golang.org/x/mod v0.21.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/grpc v1.67.1 // indirect + google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.35.1 // indirect lukechampine.com/blake3 v1.3.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index 9c47290e73c..7d2cc7c22f2 100644 --- a/go.sum +++ b/go.sum @@ -57,12 +57,12 @@ github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yu github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= -github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 h1:Td/dlhRp/kIk9W1rjXHSL87zZZiBQaKPV18OnoEREUA= -github.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:dgo5lVziOOnWX8SxxHqYuc8ShsQou54eKLdahxFlHVc= -github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319 h1:BRxgmkGWi5vAvajiCwEK+xit4FeFU3GRjbiX4DKTLtM= -github.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:9WSor0wu2swhtYoFkrjy3GHt7aNgKR2A7FhnpP+CH5o= -github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319 h1:WdmIerlurjZSoLI2w8014yzJY+q4qdO/A3ZJBEK7LQA= -github.com/containerd/stargz-snapshotter/ipfs v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:L/J/O36DzcGxq3drHM45sJRr/pEQTG5u+tbffVhP6r8= +github.com/containerd/stargz-snapshotter v0.16.1 h1:Bdahjs5h/Fu+7nMfF5L/XS7mvSvIq45kSpOpDTJ6LJQ= +github.com/containerd/stargz-snapshotter v0.16.1/go.mod h1:r8lNnBB/gqhXo4Pezxo474rFTkhuzbNSqQQEzigDmk0= +github.com/containerd/stargz-snapshotter/estargz v0.16.1 h1:7YswwU6746cJBN3p3l65JRk3+NZL7bap9Y6E3YeYowk= +github.com/containerd/stargz-snapshotter/estargz v0.16.1/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= +github.com/containerd/stargz-snapshotter/ipfs v0.16.1 h1:ukd71zUeHCh0eF7nvKTtpg5zEZuH77LpuMGi3YzERj4= +github.com/containerd/stargz-snapshotter/ipfs v0.16.1/go.mod h1:PUZJPURojlqo5natkG4JF91fJ1UcO6IcObT6ZwtzZ44= github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= @@ -302,8 +302,8 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= -github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= +github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs= +github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI= github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= @@ -419,8 +419,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= -google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 1fdb4b0ae3886aad1674171d07abbdb51355b657 Mon Sep 17 00:00:00 2001 From: Arjun Raja Yogidas Date: Wed, 13 Nov 2024 02:39:51 +0000 Subject: [PATCH 0937/1066] fix: default json-file log size to 100MB Signed-off-by: Arjun Raja Yogidas --- pkg/logging/json_logger.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index 5c38bdd1492..05d1c19c8c1 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -88,10 +88,11 @@ func (jsonLogger *JSONLogger) PreProcess(dataStore string, config *logging.Confi l := &logrotate.Logger{ Filename: jsonFilePath, } - //maxSize Defaults to unlimited. - var capVal int64 - capVal = -1 + // MaxBytes is the maximum size in bytes of the log file before it gets + // rotated. If not set, it defaults to 100 MiB. + // see: https://github.com/fahedouch/go-logrotate/blob/6a8beddaea39b2b9c77109d7fa2fe92053c063e5/logrotate.go#L500 if capacity, ok := jsonLogger.Opts[MaxSize]; ok { + var capVal int64 var err error capVal, err = units.FromHumanSize(capacity) if err != nil { @@ -100,8 +101,8 @@ func (jsonLogger *JSONLogger) PreProcess(dataStore string, config *logging.Confi if capVal <= 0 { return fmt.Errorf("max-size must be a positive number") } + l.MaxBytes = capVal } - l.MaxBytes = capVal maxFile := 1 if maxFileString, ok := jsonLogger.Opts[MaxFile]; ok { var err error From 37df93d3164708dcec880c9f549632ed3de76cc5 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 19 Nov 2024 03:26:25 +0000 Subject: [PATCH 0938/1066] update runc (1.2.2) Signed-off-by: Kay Yan --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4892f0b911e..cb5f7009fbe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v2.0.0 -ARG RUNC_VERSION=v1.2.1 +ARG RUNC_VERSION=v1.2.2 ARG CNI_PLUGINS_VERSION=v1.6.0 # Extra deps: Build From 2463f8b66a9325bc1b7db06c3145f3a3aeabac37 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 19 Nov 2024 03:27:47 +0000 Subject: [PATCH 0939/1066] update BuildKit (0.17.1) Signed-off-by: Kay Yan --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.0 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.1 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.1 diff --git a/Dockerfile b/Dockerfile index cb5f7009fbe..0f11cf3a84f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.2.2 ARG CNI_PLUGINS_VERSION=v1.6.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.17.0 +ARG BUILDKIT_VERSION=v0.17.1 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.0 deleted file mode 100644 index 7209867ca99..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.0 +++ /dev/null @@ -1,2 +0,0 @@ -3a9fea5977df76e9008fa5fb3d9b5dd581729e8adced2180a45bd3c12a4d1331 buildkit-v0.17.0.linux-amd64.tar.gz -5ec19fe78eeef2c03bef216d6890f05901fc117e7a66f88b423268dfcf5cf4af buildkit-v0.17.0.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.1 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.1 new file mode 100644 index 00000000000..b5bfc48ff86 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.1 @@ -0,0 +1,2 @@ +9352f7362045f4ae5eae55b41f8f30375d35a37f6a5931e2542916c92c3d00f9 buildkit-v0.17.1.linux-amd64.tar.gz +e232060d7782938e7c3d23c247a438e571f96fd197279c6b021a7f81deae45eb buildkit-v0.17.1.linux-arm64.tar.gz From c41cc9d928f1964ea7e610f51fd468360e6493ed Mon Sep 17 00:00:00 2001 From: Ryan Fowler Date: Tue, 19 Nov 2024 14:50:34 -0700 Subject: [PATCH 0940/1066] Pass appropriate --device arguments from compose to run This was passing a stringified version of the DeviceMapping struct instead of a source:target:permissions string. Signed-off-by: Ryan Fowler --- pkg/composer/serviceparser/serviceparser.go | 2 +- .../serviceparser/serviceparser_test.go | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/pkg/composer/serviceparser/serviceparser.go b/pkg/composer/serviceparser/serviceparser.go index 635b93594b4..2c45a1cecf8 100644 --- a/pkg/composer/serviceparser/serviceparser.go +++ b/pkg/composer/serviceparser/serviceparser.go @@ -515,7 +515,7 @@ func newContainer(project *types.Project, parsed *Service, i int) (*Container, e } for _, v := range svc.Devices { - c.RunArgs = append(c.RunArgs, fmt.Sprintf("--device=%s", v)) + c.RunArgs = append(c.RunArgs, fmt.Sprintf("--device=%s:%s:%s", v.Source, v.Target, v.Permissions)) } for _, v := range svc.DNS { diff --git a/pkg/composer/serviceparser/serviceparser_test.go b/pkg/composer/serviceparser/serviceparser_test.go index 337617a49f9..c3eaee0cd49 100644 --- a/pkg/composer/serviceparser/serviceparser_test.go +++ b/pkg/composer/serviceparser/serviceparser_test.go @@ -337,6 +337,36 @@ services: } +func TestParseDevices(t *testing.T) { + const dockerComposeYAML = ` +services: + foo: + image: nginx:alpine + devices: + - /dev/a + - /dev/b:/dev/b + - /dev/c:/dev/c:rw +` + comp := testutil.NewComposeDir(t, dockerComposeYAML) + defer comp.CleanUp() + + project, err := testutil.LoadProject(comp.YAMLFullPath(), comp.ProjectName(), nil) + assert.NilError(t, err) + + fooSvc, err := project.GetService("foo") + assert.NilError(t, err) + + foo, err := Parse(project, fooSvc) + assert.NilError(t, err) + + t.Logf("foo: %+v", foo) + for _, c := range foo.Containers { + assert.Assert(t, in(c.RunArgs, "--device=/dev/a:/dev/a:rwm")) + assert.Assert(t, in(c.RunArgs, "--device=/dev/b:/dev/b:rwm")) + assert.Assert(t, in(c.RunArgs, "--device=/dev/c:/dev/c:rw")) + } +} + func TestParseRelative(t *testing.T) { t.Parallel() From 3b3c68c1b46a49d1c77bbf2d75de4906ca4e3003 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 22:40:37 +0000 Subject: [PATCH 0941/1066] build(deps): bump docker/metadata-action from 5.5.1 to 5.6.1 Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.5.1 to 5.6.1. - [Release notes](https://github.com/docker/metadata-action/releases) - [Commits](https://github.com/docker/metadata-action/compare/v5.5.1...v5.6.1) --- updated-dependencies: - dependency-name: docker/metadata-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 84ab99f681b..29b01a0087c 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -53,7 +53,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v5.5.1 + uses: docker/metadata-action@v5.6.1 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} From f572d40f62af88f13e377885414058ea832b561f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 22:55:59 +0000 Subject: [PATCH 0942/1066] build(deps): bump github.com/Masterminds/semver/v3 from 3.3.0 to 3.3.1 Bumps [github.com/Masterminds/semver/v3](https://github.com/Masterminds/semver) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/Masterminds/semver/releases) - [Changelog](https://github.com/Masterminds/semver/blob/master/CHANGELOG.md) - [Commits](https://github.com/Masterminds/semver/compare/v3.3.0...v3.3.1) --- updated-dependencies: - dependency-name: github.com/Masterminds/semver/v3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9740c314536..87f2d842652 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ go 1.22.7 // We should still move back to upstream in the future, and remove our copy. require ( - github.com/Masterminds/semver/v3 v3.3.0 + github.com/Masterminds/semver/v3 v3.3.1 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.9 github.com/compose-spec/compose-go/v2 v2.4.4 diff --git a/go.sum b/go.sum index e4b42a4bb63..a59dd66e62f 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg6 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 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.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= -github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= +github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= 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.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg= From 1cbc1203bc9d9ff36b2ab7ad5d916e861f2314db Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Wed, 20 Nov 2024 01:35:48 +0000 Subject: [PATCH 0943/1066] update stargz-snapshotter (0.16.1) Signed-off-by: Kay Yan --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.15.1 | 3 --- Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.1 | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.15.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.1 diff --git a/Dockerfile b/Dockerfile index 0f11cf3a84f..07258ef3e5b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ ARG CNI_PLUGINS_VERSION=v1.6.0 # Extra deps: Build ARG BUILDKIT_VERSION=v0.17.1 # Extra deps: Lazy-pulling -ARG STARGZ_SNAPSHOTTER_VERSION=v0.15.1 +ARG STARGZ_SNAPSHOTTER_VERSION=v0.16.1 # Extra deps: Encryption ARG IMGCRYPT_VERSION=v2.0.0-rc.1 # Extra deps: Rootless diff --git a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.15.1 b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.15.1 deleted file mode 100644 index bb983c9d0dd..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.15.1 +++ /dev/null @@ -1,3 +0,0 @@ -7f25b570f5e954a33df695d41fdf60d060a3096066f1668236fb5e1b4c7b7753 stargz-snapshotter-v0.15.1-linux-amd64.tar.gz -4bd1ac3331501e14d87f5f8c3cde82cb08971d9b55643eb80155f74261e82a5a stargz-snapshotter-v0.15.1-linux-arm64.tar.gz -f1cf855870af16a653d8acb9daa3edf84687c2c05323cb958f078fb148af3eec stargz-snapshotter.service diff --git a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.1 b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.1 new file mode 100644 index 00000000000..43265447cbd --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.1 @@ -0,0 +1,3 @@ +59bafc59bf2536c692542876d4ff4e0d9411006c72c3030e262cc9b7b8b7b962 stargz-snapshotter-v0.16.1-linux-amd64.tar.gz +89213afb49517f5acd9d04017d0985731085ccd5495efc9073611333ba6961ee stargz-snapshotter-v0.16.1-linux-arm64.tar.gz +f1cf855870af16a653d8acb9daa3edf84687c2c05323cb958f078fb148af3eec stargz-snapshotter.service From f128aac0c12aa6c5c6db31544d2fd2ee202b1a0d Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Wed, 13 Nov 2024 00:01:52 +0900 Subject: [PATCH 0944/1066] fix: refactor pkg/infoutil in order to resolve import cycle This pull request will add the fields such as `CONTAINER_NAME` and `IMAGE_NAME` to the journald log entries sent by containers when `nerdctl run` is run with `--log-driver=journald`. However, the following `import cycle not allowed` error occurs when trying to import `containerutil package` in `logging package` in the implementation to be changed in this pull request. ``` > make CGO_ENABLED=0 GOOS=linux go -C /local/home/haytok/workspace/nerdctl build -ldflags "-s -w -X github.com/containerd/nerdctl/v2/pkg/version.Version=0d7dc8ec.m -X github.com/containerd/nerdctl/v2/pkg/version.Revision=0d7dc8ec4cda815acfca165b0281e801c4c5ef6e.m" -o /local/home/haytok/workspace/nerdctl/_output/nerdctl ./cmd/nerdctl package github.com/containerd/nerdctl/v2/cmd/nerdctl ... imports github.com/containerd/nerdctl/v2/pkg/infoutil: import cycle not allowed make: *** [nerdctl] Error 1 ``` Therefore, this commit refactors `infoutil package` to avoid `import cycle not allowd` error in the next commit. Signed-off-by: Hayato Kiwata --- pkg/cmd/system/info.go | 2 ++ pkg/infoutil/infoutil.go | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/system/info.go b/pkg/cmd/system/info.go index 2d3e6e194b1..183fc577979 100644 --- a/pkg/cmd/system/info.go +++ b/pkg/cmd/system/info.go @@ -37,6 +37,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/infoutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" + "github.com/containerd/nerdctl/v2/pkg/logging" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/strutil" ) @@ -72,6 +73,7 @@ func Info(ctx context.Context, client *containerd.Client, options types.SystemIn if err != nil { return err } + infoCompat.Plugins.Log = logging.Drivers() default: return fmt.Errorf("unknown mode %q", options.Mode) } diff --git a/pkg/infoutil/infoutil.go b/pkg/infoutil/infoutil.go index 36a65a6f96e..43041dd5d1b 100644 --- a/pkg/infoutil/infoutil.go +++ b/pkg/infoutil/infoutil.go @@ -35,7 +35,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" - "github.com/containerd/nerdctl/v2/pkg/logging" "github.com/containerd/nerdctl/v2/pkg/version" ) @@ -82,7 +81,6 @@ func Info(ctx context.Context, client *containerd.Client, snapshotter, cgroupMan info.ID = daemonIntro.UUID // Storage drivers and logging drivers are not really Server concept for nerdctl, but mimics `docker info` output info.Driver = snapshotter - info.Plugins.Log = logging.Drivers() info.Plugins.Storage = snapshotterPlugins info.SystemTime = time.Now().Format(time.RFC3339Nano) info.LoggingDriver = "json-file" // hard-coded From ba72ac7b971cbcd00a7a0d2b27989346c20e2406 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 22:42:03 +0000 Subject: [PATCH 0945/1066] build(deps): bump github.com/containerd/cgroups/v3 from 3.0.3 to 3.0.4 Bumps [github.com/containerd/cgroups/v3](https://github.com/containerd/cgroups) from 3.0.3 to 3.0.4. - [Release notes](https://github.com/containerd/cgroups/releases) - [Commits](https://github.com/containerd/cgroups/compare/v3.0.3...v3.0.4) --- updated-dependencies: - dependency-name: github.com/containerd/cgroups/v3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 87f2d842652..7ec4b48f3bf 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/Microsoft/hcsshim v0.12.9 github.com/compose-spec/compose-go/v2 v2.4.4 github.com/containerd/accelerated-container-image v1.2.3 - github.com/containerd/cgroups/v3 v3.0.3 + github.com/containerd/cgroups/v3 v3.0.4 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0 github.com/containerd/containerd/v2 v2.0.0 @@ -135,11 +135,11 @@ require ( go.opentelemetry.io/otel v1.31.0 // indirect go.opentelemetry.io/otel/metric v1.31.0 // indirect go.opentelemetry.io/otel/trace v1.31.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/mod v0.21.0 // indirect + golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect + golang.org/x/mod v0.22.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/grpc v1.68.0 // indirect - google.golang.org/protobuf v1.35.1 // indirect + google.golang.org/protobuf v1.35.2 // indirect lukechampine.com/blake3 v1.3.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect tags.cncf.io/container-device-interface v0.8.0 // indirect diff --git a/go.sum b/go.sum index a59dd66e62f..418dda7e4a4 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,8 @@ github.com/compose-spec/compose-go/v2 v2.4.4 h1:cvHBl5Jf1iNBmRrZCICmHvaoskYc1etT github.com/compose-spec/compose-go/v2 v2.4.4/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= -github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0= -github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0= +github.com/containerd/cgroups/v3 v3.0.4 h1:2fs7l3P0Qxb1nKWuJNFiwhp2CqiKzho71DQkDrHJIo4= +github.com/containerd/cgroups/v3 v3.0.4/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= 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/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= @@ -342,15 +342,15 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= +golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= 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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -401,8 +401,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= +golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -430,8 +430,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= From 0e8abacc371386a058c71012ccff3ce38d8cd123 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Thu, 21 Nov 2024 22:51:14 +0000 Subject: [PATCH 0946/1066] Update containerd (1.7.24) in CI Signed-off-by: Austin Vazquez --- .github/workflows/test-canary.yml | 2 +- .github/workflows/test.yml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 75a666d32b4..152097cd0fc 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -82,7 +82,7 @@ jobs: - uses: actions/checkout@v4.2.2 with: repository: containerd/containerd - ref: "v1.7.23" + ref: "v1.7.24" path: containerd fetch-depth: 1 - name: "Set up CNI" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b9a1f3c4f83..46405ac2f93 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: containerd: v1.6.36 arch: amd64 - runner: ubuntu-24.04 - containerd: v1.7.23 + containerd: v1.7.24 arch: amd64 - runner: ubuntu-24.04 containerd: v2.0.0 @@ -85,7 +85,7 @@ jobs: uses: actions/checkout@v4.2.2 with: repository: containerd/containerd - ref: v1.7.23 + ref: v1.7.24 path: containerd fetch-depth: 1 - if: ${{ matrix.goos=='windows' }} @@ -110,7 +110,7 @@ jobs: runner: "ubuntu-20.04" arch: amd64 - ubuntu: 22.04 - containerd: v1.7.23 + containerd: v1.7.24 runner: "ubuntu-22.04" arch: amd64 - ubuntu: 24.04 @@ -235,7 +235,7 @@ jobs: target: rootless arch: amd64 - ubuntu: 22.04 - containerd: v1.7.23 + containerd: v1.7.24 rootlesskit: v2.3.1 target: rootless arch: amd64 @@ -245,7 +245,7 @@ jobs: target: rootless arch: amd64 - ubuntu: 24.04 - containerd: v1.7.23 + containerd: v1.7.24 rootlesskit: v2.3.1 target: rootless-port-slirp4netns arch: amd64 @@ -378,7 +378,7 @@ jobs: - uses: actions/checkout@v4.2.2 with: repository: containerd/containerd - ref: v1.7.23 + ref: v1.7.24 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -386,7 +386,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.23 + ctrdVersion: 1.7.24 run: powershell hack/configure-windows-ci.ps1 - name: "Run integration tests" run: ./hack/test-integration.sh -test.only-flaky=false From 788fc0c298c384904fa74d018077b81152ed5ea2 Mon Sep 17 00:00:00 2001 From: ningmingxiao Date: Tue, 19 Nov 2024 09:48:34 +0800 Subject: [PATCH 0947/1066] fix nerdctl ps slow on heavy IO system by using goroutine Signed-off-by: ningmingxiao --- pkg/cmd/container/list.go | 46 ++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/pkg/cmd/container/list.go b/pkg/cmd/container/list.go index b5887dcd789..b23dbb9e14b 100644 --- a/pkg/cmd/container/list.go +++ b/pkg/cmd/container/list.go @@ -22,6 +22,7 @@ import ( "fmt" "sort" "strings" + "sync" "time" containerd "github.com/containerd/containerd/v2/client" @@ -40,11 +41,11 @@ import ( // List prints containers according to `options`. func List(ctx context.Context, client *containerd.Client, options types.ContainerListOptions) ([]ListItem, error) { - containers, err := filterContainers(ctx, client, options.Filters, options.LastN, options.All) + containers, cMap, err := filterContainers(ctx, client, options.Filters, options.LastN, options.All) if err != nil { return nil, err } - return prepareContainers(ctx, client, containers, options) + return prepareContainers(ctx, client, containers, cMap, options) } // filterContainers returns containers matching the filters. @@ -53,14 +54,14 @@ func List(ctx context.Context, client *containerd.Client, options types.Containe // - all means showing all containers (default shows just running). // - lastN means only showing n last created containers (includes all states). Non-positive values are ignored. // In other words, if lastN is positive, all will be set to true. -func filterContainers(ctx context.Context, client *containerd.Client, filters []string, lastN int, all bool) ([]containerd.Container, error) { +func filterContainers(ctx context.Context, client *containerd.Client, filters []string, lastN int, all bool) ([]containerd.Container, map[string]string, error) { containers, err := client.Containers(ctx) if err != nil { - return nil, err + return nil, nil, err } filterCtx, err := foldContainerFilters(ctx, containers, filters) if err != nil { - return nil, err + return nil, nil, err } containers = filterCtx.MatchesFilters(ctx) @@ -77,18 +78,37 @@ func filterContainers(ctx context.Context, client *containerd.Client, filters [] } } + var wg sync.WaitGroup + statusPerContainer := make(map[string]string) + var mu sync.Mutex + // formatter.ContainerStatus(ctx, c) is time consuming so we do it in goroutines and return the container's id with status as a map. + // prepareContainers func will use this map to avoid call formatter.ContainerStatus again. + for _, c := range containers { + if c.ID() == "" { + return nil, nil, fmt.Errorf("container id is nill") + } + wg.Add(1) + go func(ctx context.Context, c containerd.Container) { + defer wg.Done() + cStatus := formatter.ContainerStatus(ctx, c) + mu.Lock() + statusPerContainer[c.ID()] = cStatus + mu.Unlock() + }(ctx, c) + } + wg.Wait() if all || filterCtx.all { - return containers, nil + return containers, statusPerContainer, nil } var upContainers []containerd.Container for _, c := range containers { - cStatus := formatter.ContainerStatus(ctx, c) + cStatus := statusPerContainer[c.ID()] if strings.HasPrefix(cStatus, "Up") { upContainers = append(upContainers, c) } } - return upContainers, nil + return upContainers, statusPerContainer, nil } type ListItem struct { @@ -112,7 +132,7 @@ func (x *ListItem) Label(s string) string { return x.LabelsMap[s] } -func prepareContainers(ctx context.Context, client *containerd.Client, containers []containerd.Container, options types.ContainerListOptions) ([]ListItem, error) { +func prepareContainers(ctx context.Context, client *containerd.Client, containers []containerd.Container, statusPerContainer map[string]string, options types.ContainerListOptions) ([]ListItem, error) { listItems := make([]ListItem, len(containers)) snapshottersCache := map[string]snapshots.Snapshotter{} for i, c := range containers { @@ -136,6 +156,12 @@ func prepareContainers(ctx context.Context, client *containerd.Client, container if options.Truncate && len(id) > 12 { id = id[:12] } + var status string + if s, ok := statusPerContainer[c.ID()]; ok { + status = s + } else { + return nil, fmt.Errorf("can't get container %s status", c.ID()) + } li := ListItem{ Command: formatter.InspectContainerCommand(spec, options.Truncate, true), CreatedAt: info.CreatedAt, @@ -144,7 +170,7 @@ func prepareContainers(ctx context.Context, client *containerd.Client, container Platform: info.Labels[labels.Platform], Names: containerutil.GetContainerName(info.Labels), Ports: formatter.FormatPorts(info.Labels), - Status: formatter.ContainerStatus(ctx, c), + Status: status, Runtime: info.Runtime.Name, Labels: formatter.FormatLabels(info.Labels), LabelsMap: info.Labels, From 232b6adcb70068f3b17e830c7c5c35b5014df7e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 22:37:37 +0000 Subject: [PATCH 0948/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.4.4 to 2.4.5. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.4.4...v2.4.5) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7ec4b48f3bf..9328dc1190f 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.1 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.9 - github.com/compose-spec/compose-go/v2 v2.4.4 + github.com/compose-spec/compose-go/v2 v2.4.5 github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.4 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index 418dda7e4a4..7b5cb821efb 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.4.4 h1:cvHBl5Jf1iNBmRrZCICmHvaoskYc1etTPEMLKVwokAY= -github.com/compose-spec/compose-go/v2 v2.4.4/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.4.5 h1:p4ih4Jb6VgGPLPxh3fSFVKAjFHtZd+7HVLCSFzcFx9Y= +github.com/compose-spec/compose-go/v2 v2.4.5/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.4 h1:2fs7l3P0Qxb1nKWuJNFiwhp2CqiKzho71DQkDrHJIo4= From b060ead7b71f5a4279b05a8430d2d5db3364af08 Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Wed, 13 Nov 2024 00:12:31 +0900 Subject: [PATCH 0949/1066] fix: add fields such as CONTAINER_NAME to journald log entries sent to by containers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the current implementation, containers running by `nerdctl` dose not export entries containing fields such as `CONTAINER_NAME`, `IMAGE_NAME` , and etc to the journald log like containers running by `docker cli`. At this time, the journald log entry describes below when sending to the journald log using nerdctl. ``` > nerdctl run -d --name nginx-nerdctl --log-driver=journald nginx bb7df47d27fd73426cec286ed88c5abf1443e74df637e2440d2dbca7229a84dc > nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bb7df47d27fd docker.io/library/nginx:latest "/docker-entrypoint.…" 3 seconds ago Up nginx-nerdctl > sudo journalctl SYSLOG_IDENTIFIER=bb7df47d27fd -a -n 1 -o json-pretty { "__CURSOR" : "???", "__REALTIME_TIMESTAMP" : "1730899940827182", "__MONOTONIC_TIMESTAMP" : "10815937979908", "_BOOT_ID" : "???", "_UID" : "0", "_GID" : "0", "_CAP_EFFECTIVE" : "1ffffffffff", "_MACHINE_ID" : "???", "_HOSTNAME" : "???.us-west-2.amazon.com", "_TRANSPORT" : "journal", "_SYSTEMD_SLICE" : "system.slice", "PRIORITY" : "3", "_SYSTEMD_CGROUP" : "/system.slice/containerd.service", "_SYSTEMD_UNIT" : "containerd.service", "_COMM" : "nerdctl", "_EXE" : "/usr/local/bin/nerdctl", "_CMDLINE" : "/usr/local/bin/nerdctl _NERDCTL_INTERNAL_LOGGING /var/lib/nerdctl/1935db59", "SYSLOG_IDENTIFIER" : "bb7df47d27fd", "_PID" : "8118", "MESSAGE" : "2024/11/06 13:32:20 [notice] 1#1: start worker process 44", "_SOURCE_REALTIME_TIMESTAMP" : "1730899940825905" } ``` On the other hand, the output fields are listed below when we use the journald logging driver with docker cli. - https://docs.docker.com/engine/logging/drivers/journald/ As you can see, some entries are not output by nerdctl and are incompatible with the docker cli. This feature request is reported in the following: - https://github.com/containerd/nerdctl/issues/3486 Therefore, in this pull request, we will add the fields to be output in the journald log. After applying this fix, the journald log will output the following fields. ``` { "__CURSOR": "???", "__REALTIME_TIMESTAMP": "1731385591671422", "__MONOTONIC_TIMESTAMP": "11301588824148", "_BOOT_ID": "???", "_MACHINE_ID": "???", "_HOSTNAME": "???.us-west-2.amazon.com", "PRIORITY": "3", "_TRANSPORT": "journal", "_UID": "0", "_GID": "0", "_COMM": "nerdctl", "_EXE": "/usr/local/bin/nerdctl", "_CMDLINE": "/usr/local/bin/nerdctl _NERDCTL_INTERNAL_LOGGING /var/lib/nerdctl/1935db59", "_CAP_EFFECTIVE": "1ffffffffff", "_SYSTEMD_CGROUP": "/system.slice/containerd.service", "_SYSTEMD_UNIT": "containerd.service", "_SYSTEMD_SLICE": "system.slice", "CONTAINER_NAME": "nginx-nerdctl", "IMAGE_NAME": "nginx", "CONTAINER_ID_FULL": "fe22eccbd704ba799785999079ac465ed067d5914e9e3f1020e769921d5a83c5", "SYSLOG_IDENTIFIER": "fe22eccbd704", "CONTAINER_TAG": "fe22eccbd704", "CONTAINER_ID": "fe22eccbd704", "_PID": "31643", "MESSAGE": "2024/11/12 04:26:31 [notice] 1#1: start worker process 44", "_SOURCE_REALTIME_TIMESTAMP": "1731385591669765" } ``` Signed-off-by: Hayato Kiwata --- cmd/nerdctl/container/container_run_test.go | 47 ++++++++++++++++----- pkg/cmd/container/create.go | 7 +-- pkg/logging/fluentd_logger.go | 3 +- pkg/logging/journald_logger.go | 38 +++++++++++++++-- pkg/logging/json_logger.go | 2 +- pkg/logging/logging.go | 31 +++++++------- pkg/logging/logging_test.go | 2 +- pkg/logging/none_logger.go | 4 +- pkg/logging/none_logger_test.go | 4 +- pkg/logging/syslog_logger.go | 3 +- 10 files changed, 103 insertions(+), 38 deletions(-) diff --git a/cmd/nerdctl/container/container_run_test.go b/cmd/nerdctl/container/container_run_test.go index a727a68ea45..9a22aded3b0 100644 --- a/cmd/nerdctl/container/container_run_test.go +++ b/cmd/nerdctl/container/container_run_test.go @@ -329,19 +329,44 @@ func TestRunWithJournaldLogDriver(t *testing.T) { time.Sleep(3 * time.Second) journalctl, err := exec.LookPath("journalctl") assert.NilError(t, err) + inspectedContainer := base.InspectContainer(containerName) - found := 0 - check := func(log poll.LogT) poll.Result { - res := icmd.RunCmd(icmd.Command(journalctl, "--no-pager", "--since", "2 minutes ago", fmt.Sprintf("SYSLOG_IDENTIFIER=%s", inspectedContainer.ID[:12]))) - assert.Equal(t, 0, res.ExitCode, res) - if strings.Contains(res.Stdout(), "bar") && strings.Contains(res.Stdout(), "foo") { - found = 1 - return poll.Success() - } - return poll.Continue("reading from journald is not yet finished") + + type testCase struct { + name string + filter string + } + testCases := []testCase{ + { + name: "filter journald logs using SYSLOG_IDENTIFIER field", + filter: fmt.Sprintf("SYSLOG_IDENTIFIER=%s", inspectedContainer.ID[:12]), + }, + { + name: "filter journald logs using CONTAINER_NAME field", + filter: fmt.Sprintf("CONTAINER_NAME=%s", containerName), + }, + { + name: "filter journald logs using IMAGE_NAME field", + filter: fmt.Sprintf("IMAGE_NAME=%s", testutil.CommonImage), + }, + } + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + found := 0 + check := func(log poll.LogT) poll.Result { + res := icmd.RunCmd(icmd.Command(journalctl, "--no-pager", "--since", "2 minutes ago", tc.filter)) + assert.Equal(t, 0, res.ExitCode, res) + if strings.Contains(res.Stdout(), "bar") && strings.Contains(res.Stdout(), "foo") { + found = 1 + return poll.Success() + } + return poll.Continue("reading from journald is not yet finished") + } + poll.WaitOn(t, check, poll.WithDelay(100*time.Microsecond), poll.WithTimeout(20*time.Second)) + assert.Equal(t, 1, found) + }) } - poll.WaitOn(t, check, poll.WithDelay(100*time.Microsecond), poll.WithTimeout(20*time.Second)) - assert.Equal(t, 1, found) } func TestRunWithJournaldLogDriverAndLogOpt(t *testing.T) { diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index c5c6e222820..7ee88f82d4a 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -218,7 +218,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa // 1, nerdctl run --name demo -it imagename // 2, ctrl + c to stop demo container // 3, nerdctl start/restart demo - logConfig, err := generateLogConfig(dataStore, id, options.LogDriver, options.LogOpt, options.GOptions.Namespace) + logConfig, err := generateLogConfig(dataStore, id, options.LogDriver, options.LogOpt, options.GOptions.Namespace, options.GOptions.Address) if err != nil { return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), err } @@ -819,12 +819,13 @@ func writeCIDFile(path, id string) error { } // generateLogConfig creates a LogConfig for the current container store -func generateLogConfig(dataStore string, id string, logDriver string, logOpt []string, ns string) (logConfig logging.LogConfig, err error) { +func generateLogConfig(dataStore string, id string, logDriver string, logOpt []string, ns, address string) (logConfig logging.LogConfig, err error) { var u *url.URL if u, err = url.Parse(logDriver); err == nil && u.Scheme != "" { logConfig.LogURI = logDriver } else { logConfig.Driver = logDriver + logConfig.Address = address logConfig.Opts, err = parseKVStringsMapFromLogOpt(logOpt, logDriver) if err != nil { return logConfig, err @@ -834,7 +835,7 @@ func generateLogConfig(dataStore string, id string, logDriver string, logOpt []s logConfigB []byte lu *url.URL ) - logDriverInst, err = logging.GetDriver(logDriver, logConfig.Opts) + logDriverInst, err = logging.GetDriver(logDriver, logConfig.Opts, logConfig.Address) if err != nil { return logConfig, err } diff --git a/pkg/logging/fluentd_logger.go b/pkg/logging/fluentd_logger.go index 0f9fc762053..c0a7d579fdb 100644 --- a/pkg/logging/fluentd_logger.go +++ b/pkg/logging/fluentd_logger.go @@ -17,6 +17,7 @@ package logging import ( + "context" "fmt" "math" "net/url" @@ -99,7 +100,7 @@ func (f *FluentdLogger) Init(dataStore, ns, id string) error { return nil } -func (f *FluentdLogger) PreProcess(_ string, config *logging.Config) error { +func (f *FluentdLogger) PreProcess(_ context.Context, _ string, config *logging.Config) error { if runtime.GOOS == "windows" { // TODO: support fluentd on windows return fmt.Errorf("logging to fluentd is not supported on windows") diff --git a/pkg/logging/journald_logger.go b/pkg/logging/journald_logger.go index e2242af73c3..404d4abd02f 100644 --- a/pkg/logging/journald_logger.go +++ b/pkg/logging/journald_logger.go @@ -18,6 +18,7 @@ package logging import ( "bytes" + "context" "errors" "fmt" "io" @@ -35,6 +36,8 @@ import ( "github.com/containerd/containerd/v2/core/runtime/v2/logging" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/strutil" ) @@ -52,8 +55,9 @@ func JournalLogOptsValidate(logOptMap map[string]string) error { } type JournaldLogger struct { - Opts map[string]string - vars map[string]string + Opts map[string]string + vars map[string]string + Address string } type identifier struct { @@ -66,7 +70,7 @@ func (journaldLogger *JournaldLogger) Init(dataStore, ns, id string) error { return nil } -func (journaldLogger *JournaldLogger) PreProcess(dataStore string, config *logging.Config) error { +func (journaldLogger *JournaldLogger) PreProcess(ctx context.Context, dataStore string, config *logging.Config) error { if !journal.Enabled() { return errors.New("the local systemd journal is not available for logging") } @@ -95,9 +99,37 @@ func (journaldLogger *JournaldLogger) PreProcess(dataStore string, config *loggi syslogIdentifier = b.String() } } + + client, ctx, cancel, err := clientutil.NewClient(ctx, config.Namespace, journaldLogger.Address) + if err != nil { + return err + } + defer func() { + cancel() + client.Close() + }() + containerID := config.ID + container, err := client.LoadContainer(ctx, containerID) + if err != nil { + return err + } + containerLabels, err := container.Labels(ctx) + if err != nil { + return err + } + containerInfo, err := container.Info(ctx) + if err != nil { + return err + } + // construct log metadata for the container vars := map[string]string{ "SYSLOG_IDENTIFIER": syslogIdentifier, + "CONTAINER_TAG": syslogIdentifier, + "CONTAINER_ID": shortID, + "CONTAINER_ID_FULL": containerID, + "CONTAINER_NAME": containerutil.GetContainerName(containerLabels), + "IMAGE_NAME": containerInfo.Image, } journaldLogger.vars = vars return nil diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index 05d1c19c8c1..988e847d5e9 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -78,7 +78,7 @@ func (jsonLogger *JSONLogger) Init(dataStore, ns, id string) error { return nil } -func (jsonLogger *JSONLogger) PreProcess(dataStore string, config *logging.Config) error { +func (jsonLogger *JSONLogger) PreProcess(ctx context.Context, dataStore string, config *logging.Config) error { var jsonFilePath string if logPath, ok := jsonLogger.Opts[LogPath]; ok { jsonFilePath = logPath diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index 318e3496e6b..0a5e57d5524 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -49,12 +49,12 @@ const ( type Driver interface { Init(dataStore, ns, id string) error - PreProcess(dataStore string, config *logging.Config) error + PreProcess(ctx context.Context, dataStore string, config *logging.Config) error Process(stdout <-chan string, stderr <-chan string) error PostProcess() error } -type DriverFactory func(map[string]string) (Driver, error) +type DriverFactory func(map[string]string, string) (Driver, error) type LogOptsValidateFunc func(logOptMap map[string]string) error var drivers = make(map[string]DriverFactory) @@ -81,28 +81,28 @@ func Drivers() []string { return ss } -func GetDriver(name string, opts map[string]string) (Driver, error) { +func GetDriver(name string, opts map[string]string, address string) (Driver, error) { driverFactory, ok := drivers[name] if !ok { return nil, fmt.Errorf("unknown logging driver %q: %w", name, errdefs.ErrNotFound) } - return driverFactory(opts) + return driverFactory(opts, address) } func init() { - RegisterDriver("none", func(opts map[string]string) (Driver, error) { + RegisterDriver("none", func(opts map[string]string, address string) (Driver, error) { return &NoneLogger{}, nil }, NoneLogOptsValidate) - RegisterDriver("json-file", func(opts map[string]string) (Driver, error) { + RegisterDriver("json-file", func(opts map[string]string, address string) (Driver, error) { return &JSONLogger{Opts: opts}, nil }, JSONFileLogOptsValidate) - RegisterDriver("journald", func(opts map[string]string) (Driver, error) { - return &JournaldLogger{Opts: opts}, nil + RegisterDriver("journald", func(opts map[string]string, address string) (Driver, error) { + return &JournaldLogger{Opts: opts, Address: address}, nil }, JournalLogOptsValidate) - RegisterDriver("fluentd", func(opts map[string]string) (Driver, error) { + RegisterDriver("fluentd", func(opts map[string]string, address string) (Driver, error) { return &FluentdLogger{Opts: opts}, nil }, FluentdLogOptsValidate) - RegisterDriver("syslog", func(opts map[string]string) (Driver, error) { + RegisterDriver("syslog", func(opts map[string]string, address string) (Driver, error) { return &SyslogLogger{Opts: opts}, nil }, SyslogOptsValidate) } @@ -121,9 +121,10 @@ func Main(argv2 string) error { // LogConfig is marshalled as "log-config.json" type LogConfig struct { - Driver string `json:"driver"` - Opts map[string]string `json:"opts,omitempty"` - LogURI string `json:"-"` + Driver string `json:"driver"` + Opts map[string]string `json:"opts,omitempty"` + LogURI string `json:"-"` + Address string `json:"address"` } // LogConfigFilePath returns the path of log-config.json @@ -149,7 +150,7 @@ func LoadLogConfig(dataStore, ns, id string) (LogConfig, error) { } func loggingProcessAdapter(ctx context.Context, driver Driver, dataStore string, config *logging.Config) error { - if err := driver.PreProcess(dataStore, config); err != nil { + if err := driver.PreProcess(ctx, dataStore, config); err != nil { return err } @@ -215,7 +216,7 @@ func loggerFunc(dataStore string) (logging.LoggerFunc, error) { if err != nil { return err } - driver, err := GetDriver(logConfig.Driver, logConfig.Opts) + driver, err := GetDriver(logConfig.Driver, logConfig.Opts, logConfig.Address) if err != nil { return err } diff --git a/pkg/logging/logging_test.go b/pkg/logging/logging_test.go index 4cec4c868cc..175f1b3e64b 100644 --- a/pkg/logging/logging_test.go +++ b/pkg/logging/logging_test.go @@ -38,7 +38,7 @@ func (m *MockDriver) Init(dataStore, ns, id string) error { return nil } -func (m *MockDriver) PreProcess(dataStore string, config *logging.Config) error { +func (m *MockDriver) PreProcess(ctx context.Context, dataStore string, config *logging.Config) error { return nil } diff --git a/pkg/logging/none_logger.go b/pkg/logging/none_logger.go index 57d7e1c1b34..8d316c32465 100644 --- a/pkg/logging/none_logger.go +++ b/pkg/logging/none_logger.go @@ -17,6 +17,8 @@ package logging import ( + "context" + "github.com/containerd/containerd/v2/core/runtime/v2/logging" ) @@ -28,7 +30,7 @@ func (n *NoneLogger) Init(dataStore, ns, id string) error { return nil } -func (n *NoneLogger) PreProcess(dataStore string, config *logging.Config) error { +func (n *NoneLogger) PreProcess(ctx context.Context, dataStore string, config *logging.Config) error { return nil } diff --git a/pkg/logging/none_logger_test.go b/pkg/logging/none_logger_test.go index 88e35b72d3c..59e967bc5e1 100644 --- a/pkg/logging/none_logger_test.go +++ b/pkg/logging/none_logger_test.go @@ -17,6 +17,7 @@ package logging import ( + "context" "os" "testing" "time" @@ -29,6 +30,7 @@ import ( func TestNoneLogger(t *testing.T) { // Create a temporary directory for potential log files tmpDir := t.TempDir() + ctx := context.Background() logger := &NoneLogger{ Opts: map[string]string{}, @@ -40,7 +42,7 @@ func TestNoneLogger(t *testing.T) { // Run all logger methods logger.Init(tmpDir, "namespace", "id") - logger.PreProcess(tmpDir, &logging.Config{}) + logger.PreProcess(ctx, tmpDir, &logging.Config{}) stdout := make(chan string) stderr := make(chan string) diff --git a/pkg/logging/syslog_logger.go b/pkg/logging/syslog_logger.go index 154478cad2a..460caf5313a 100644 --- a/pkg/logging/syslog_logger.go +++ b/pkg/logging/syslog_logger.go @@ -17,6 +17,7 @@ package logging import ( + "context" "crypto/tls" "errors" "fmt" @@ -122,7 +123,7 @@ func (sy *SyslogLogger) Init(dataStore string, ns string, id string) error { return nil } -func (sy *SyslogLogger) PreProcess(dataStore string, config *logging.Config) error { +func (sy *SyslogLogger) PreProcess(ctx context.Context, dataStore string, config *logging.Config) error { logger, err := parseSyslog(config.ID, sy.Opts) if err != nil { return err From 2ad3f57cb53b9141a70e765555225191e8cf28c1 Mon Sep 17 00:00:00 2001 From: "bo.jiang" Date: Tue, 26 Nov 2024 15:05:58 +0800 Subject: [PATCH 0950/1066] fix redundant error checks and comment format Signed-off-by: bo.jiang --- pkg/containerutil/container_network_manager.go | 12 ++---------- pkg/lockutil/lockutil_unix.go | 5 +---- pkg/mountutil/volumestore/volumestore.go | 2 +- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/pkg/containerutil/container_network_manager.go b/pkg/containerutil/container_network_manager.go index 5bc34e1e921..23852f56f58 100644 --- a/pkg/containerutil/container_network_manager.go +++ b/pkg/containerutil/container_network_manager.go @@ -420,11 +420,7 @@ func (m *hostNetworkManager) SetupNetworking(ctx context.Context, containerID st } // Save the meta information - if err = hs.Acquire(hsMeta); err != nil { - return err - } - - return nil + return hs.Acquire(hsMeta) } // CleanupNetworking Performs any required cleanup actions for the given container. @@ -449,11 +445,7 @@ func (m *hostNetworkManager) CleanupNetworking(ctx context.Context, container co } // Release - if err = hs.Release(container.ID()); err != nil { - return err - } - - return nil + return hs.Release(container.ID()) } // InternalNetworkingOptionLabels Returns the set of NetworkingOptions which should be set as labels on the container. diff --git a/pkg/lockutil/lockutil_unix.go b/pkg/lockutil/lockutil_unix.go index 7be6844aaf3..de99ca9a4e1 100644 --- a/pkg/lockutil/lockutil_unix.go +++ b/pkg/lockutil/lockutil_unix.go @@ -72,8 +72,5 @@ func Unlock(locked *os.File) error { _ = locked.Close() }() - if err := flock(locked, unix.LOCK_UN); err != nil { - return err - } - return nil + return flock(locked, unix.LOCK_UN) } diff --git a/pkg/mountutil/volumestore/volumestore.go b/pkg/mountutil/volumestore/volumestore.go index 47c1b2bd73e..9dac3df604c 100644 --- a/pkg/mountutil/volumestore/volumestore.go +++ b/pkg/mountutil/volumestore/volumestore.go @@ -39,7 +39,7 @@ const ( volumeJSONFileName = "volume.json" ) -// ErrNameStore will wrap all errors here +// ErrVolumeStore will wrap all errors here var ErrVolumeStore = errors.New("volume-store error") type VolumeStore interface { From 159e0391482b59d09683382ab4bc15f4854a6e75 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:17:16 +0000 Subject: [PATCH 0951/1066] build(deps): bump docker/build-push-action from 6.9.0 to 6.10.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.9.0 to 6.10.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.9.0...v6.10.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 29b01a0087c..e0b812946a8 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -60,7 +60,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.9.0 + uses: docker/build-push-action@v6.10.0 with: context: . platforms: linux/amd64,linux/arm64 From eac99f872a5f20da3297f791305e6ff518ce5bc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:19:39 +0000 Subject: [PATCH 0952/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.14.1-0.20240806063146-8fa319bfe9c5 to 0.15.0-rc.0. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/commits/v0.15.0-rc.0) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9328dc1190f..7b1025de858 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/containerd/go-cni v1.1.10 github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.14.1-0.20240806063146-8fa319bfe9c5 + github.com/containerd/nydus-snapshotter v0.15.0-rc.0 github.com/containerd/platforms v1.0.0-rc.0 github.com/containerd/stargz-snapshotter v0.16.1 github.com/containerd/stargz-snapshotter/estargz v0.16.1 diff --git a/go.sum b/go.sum index 7b5cb821efb..981e70bf43a 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,8 @@ github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 h1:7OMu5otk5Z2GeQs24JBPOmYbTc50+q6 github.com/containerd/imgcrypt/v2 v2.0.0-rc.1/go.mod h1:3/Ab3iliBt/aBVNYOwecT1YagCqAiHidOmVsrjtHF1A= 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.14.1-0.20240806063146-8fa319bfe9c5 h1:NpscnGdkmWwlb0o2Q+rDO/kfoLObfY2sHwB6M5uF58Q= -github.com/containerd/nydus-snapshotter v0.14.1-0.20240806063146-8fa319bfe9c5/go.mod h1:t7X6QEMNSz69fl5e2pF56ibd4XJ6KH9dEBrLnSwyYQk= +github.com/containerd/nydus-snapshotter v0.15.0-rc.0 h1:98s2N35oDdoLqW4DR8q69Hr8Ag9baU7MWuO/Pm19dTE= +github.com/containerd/nydus-snapshotter v0.15.0-rc.0/go.mod h1:biq0ijpeZe0I5yZFSJyHzFSjjRZQ7P7y/OuHyd7hYOw= github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA= github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= From dcaee106742c8e4672088885a5e3b9e1df903601 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Nov 2024 22:15:55 +0000 Subject: [PATCH 0953/1066] build(deps): bump the stargz group with 3 updates Bumps the stargz group with 3 updates: [github.com/containerd/stargz-snapshotter](https://github.com/containerd/stargz-snapshotter), [github.com/containerd/stargz-snapshotter/estargz](https://github.com/containerd/stargz-snapshotter) and [github.com/containerd/stargz-snapshotter/ipfs](https://github.com/containerd/stargz-snapshotter). Updates `github.com/containerd/stargz-snapshotter` from 0.16.1 to 0.16.2 - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/compare/v0.16.1...v0.16.2) Updates `github.com/containerd/stargz-snapshotter/estargz` from 0.16.1 to 0.16.2 - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/compare/v0.16.1...v0.16.2) Updates `github.com/containerd/stargz-snapshotter/ipfs` from 0.16.1 to 0.16.2 - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/compare/v0.16.1...v0.16.2) --- updated-dependencies: - dependency-name: github.com/containerd/stargz-snapshotter dependency-type: direct:production update-type: version-update:semver-patch dependency-group: stargz - dependency-name: github.com/containerd/stargz-snapshotter/estargz dependency-type: direct:production update-type: version-update:semver-patch dependency-group: stargz - dependency-name: github.com/containerd/stargz-snapshotter/ipfs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: stargz ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 7b1025de858..2341440f07e 100644 --- a/go.mod +++ b/go.mod @@ -25,9 +25,9 @@ require ( github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.15.0-rc.0 github.com/containerd/platforms v1.0.0-rc.0 - github.com/containerd/stargz-snapshotter v0.16.1 - github.com/containerd/stargz-snapshotter/estargz v0.16.1 - github.com/containerd/stargz-snapshotter/ipfs v0.16.1 + github.com/containerd/stargz-snapshotter v0.16.2 + github.com/containerd/stargz-snapshotter/estargz v0.16.2 + github.com/containerd/stargz-snapshotter/ipfs v0.16.2 github.com/containerd/typeurl/v2 v2.2.3 github.com/containernetworking/cni v1.2.3 github.com/containernetworking/plugins v1.5.1 diff --git a/go.sum b/go.sum index 981e70bf43a..2202ce91b04 100644 --- a/go.sum +++ b/go.sum @@ -57,12 +57,12 @@ github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yu github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= -github.com/containerd/stargz-snapshotter v0.16.1 h1:Bdahjs5h/Fu+7nMfF5L/XS7mvSvIq45kSpOpDTJ6LJQ= -github.com/containerd/stargz-snapshotter v0.16.1/go.mod h1:r8lNnBB/gqhXo4Pezxo474rFTkhuzbNSqQQEzigDmk0= -github.com/containerd/stargz-snapshotter/estargz v0.16.1 h1:7YswwU6746cJBN3p3l65JRk3+NZL7bap9Y6E3YeYowk= -github.com/containerd/stargz-snapshotter/estargz v0.16.1/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= -github.com/containerd/stargz-snapshotter/ipfs v0.16.1 h1:ukd71zUeHCh0eF7nvKTtpg5zEZuH77LpuMGi3YzERj4= -github.com/containerd/stargz-snapshotter/ipfs v0.16.1/go.mod h1:PUZJPURojlqo5natkG4JF91fJ1UcO6IcObT6ZwtzZ44= +github.com/containerd/stargz-snapshotter v0.16.2 h1:Fx8t+rxUknxUah+yOnmoNRZF0tPdTXXR1YBwnZxlSE0= +github.com/containerd/stargz-snapshotter v0.16.2/go.mod h1:9cMoG3xVkegdJ5IoxDnTrRxgCht7GteV1w+ik/xZFTw= +github.com/containerd/stargz-snapshotter/estargz v0.16.2 h1:DMcqm1rd1ak2hFghkyHlquacSo+zRe+cysRR3CmSpGk= +github.com/containerd/stargz-snapshotter/estargz v0.16.2/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= +github.com/containerd/stargz-snapshotter/ipfs v0.16.2 h1:+jDyBydg+7USzVXQ2V7ahGK3+S4BM1DZchGdgwBH3n8= +github.com/containerd/stargz-snapshotter/ipfs v0.16.2/go.mod h1:d4EuGnC3RteInKAdddUbDOL88uw3vZySSLZ44pbriGM= github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= From 442b01d2e2573c73cd866ef83fc2571d5c6fe119 Mon Sep 17 00:00:00 2001 From: apostasie Date: Sun, 1 Dec 2024 20:38:08 -0800 Subject: [PATCH 0954/1066] Fix permissions for resolv.conf and hosts WriteFile uses syscall.Open, so permissions are modified by umask, if set. For people using agressive umasks (0077), /etc/resolv.conf will end-up unreadable for non root processes. See https://github.com/containerd/nerdctl/issues/3704 Signed-off-by: apostasie --- pkg/dnsutil/hostsstore/hostsstore.go | 17 +++++++++++++++++ pkg/resolvconf/resolvconf.go | 11 ++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pkg/dnsutil/hostsstore/hostsstore.go b/pkg/dnsutil/hostsstore/hostsstore.go index 507f93ec708..1980e4f934b 100644 --- a/pkg/dnsutil/hostsstore/hostsstore.go +++ b/pkg/dnsutil/hostsstore/hostsstore.go @@ -115,6 +115,14 @@ func (x *hostsStore) Acquire(meta Meta) (err error) { return errors.Join(store.ErrSystemFailure, err) } + // os.WriteFile relies on syscall.Open. Unless there are ACLs, the effective mode of the file will be matched + // against the current process umask. + // See https://www.man7.org/linux/man-pages/man2/open.2.html for details. + // Since we must make sure that these files are world readable, explicitly chmod them here. + if err = os.Chmod(loc, 0o644); err != nil { + err = errors.Join(store.ErrSystemFailure, err) + } + var content []byte content, err = json.Marshal(meta) if err != nil { @@ -176,6 +184,14 @@ func (x *hostsStore) AllocHostsFile(id string, content []byte) (location string, err = errors.Join(store.ErrSystemFailure, err) } + // os.WriteFile relies on syscall.Open. Unless there are ACLs, the effective mode of the file will be matched + // against the current process umask. + // See https://www.man7.org/linux/man-pages/man2/open.2.html for details. + // Since we must make sure that these files are world readable, explicitly chmod them here. + if err = os.Chmod(loc, 0o644); err != nil { + err = errors.Join(store.ErrSystemFailure, err) + } + return err }) if err != nil { @@ -333,6 +349,7 @@ func (x *hostsStore) updateAllHosts() (err error) { if err != nil { log.L.WithError(err).Errorf("failed to write hosts file for %q", entry) } + _ = os.Chmod(loc, 0o644) } return nil } diff --git a/pkg/resolvconf/resolvconf.go b/pkg/resolvconf/resolvconf.go index 676fc9fe366..79bec3ecd9e 100644 --- a/pkg/resolvconf/resolvconf.go +++ b/pkg/resolvconf/resolvconf.go @@ -317,7 +317,16 @@ func Build(path string, dns, dnsSearch, dnsOptions []string) (*File, error) { return nil, err } - return &File{Content: content.Bytes(), Hash: hash}, os.WriteFile(path, content.Bytes(), 0644) + err = os.WriteFile(path, content.Bytes(), 0o644) + if err != nil { + return nil, err + } + + // os.WriteFile relies on syscall.Open. Unless there are ACLs, the effective mode of the file will be matched + // against the current process umask. + // See https://www.man7.org/linux/man-pages/man2/open.2.html for details. + // Since we must make sure that these files are world readable, explicitly chmod them here. + return &File{Content: content.Bytes(), Hash: hash}, os.Chmod(path, 0o644) } func hashData(src io.Reader) (string, error) { From 4a21ba7dbc1bd59f5092824a10e0694c14033f3c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 2 Dec 2024 19:10:14 +0900 Subject: [PATCH 0955/1066] docs: the next release will be v2.0.1, not v2.1.0 ref: issue 3709 Signed-off-by: Akihiro Suda --- docs/config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config.md b/docs/config.md index 5820562e176..d31f404b205 100644 --- a/docs/config.md +++ b/docs/config.md @@ -45,7 +45,7 @@ experimental = true | `hosts_dir` | `--hosts-dir` | | `certs.d` directory | Since 0.16.0 | | `experimental` | `--experimental` | `NERDCTL_EXPERIMENTAL` | Enable [experimental features](experimental.md) | Since 0.22.3 | | `host_gateway_ip` | `--host-gateway-ip` | `NERDCTL_HOST_GATEWAY_IP` | IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the host. It has no effect without setting --add-host | Since 1.3.0 | -| `bridge_ip` | `--bridge-ip` | `NERDCTL_BRIDGE_IP` | IP address for the default nerdctl bridge network, e.g., 10.1.100.1/24 | Since 2.1.0 | +| `bridge_ip` | `--bridge-ip` | `NERDCTL_BRIDGE_IP` | IP address for the default nerdctl bridge network, e.g., 10.1.100.1/24 | Since 2.0.1 | The properties are parsed in the following precedence: 1. CLI flag From 70679d49c5ad0839e598d9cc200509310bde9c77 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 2 Dec 2024 19:20:32 +0900 Subject: [PATCH 0956/1066] update BuildKit (0.18.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.1 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.0 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.0 diff --git a/Dockerfile b/Dockerfile index 07258ef3e5b..0dd43b8fc14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.2.2 ARG CNI_PLUGINS_VERSION=v1.6.0 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.17.1 +ARG BUILDKIT_VERSION=v0.18.0 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.16.1 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.1 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.1 deleted file mode 100644 index b5bfc48ff86..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.17.1 +++ /dev/null @@ -1,2 +0,0 @@ -9352f7362045f4ae5eae55b41f8f30375d35a37f6a5931e2542916c92c3d00f9 buildkit-v0.17.1.linux-amd64.tar.gz -e232060d7782938e7c3d23c247a438e571f96fd197279c6b021a7f81deae45eb buildkit-v0.17.1.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.0 new file mode 100644 index 00000000000..937cb0348b0 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.0 @@ -0,0 +1,2 @@ +7b4d8d825a23114a20b6ccf87aa674b0792be5cb1b573b8273fe7f3fa01f40d1 buildkit-v0.18.0.linux-amd64.tar.gz +361862432dd3b4961882e5031364ab98be7618be7b80574465207f9e1e18efc3 buildkit-v0.18.0.linux-arm64.tar.gz From 09039a18fba7a7ab7d670ec11760be72ebb90c02 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 2 Dec 2024 19:22:11 +0900 Subject: [PATCH 0957/1066] update stargz-snapshotter (0.16.2) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.1 | 3 --- Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.2 | 3 +++ 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.2 diff --git a/Dockerfile b/Dockerfile index 0dd43b8fc14..2c9b39e1b32 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ ARG CNI_PLUGINS_VERSION=v1.6.0 # Extra deps: Build ARG BUILDKIT_VERSION=v0.18.0 # Extra deps: Lazy-pulling -ARG STARGZ_SNAPSHOTTER_VERSION=v0.16.1 +ARG STARGZ_SNAPSHOTTER_VERSION=v0.16.2 # Extra deps: Encryption ARG IMGCRYPT_VERSION=v2.0.0-rc.1 # Extra deps: Rootless diff --git a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.1 b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.1 deleted file mode 100644 index 43265447cbd..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.1 +++ /dev/null @@ -1,3 +0,0 @@ -59bafc59bf2536c692542876d4ff4e0d9411006c72c3030e262cc9b7b8b7b962 stargz-snapshotter-v0.16.1-linux-amd64.tar.gz -89213afb49517f5acd9d04017d0985731085ccd5495efc9073611333ba6961ee stargz-snapshotter-v0.16.1-linux-arm64.tar.gz -f1cf855870af16a653d8acb9daa3edf84687c2c05323cb958f078fb148af3eec stargz-snapshotter.service diff --git a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.2 b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.2 new file mode 100644 index 00000000000..c1aba6628f2 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.2 @@ -0,0 +1,3 @@ +1958c8eb6275fccc3f7a987eab286fefb68045d79c331660d7253e7f5be20bc0 stargz-snapshotter-v0.16.2-linux-amd64.tar.gz +fc518ac49bb97708b2a0751bedce1bc2c146a9cec7ffdd9c0830a4dc0fd97e17 stargz-snapshotter-v0.16.2-linux-arm64.tar.gz +f1cf855870af16a653d8acb9daa3edf84687c2c05323cb958f078fb148af3eec stargz-snapshotter.service From 00763909066146126fded534a600b69c4587d469 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 2 Dec 2024 22:20:17 +0900 Subject: [PATCH 0958/1066] update CNI plugins (1.6.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.0 | 2 -- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.1 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.1 diff --git a/Dockerfile b/Dockerfile index 2c9b39e1b32..aecfb5b1cac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ # Basic deps ARG CONTAINERD_VERSION=v2.0.0 ARG RUNC_VERSION=v1.2.2 -ARG CNI_PLUGINS_VERSION=v1.6.0 +ARG CNI_PLUGINS_VERSION=v1.6.1 # Extra deps: Build ARG BUILDKIT_VERSION=v0.18.0 diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.0 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.0 deleted file mode 100644 index 8329f9a59c5..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.0 +++ /dev/null @@ -1,2 +0,0 @@ -682b49ff8933a997a52107161f1745f8312364b4c7f605ccdf7a77499130d89d cni-plugins-linux-amd64-v1.6.0.tgz -db09ab057ecf60b05ba05cbec38d55b95cc139c7f1078e2e4857cc13af158cee cni-plugins-linux-arm64-v1.6.0.tgz diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.1 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.1 new file mode 100644 index 00000000000..30c484f29a2 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.1 @@ -0,0 +1,2 @@ +2503ce29ac445715ebe146073f45468153f9e28f45fa173cb060cfd9e735f563 cni-plugins-linux-amd64-v1.6.1.tgz +f0f440b968ab50ad13d9d42d993ba98ec30b2ec666846f4ef1bddc7646a701cc cni-plugins-linux-arm64-v1.6.1.tgz From 5fa9f123eef4cb237b42956c30ce3403c2ac729d Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 2 Dec 2024 13:00:36 -0800 Subject: [PATCH 0959/1066] Relax compose concurrency lock Since compose implementation is currently unsafe to use concurrently, https://github.com/containerd/nerdctl/pull/3543 did introduce a blanket locking mechanism for any and all compose operations. However, an unintended side-effect is that a call to `compose logs`, or other operations being called in no-detach mode, would effectively prevent the user from performing any further operation until these are quitting. This commit does make it so a call to `composer.Logs` does release the lock. Note the lock logic has also been moved to `pkg/composer`. Signed-off-by: apostasie --- pkg/cmd/compose/compose.go | 17 +------------- pkg/composer/lock.go | 48 ++++++++++++++++++++++++++++++++++++++ pkg/composer/logs.go | 8 +++++++ 3 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 pkg/composer/lock.go diff --git a/pkg/cmd/compose/compose.go b/pkg/cmd/compose/compose.go index 116858fa8b5..ba6e0868af1 100644 --- a/pkg/cmd/compose/compose.go +++ b/pkg/cmd/compose/compose.go @@ -30,13 +30,11 @@ import ( "github.com/containerd/platforms" "github.com/containerd/nerdctl/v2/pkg/api/types" - "github.com/containerd/nerdctl/v2/pkg/clientutil" "github.com/containerd/nerdctl/v2/pkg/cmd/volume" "github.com/containerd/nerdctl/v2/pkg/composer" "github.com/containerd/nerdctl/v2/pkg/composer/serviceparser" "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/ipfs" - "github.com/containerd/nerdctl/v2/pkg/lockutil" "github.com/containerd/nerdctl/v2/pkg/netutil" "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/nerdctl/v2/pkg/signutil" @@ -48,20 +46,7 @@ var locked *os.File // New returns a new *composer.Composer. func New(client *containerd.Client, globalOptions types.GlobalCommandOptions, options composer.Options, stdout, stderr io.Writer) (*composer.Composer, error) { - // Compose right now cannot be made safe to use concurrently, as we shell out to nerdctl for multiple operations, - // preventing us from using the lock mechanisms from the API. - // This here imposes a global lock, effectively preventing multiple compose commands from being run in parallel and - // preventing some of the problems with concurrent execution. - // This should be removed once we have better, in-depth solutions to make this concurrency safe. - // Note that we do not close the lock explicitly. Instead, the lock will get released when the `locked` global - // variable will get collected and the file descriptor closed (eg: when the binary exits). - var err error - dataStore, err := clientutil.DataStore(globalOptions.DataRoot, globalOptions.Address) - if err != nil { - return nil, err - } - locked, err = lockutil.Lock(dataStore) - if err != nil { + if err := composer.Lock(globalOptions.DataRoot, globalOptions.Address); err != nil { return nil, err } diff --git a/pkg/composer/lock.go b/pkg/composer/lock.go new file mode 100644 index 00000000000..8fedda7bfc4 --- /dev/null +++ b/pkg/composer/lock.go @@ -0,0 +1,48 @@ +/* + 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 composer + +import ( + "os" + + "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/lockutil" +) + +//nolint:unused +var locked *os.File + +func Lock(dataRoot string, address string) error { + // Compose right now cannot be made safe to use concurrently, as we shell out to nerdctl for multiple operations, + // preventing us from using the lock mechanisms from the API. + // This here allows to impose a global lock, effectively preventing multiple compose commands from being run in parallel and + // preventing some of the problems with concurrent execution. + // This should be removed once we have better, in-depth solutions to make compose concurrency safe. + // Note that in most cases we do not close the lock explicitly. Instead, the lock will get released when the `locked` global + // variable will get collected and the file descriptor closed (eg: when the binary exits). + var err error + dataStore, err := clientutil.DataStore(dataRoot, address) + if err != nil { + return err + } + locked, err = lockutil.Lock(dataStore) + return err +} + +func Unlock() error { + return lockutil.Unlock(locked) +} diff --git a/pkg/composer/logs.go b/pkg/composer/logs.go index b14722270ec..a6175d793c6 100644 --- a/pkg/composer/logs.go +++ b/pkg/composer/logs.go @@ -44,6 +44,14 @@ type LogsOptions struct { } func (c *Composer) Logs(ctx context.Context, lo LogsOptions, services []string) error { + // Whether we called `compose logs`, or we are showing logs at the end of `up`, while in non detach mode, we need + // to release the lock. At this point, no operation will be performed that needs exclusive locking anymore, and + // not releasing the lock would otherwise unduly prevent further compose operations. + // See https://github.com/containerd/nerdctl/issues/3678 + if err := Unlock(); err != nil { + return err + } + var serviceNames []string err := c.project.ForEachService(services, func(name string, svc *types.ServiceConfig) error { serviceNames = append(serviceNames, svc.Name) From 69de5dd492e93f057cff41ec53bb8276b2df23b9 Mon Sep 17 00:00:00 2001 From: Justin Alvarez Date: Thu, 21 Nov 2024 21:53:29 +0000 Subject: [PATCH 0960/1066] feat: add force-recreate and no-recreate for compose up command Signed-off-by: Justin Alvarez --- cmd/nerdctl/compose/compose_create.go | 2 +- cmd/nerdctl/compose/compose_up.go | 15 ++++++ docs/command-reference.md | 4 +- pkg/composer/container.go | 21 ++++++++ pkg/composer/logs.go | 21 ++++++-- pkg/composer/run.go | 2 +- pkg/composer/up.go | 13 +++++ pkg/composer/up_service.go | 69 ++++++++++++++++++--------- 8 files changed, 117 insertions(+), 30 deletions(-) diff --git a/cmd/nerdctl/compose/compose_create.go b/cmd/nerdctl/compose/compose_create.go index 211cc4758f9..9621398ae49 100644 --- a/cmd/nerdctl/compose/compose_create.go +++ b/cmd/nerdctl/compose/compose_create.go @@ -65,7 +65,7 @@ func composeCreateAction(cmd *cobra.Command, args []string) error { } noRecreate, err := cmd.Flags().GetBool("no-recreate") if err != nil { - return nil + return err } if forceRecreate && noRecreate { return errors.New("flag --force-recreate and --no-recreate cannot be specified together") diff --git a/cmd/nerdctl/compose/compose_up.go b/cmd/nerdctl/compose/compose_up.go index f2829ae1e02..f4670947c3f 100644 --- a/cmd/nerdctl/compose/compose_up.go +++ b/cmd/nerdctl/compose/compose_up.go @@ -47,6 +47,8 @@ func newComposeUpCommand() *cobra.Command { composeUpCommand.Flags().Bool("ipfs", false, "Allow pulling base images from IPFS during build") composeUpCommand.Flags().Bool("quiet-pull", false, "Pull without printing progress information") composeUpCommand.Flags().Bool("remove-orphans", false, "Remove containers for services not defined in the Compose file.") + composeUpCommand.Flags().Bool("force-recreate", false, "Recreate containers even if their configuration and image haven't changed.") + composeUpCommand.Flags().Bool("no-recreate", false, "Don't recreate containers if they exist, conflict with --force-recreate.") composeUpCommand.Flags().StringArray("scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.") return composeUpCommand } @@ -102,6 +104,17 @@ func composeUpAction(cmd *cobra.Command, services []string) error { if err != nil { return err } + forceRecreate, err := cmd.Flags().GetBool("force-recreate") + if err != nil { + return err + } + noRecreate, err := cmd.Flags().GetBool("no-recreate") + if err != nil { + return err + } + if forceRecreate && noRecreate { + return errors.New("flag --force-recreate and --no-recreate cannot be specified together") + } scale := make(map[string]int) for _, s := range scaleSlice { parts := strings.Split(s, "=") @@ -141,6 +154,8 @@ func composeUpAction(cmd *cobra.Command, services []string) error { QuietPull: quietPull, RemoveOrphans: removeOrphans, Scale: scale, + ForceRecreate: forceRecreate, + NoRecreate: noRecreate, } return c.Up(ctx, uo, services) } diff --git a/docs/command-reference.md b/docs/command-reference.md index 95dfddcfd45..4f7a314678a 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1410,8 +1410,10 @@ Flags: - :whale: `--quiet-pull`: Pull without printing progress information - :whale: `--scale`: Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. - :whale: `--remove-orphans`: Remove containers for services not defined in the Compose file +- :whale: `--force-recreate`: force Compose to stop and recreate all containers +- :whale: `--no-recreate`: force Compose to reuse existing containers -Unimplemented `docker-compose up` (V1) flags: `--no-deps`, `--force-recreate`, `--always-recreate-deps`, `--no-recreate`, +Unimplemented `docker-compose up` (V1) flags: `--no-deps`, `--always-recreate-deps`, `--no-start`, `--abort-on-container-exit`, `--attach-dependencies`, `--timeout`, `--renew-anon-volumes`, `--exit-code-from` Unimplemented `docker compose up` (V2) flags: `--environment` diff --git a/pkg/composer/container.go b/pkg/composer/container.go index b1e101b7238..c789e42696a 100644 --- a/pkg/composer/container.go +++ b/pkg/composer/container.go @@ -63,3 +63,24 @@ func (c *Composer) containerExists(ctx context.Context, name, service string) (b // container doesn't exist return false, nil } + +func (c *Composer) containerID(ctx context.Context, name, service string) (string, error) { + // get list of containers for service + containers, err := c.Containers(ctx, service) + if err != nil { + return "", err + } + + for _, container := range containers { + containerLabels, err := container.Labels(ctx) + if err != nil { + return "", err + } + if name == containerLabels[labels.Name] { + // container exists + return container.ID(), nil + } + } + // container doesn't exist + return "", nil +} diff --git a/pkg/composer/logs.go b/pkg/composer/logs.go index b14722270ec..daa3ed0dd6b 100644 --- a/pkg/composer/logs.go +++ b/pkg/composer/logs.go @@ -41,6 +41,7 @@ type LogsOptions struct { Tail string NoColor bool NoLogPrefix bool + LatestRun bool } func (c *Composer) Logs(ctx context.Context, lo LogsOptions, services []string) error { @@ -62,9 +63,10 @@ func (c *Composer) Logs(ctx context.Context, lo LogsOptions, services []string) func (c *Composer) logs(ctx context.Context, containers []containerd.Container, lo LogsOptions) error { var logTagMaxLen int type containerState struct { - name string - logTag string - logCmd *exec.Cmd + name string + logTag string + logCmd *exec.Cmd + startedAt string } containerStates := make(map[string]containerState, len(containers)) // key: containerID @@ -78,9 +80,15 @@ func (c *Composer) logs(ctx context.Context, containers []containerd.Container, if l := len(logTag); l > logTagMaxLen { logTagMaxLen = l } + ts, err := info.UpdatedAt.MarshalText() + if err != nil { + return err + } + containerStates[container.ID()] = containerState{ - name: name, - logTag: logTag, + name: name, + logTag: logTag, + startedAt: string(ts), } } @@ -102,6 +110,9 @@ func (c *Composer) logs(ctx context.Context, containers []containerd.Container, args = append(args, lo.Tail) } } + if lo.LatestRun { + args = append(args, fmt.Sprintf("--since=%s", state.startedAt)) + } args = append(args, id) state.logCmd = c.createNerdctlCmd(ctx, args...) diff --git a/pkg/composer/run.go b/pkg/composer/run.go index 82e3a347b52..b2e98ea2b1d 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -242,7 +242,7 @@ func (c *Composer) runServices(ctx context.Context, parsedServices []*servicepar container := ps.Containers[0] runEG.Go(func() error { - id, err := c.upServiceContainer(ctx, ps, container) + id, err := c.upServiceContainer(ctx, ps, container, RecreateForce) if err != nil { return err } diff --git a/pkg/composer/up.go b/pkg/composer/up.go index 15545a977cf..b508b8ddc3d 100644 --- a/pkg/composer/up.go +++ b/pkg/composer/up.go @@ -39,9 +39,22 @@ type UpOptions struct { IPFS bool QuietPull bool RemoveOrphans bool + ForceRecreate bool + NoRecreate bool Scale map[string]int // map of service name to replicas } +func (opts UpOptions) recreateStrategy() string { + switch { + case opts.ForceRecreate: + return RecreateForce + case opts.NoRecreate: + return RecreateNever + default: + return RecreateDiverged + } +} + func (c *Composer) Up(ctx context.Context, uo UpOptions, services []string) error { for shortName := range c.project.Networks { if err := c.upNetwork(ctx, shortName); err != nil { diff --git a/pkg/composer/up_service.go b/pkg/composer/up_service.go index f3f9b26136d..7bd6ea48c92 100644 --- a/pkg/composer/up_service.go +++ b/pkg/composer/up_service.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "os" + "os/exec" "path/filepath" "strings" "sync" @@ -45,6 +46,8 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars } } + recreate := uo.recreateStrategy() + var ( containers = make(map[string]serviceparser.Container) // key: container ID services = []string{} @@ -57,7 +60,7 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars for _, container := range ps.Containers { container := container runEG.Go(func() error { - id, err := c.upServiceContainer(ctx, ps, container) + id, err := c.upServiceContainer(ctx, ps, container, recreate) if err != nil { return err } @@ -87,6 +90,7 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars Follow: true, NoColor: uo.NoColor, NoLogPrefix: uo.NoLogPrefix, + LatestRun: recreate == RecreateNever, } if err := c.Logs(ctx, lo, services); err != nil { return err @@ -118,15 +122,35 @@ func (c *Composer) ensureServiceImage(ctx context.Context, ps *serviceparser.Ser // upServiceContainer must be called after ensureServiceImage // upServiceContainer returns container ID -func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparser.Service, container serviceparser.Container) (string, error) { +func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparser.Service, container serviceparser.Container, recreate string) (string, error) { // check if container already exists - exists, err := c.containerExists(ctx, container.Name, service.Unparsed.Name) + existingCid, err := c.containerID(ctx, container.Name, service.Unparsed.Name) if err != nil { return "", fmt.Errorf("error while checking for containers with name %q: %s", container.Name, err) } + // FIXME + if service.Unparsed.StdinOpen != service.Unparsed.Tty { + return "", fmt.Errorf("currently StdinOpen(-i) and Tty(-t) should be same") + } + + var runFlagD bool + if !service.Unparsed.StdinOpen && !service.Unparsed.Tty { + container.RunArgs = append([]string{"-d"}, container.RunArgs...) + runFlagD = true + } + + // start the existing container and exit early + if existingCid != "" && recreate == RecreateNever { + cmd := c.createNerdctlCmd(ctx, append([]string{"start"}, existingCid)...) + if err := c.executeUpCmd(ctx, cmd, container.Name, runFlagD, service.Unparsed.StdinOpen); err != nil { + return "", fmt.Errorf("error while starting existing container %s: %w", container.Name, err) + } + return existingCid, nil + } + // delete container if it already exists - if exists { + if existingCid != "" { log.G(ctx).Debugf("Container %q already exists, deleting", container.Name) delCmd := c.createNerdctlCmd(ctx, "rm", "-f", container.Name) if err = delCmd.Run(); err != nil { @@ -151,12 +175,6 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse defer os.RemoveAll(tempDir) cidFilename := filepath.Join(tempDir, "cid") - var runFlagD bool - if !service.Unparsed.StdinOpen && !service.Unparsed.Tty { - container.RunArgs = append([]string{"-d"}, container.RunArgs...) - runFlagD = true - } - //add metadata labels to container https://github.com/compose-spec/compose-spec/blob/master/spec.md#labels container.RunArgs = append([]string{ "--cidfile=" + cidFilename, @@ -169,12 +187,24 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse log.G(ctx).Debugf("Running %v", cmd.Args) } - // FIXME - if service.Unparsed.StdinOpen != service.Unparsed.Tty { - return "", fmt.Errorf("currently StdinOpen(-i) and Tty(-t) should be same") + if err := c.executeUpCmd(ctx, cmd, container.Name, runFlagD, service.Unparsed.StdinOpen); err != nil { + return "", fmt.Errorf("error while creating container %s: %w", container.Name, err) + } + + cid, err := os.ReadFile(cidFilename) + if err != nil { + return "", fmt.Errorf("error while creating container %s: %w", container.Name, err) + } + return strings.TrimSpace(string(cid)), nil +} + +func (c *Composer) executeUpCmd(ctx context.Context, cmd *exec.Cmd, containerName string, runFlagD, stdinOpen bool) error { + log.G(ctx).Infof("Running %v", cmd.Args) + if c.DebugPrintFull { + log.G(ctx).Debugf("Running %v", cmd.Args) } - if service.Unparsed.StdinOpen { + if stdinOpen { cmd.Stdin = os.Stdin } if !runFlagD { @@ -183,14 +213,9 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse // Always propagate stderr to print detailed error messages (https://github.com/containerd/nerdctl/issues/1942) cmd.Stderr = os.Stderr - err = cmd.Run() - if err != nil { - return "", fmt.Errorf("error while creating container %s: %w", container.Name, err) + if err := cmd.Run(); err != nil { + return fmt.Errorf("error while creating container %s: %w", containerName, err) } - cid, err := os.ReadFile(cidFilename) - if err != nil { - return "", fmt.Errorf("error while creating container %s: %w", container.Name, err) - } - return strings.TrimSpace(string(cid)), nil + return nil } From 531e203682ef97be689ac7402f09a03853c44983 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 2 Dec 2024 14:18:30 -0800 Subject: [PATCH 0961/1066] Marking TestCreate/logs as flaky Signed-off-by: apostasie --- cmd/nerdctl/container/container_create_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/nerdctl/container/container_create_test.go b/cmd/nerdctl/container/container_create_test.go index 12b6a8af519..6885a1e64aa 100644 --- a/cmd/nerdctl/container/container_create_test.go +++ b/cmd/nerdctl/container/container_create_test.go @@ -39,6 +39,8 @@ func TestCreate(t *testing.T) { helpers.Anyhow("rm", "-f", data.Identifier("container")) } + testCase.Require = nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3717") + testCase.SubTests = []*test.Case{ { Description: "ps -a", From e28491fa2bbf9a1e772548aafd5c6fc8a3c8fe7f Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 2 Dec 2024 13:55:54 -0800 Subject: [PATCH 0962/1066] Enhance CNI config load error condition UX Signed-off-by: apostasie --- pkg/netutil/netutil.go | 48 +++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index abab2b5ab61..5708cbc9487 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -501,7 +501,6 @@ func (e *CNIEnv) writeNetworkConfig(net *NetworkConfig) error { // networkConfigList loads config from dir if dir exists. func (e *CNIEnv) networkConfigList() ([]*NetworkConfig, error) { - l := []*NetworkConfig{} common, err := libcni.ConfFiles(e.NetconfPath, []string{".conf", ".conflist", ".json"}) if err != nil { return nil, err @@ -513,34 +512,53 @@ func (e *CNIEnv) networkConfigList() ([]*NetworkConfig, error) { return nil, err } } - fileNames := append(common, namespaced...) + return cniLoad(append(common, namespaced...)) +} + +func wrapCNIError(fileName string, err error) error { + return fmt.Errorf("failed marshalling json out of network configuration file %q: %w\n"+ + "For details on the schema, see https://pkg.go.dev/github.com/containernetworking/cni/libcni#NetworkConfigList", fileName, err) +} + +func cniLoad(fileNames []string) (configList []*NetworkConfig, err error) { + var fileName string + sort.Strings(fileNames) - for _, fileName := range fileNames { - var lcl *libcni.NetworkConfigList + + for _, fileName = range fileNames { + var bytes []byte + bytes, err = os.ReadFile(fileName) + if err != nil { + return nil, fmt.Errorf("error reading %s: %w", fileName, err) + } + + var netConfigList *libcni.NetworkConfigList if strings.HasSuffix(fileName, ".conflist") { - lcl, err = libcni.ConfListFromFile(fileName) + netConfigList, err = libcni.ConfListFromBytes(bytes) if err != nil { - return nil, err + return nil, wrapCNIError(fileName, err) } } else { - lc, err := libcni.ConfFromFile(fileName) + var netConfig *libcni.NetworkConfig + netConfig, err = libcni.ConfFromBytes(bytes) if err != nil { - return nil, err + return nil, wrapCNIError(fileName, err) } - lcl, err = libcni.ConfListFromConf(lc) + netConfigList, err = libcni.ConfListFromConf(netConfig) if err != nil { - return nil, err + return nil, wrapCNIError(fileName, err) } } - id, lbls := nerdctlIDLabels(lcl.Bytes) - l = append(l, &NetworkConfig{ - NetworkConfigList: lcl, + id, nerdctlLabels := nerdctlIDLabels(netConfigList.Bytes) + configList = append(configList, &NetworkConfig{ + NetworkConfigList: netConfigList, NerdctlID: id, - NerdctlLabels: lbls, + NerdctlLabels: nerdctlLabels, File: fileName, }) } - return l, nil + + return configList, nil } func nerdctlIDLabels(b []byte) (*string, *map[string]string) { From e2708fb59b33d5eaf4a42232c71e2c1ff4367f82 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 2 Dec 2024 15:47:47 -0800 Subject: [PATCH 0963/1066] Fix hosts.toml resolution for docker domain Signed-off-by: apostasie --- pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go index 5262dd729d0..8577b8e2bc6 100644 --- a/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go +++ b/pkg/imgutil/dockerconfigresolver/dockerconfigresolver.go @@ -82,6 +82,13 @@ func NewHostOptions(ctx context.Context, refHostname string, optFuncs ...Opt) (* ho.HostDir = func(hostURL string) (string, error) { regURL, err := Parse(hostURL) + // Docker inconsistencies handling: `index.docker.io` actually expects `docker.io` for hosts.toml on the filesystem + // See https://github.com/containerd/nerdctl/issues/3697 + // FIXME: we need to reevaluate this comparing with what docker does. What should happen for FQ images with alternate docker domains? (eg: registry-1.docker.io) + if regURL.Hostname() == "index.docker.io" { + regURL.Host = "docker.io" + } + if err != nil { return "", err } From 32ab7472f3e535c3317e6522205abe64e2864227 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 2 Dec 2024 21:43:21 -0800 Subject: [PATCH 0964/1066] Create directory for bypass4netns pid file Signed-off-by: apostasie --- pkg/bypass4netnsutil/bypass4netnsutil.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/bypass4netnsutil/bypass4netnsutil.go b/pkg/bypass4netnsutil/bypass4netnsutil.go index 7fa7e605a72..b34f1e4c08f 100644 --- a/pkg/bypass4netnsutil/bypass4netnsutil.go +++ b/pkg/bypass4netnsutil/bypass4netnsutil.go @@ -131,8 +131,14 @@ func GetPidFilePathByID(id string) (string, error) { return "", err } - socketPath := filepath.Join(xdgRuntimeDir, "bypass4netns", id[0:15]+".pid") - return socketPath, nil + pidPath := filepath.Join(xdgRuntimeDir, "bypass4netns", id[0:15]+".pid") + + err = os.MkdirAll(filepath.Join(xdgRuntimeDir, "bypass4netns"), 0o700) + if err != nil { + return "", err + } + + return pidPath, nil } func IsBypass4netnsEnabled(annotationsMap map[string]string) (enabled, bindEnabled bool, err error) { From 775a005375fa3831f88fab24b5a5876932a695b6 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 21 Aug 2024 16:19:36 -0700 Subject: [PATCH 0965/1066] gocni -> cni Signed-off-by: apostasie --- cmd/nerdctl/compose/compose_ps.go | 4 +- .../container/container_run_network.go | 4 +- pkg/api/types/container_network_types.go | 4 +- pkg/bypass4netnsutil/bypass.go | 4 +- pkg/cmd/container/create.go | 4 +- pkg/cmd/container/kill.go | 18 +++---- .../container_network_manager_windows.go | 28 +++++----- pkg/defaults/defaults_freebsd.go | 6 +-- pkg/defaults/defaults_linux.go | 8 +-- pkg/labels/labels.go | 2 +- pkg/ocihook/ocihook.go | 54 +++++++++---------- pkg/ocihook/rootless_linux.go | 6 +-- pkg/ocihook/rootless_other.go | 6 +-- pkg/portutil/portutil.go | 16 +++--- pkg/portutil/portutil_test.go | 36 ++++++------- pkg/rootlessutil/port_linux.go | 6 +-- 16 files changed, 103 insertions(+), 103 deletions(-) diff --git a/cmd/nerdctl/compose/compose_ps.go b/cmd/nerdctl/compose/compose_ps.go index 421731f78b7..1626b14cd5f 100644 --- a/cmd/nerdctl/compose/compose_ps.go +++ b/cmd/nerdctl/compose/compose_ps.go @@ -29,7 +29,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/runtime/restart" "github.com/containerd/errdefs" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" @@ -323,7 +323,7 @@ type PortPublisher struct { // formatPublishers parses and returns docker-compatible []PortPublisher from // label map. If an error happens, an empty slice is returned. func formatPublishers(labelMap map[string]string) []PortPublisher { - mapper := func(pm gocni.PortMapping) PortPublisher { + mapper := func(pm cni.PortMapping) PortPublisher { return PortPublisher{ URL: pm.HostIP, TargetPort: int(pm.ContainerPort), diff --git a/cmd/nerdctl/container/container_run_network.go b/cmd/nerdctl/container/container_run_network.go index f731a53aaef..fdf75a2e8ba 100644 --- a/cmd/nerdctl/container/container_run_network.go +++ b/cmd/nerdctl/container/container_run_network.go @@ -21,7 +21,7 @@ import ( "github.com/spf13/cobra" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/portutil" @@ -144,7 +144,7 @@ func loadNetworkFlags(cmd *cobra.Command) (types.NetworkOptions, error) { return netOpts, err } portSlice = strutil.DedupeStrSlice(portSlice) - portMappings := []gocni.PortMapping{} + portMappings := []cni.PortMapping{} for _, p := range portSlice { pm, err := portutil.ParseFlagP(p) if err != nil { diff --git a/pkg/api/types/container_network_types.go b/pkg/api/types/container_network_types.go index 28e9a54102a..c4b5971240c 100644 --- a/pkg/api/types/container_network_types.go +++ b/pkg/api/types/container_network_types.go @@ -17,7 +17,7 @@ package types import ( - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" ) // NetworkOptions struct defining networking-related options. @@ -43,5 +43,5 @@ type NetworkOptions struct { // UTS namespace to use UTSNamespace string // PortMappings specifies a list of ports to publish from the container to the host - PortMappings []gocni.PortMapping + PortMappings []cni.PortMapping } diff --git a/pkg/bypass4netnsutil/bypass.go b/pkg/bypass4netnsutil/bypass.go index a6112ea3858..bc9eed11f9d 100644 --- a/pkg/bypass4netnsutil/bypass.go +++ b/pkg/bypass4netnsutil/bypass.go @@ -28,7 +28,7 @@ import ( rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" "github.com/containerd/errdefs" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/nerdctl/v2/pkg/annotations" ) @@ -66,7 +66,7 @@ type Bypass4netnsCNIBypassManager struct { ignoreBind bool } -func (b4nnm *Bypass4netnsCNIBypassManager) StartBypass(ctx context.Context, ports []gocni.PortMapping, id, stateDir string) error { +func (b4nnm *Bypass4netnsCNIBypassManager) StartBypass(ctx context.Context, ports []cni.PortMapping, id, stateDir string) error { socketPath, err := GetSocketPathByID(id) if err != nil { return err diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 7ee88f82d4a..946203ad1e3 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -37,7 +37,7 @@ import ( "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/oci" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/annotations" @@ -646,7 +646,7 @@ type internalLabels struct { networks []string ipAddress string ip6Address string - ports []gocni.PortMapping + ports []cni.PortMapping macAddress string // volume mountPoints []*mountutil.Processed diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index f986bf184ac..ceb4ef9ac88 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -29,7 +29,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/errdefs" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/api/types" @@ -131,8 +131,8 @@ func cleanupNetwork(ctx context.Context, container containerd.Container, globalO if portErr != nil { return fmt.Errorf("no oci spec: %q", portErr) } - portMappings := []gocni.NamespaceOpts{ - gocni.WithCapabilityPortMap(ports), + portMappings := []cni.NamespaceOpts{ + cni.WithCapabilityPortMap(ports), } // retrieve info to get cni instance @@ -158,26 +158,26 @@ func cleanupNetwork(ctx context.Context, container containerd.Container, globalO if err != nil { return err } - cniOpts := []gocni.Opt{ - gocni.WithPluginDir([]string{globalOpts.CNIPath}), + cniOpts := []cni.Opt{ + cni.WithPluginDir([]string{globalOpts.CNIPath}), } var netw *netutil.NetworkConfig for _, netstr := range networks { if netw, err = e.NetworkByNameOrID(netstr); err != nil { return err } - cniOpts = append(cniOpts, gocni.WithConfListBytes(netw.Bytes)) + cniOpts = append(cniOpts, cni.WithConfListBytes(netw.Bytes)) } - cni, err := gocni.New(cniOpts...) + cniObj, err := cni.New(cniOpts...) if err != nil { return err } - var namespaceOpts []gocni.NamespaceOpts + var namespaceOpts []cni.NamespaceOpts namespaceOpts = append(namespaceOpts, portMappings...) namespace := spec.Annotations[labels.Namespace] fullID := namespace + "-" + container.ID() - if err := cni.Remove(ctx, fullID, "", namespaceOpts...); err != nil { + if err := cniObj.Remove(ctx, fullID, "", namespaceOpts...); err != nil { log.L.WithError(err).Errorf("failed to call cni.Remove") return err } diff --git a/pkg/containerutil/container_network_manager_windows.go b/pkg/containerutil/container_network_manager_windows.go index 45128d8bfe9..6cde2b351d8 100644 --- a/pkg/containerutil/container_network_manager_windows.go +++ b/pkg/containerutil/container_network_manager_windows.go @@ -23,7 +23,7 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/netns" "github.com/containerd/containerd/v2/pkg/oci" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/netutil" @@ -66,26 +66,26 @@ func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { return nil } -func (m *cniNetworkManager) getCNI() (gocni.CNI, error) { +func (m *cniNetworkManager) getCNI() (cni.CNI, error) { e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork(m.globalOptions.BridgeIP)) if err != nil { return nil, fmt.Errorf("failed to instantiate CNI env: %s", err) } - cniOpts := []gocni.Opt{ - gocni.WithPluginDir([]string{m.globalOptions.CNIPath}), - gocni.WithPluginConfDir(m.globalOptions.CNINetConfPath), + cniOpts := []cni.Opt{ + cni.WithPluginDir([]string{m.globalOptions.CNIPath}), + cni.WithPluginConfDir(m.globalOptions.CNINetConfPath), } if netMap, err := verifyNetworkTypes(e, m.netOpts.NetworkSlice, nil); err == nil { for _, netConf := range netMap { - cniOpts = append(cniOpts, gocni.WithConfListBytes(netConf.Bytes)) + cniOpts = append(cniOpts, cni.WithConfListBytes(netConf.Bytes)) } } else { return nil, err } - return gocni.New(cniOpts...) + return cni.New(cniOpts...) } // Performs setup actions required for the container with the given ID. @@ -171,10 +171,10 @@ func (m *cniNetworkManager) setupNetNs() (*netns.NetNS, error) { return ns, err } -// Returns the []gocni.NamespaceOpts to be used for CNI setup/teardown. -func (m *cniNetworkManager) getCNINamespaceOpts() []gocni.NamespaceOpts { - opts := []gocni.NamespaceOpts{ - gocni.WithLabels(map[string]string{ +// Returns the []cni.NamespaceOpts to be used for CNI setup/teardown. +func (m *cniNetworkManager) getCNINamespaceOpts() []cni.NamespaceOpts { + opts := []cni.NamespaceOpts{ + cni.WithLabels(map[string]string{ // allow loose CNI argument verification // FYI: https://github.com/containernetworking/cni/issues/560 "IgnoreUnknown": "1", @@ -182,15 +182,15 @@ func (m *cniNetworkManager) getCNINamespaceOpts() []gocni.NamespaceOpts { } if m.netOpts.MACAddress != "" { - opts = append(opts, gocni.WithArgs("MAC", m.netOpts.MACAddress)) + opts = append(opts, cni.WithArgs("MAC", m.netOpts.MACAddress)) } if m.netOpts.IPAddress != "" { - opts = append(opts, gocni.WithArgs("IP", m.netOpts.IPAddress)) + opts = append(opts, cni.WithArgs("IP", m.netOpts.IPAddress)) } if m.netOpts.PortMappings != nil { - opts = append(opts, gocni.WithCapabilityPortMap(m.netOpts.PortMappings)) + opts = append(opts, cni.WithCapabilityPortMap(m.netOpts.PortMappings)) } return opts diff --git a/pkg/defaults/defaults_freebsd.go b/pkg/defaults/defaults_freebsd.go index 8c165353b88..8092beb8585 100644 --- a/pkg/defaults/defaults_freebsd.go +++ b/pkg/defaults/defaults_freebsd.go @@ -17,7 +17,7 @@ package defaults import ( - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" ) const ( @@ -32,11 +32,11 @@ func DataRoot() string { func CNIPath() string { // default: /opt/cni/bin - return gocni.DefaultCNIDir + return cni.DefaultCNIDir } func CNINetConfPath() string { - return gocni.DefaultNetDir + return cni.DefaultNetDir } func CNIRuntimeDir() string { diff --git a/pkg/defaults/defaults_linux.go b/pkg/defaults/defaults_linux.go index 6de6f294333..ac35cf9c786 100644 --- a/pkg/defaults/defaults_linux.go +++ b/pkg/defaults/defaults_linux.go @@ -23,7 +23,7 @@ import ( "path/filepath" "github.com/containerd/containerd/v2/plugins" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" @@ -48,7 +48,7 @@ func DataRoot() string { func CNIPath() string { candidates := []string{ - gocni.DefaultCNIDir, // /opt/cni/bin + cni.DefaultCNIDir, // /opt/cni/bin "/usr/local/libexec/cni", "/usr/local/lib/cni", "/usr/libexec/cni", // Fedora @@ -74,12 +74,12 @@ func CNIPath() string { } // default: /opt/cni/bin - return gocni.DefaultCNIDir + return cni.DefaultCNIDir } func CNINetConfPath() string { if !rootlessutil.IsRootless() { - return gocni.DefaultNetDir + return cni.DefaultNetDir } xch, err := rootlessutil.XDGConfigHome() if err != nil { diff --git a/pkg/labels/labels.go b/pkg/labels/labels.go index e470c7230dc..e2dd6ede16d 100644 --- a/pkg/labels/labels.go +++ b/pkg/labels/labels.go @@ -54,7 +54,7 @@ const ( // Currently, the length of the slice must be 1. Networks = Prefix + "networks" - // Ports is a JSON-marshalled string of []gocni.PortMapping . + // Ports is a JSON-marshalled string of []cni.PortMapping . Ports = Prefix + "ports" // IPAddress is the static IP address of the container assigned by the user diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index 7e31eb1c1a5..bcebedca18c 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -33,7 +33,7 @@ import ( b4nndclient "github.com/rootless-containers/bypass4netns/pkg/api/daemon/client" rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/bypass4netnsutil" @@ -177,18 +177,18 @@ func newHandlerOpts(state *specs.State, dataStore, cniPath, cniNetconfPath, brid if err != nil { return nil, err } - cniOpts := []gocni.Opt{ - gocni.WithPluginDir([]string{cniPath}), + cniOpts := []cni.Opt{ + cni.WithPluginDir([]string{cniPath}), } var netw *netutil.NetworkConfig for _, netstr := range networks { if netw, err = e.NetworkByNameOrID(netstr); err != nil { return nil, err } - cniOpts = append(cniOpts, gocni.WithConfListBytes(netw.Bytes)) + cniOpts = append(cniOpts, cni.WithConfListBytes(netw.Bytes)) o.cniNames = append(o.cniNames, netstr) } - o.cni, err = gocni.New(cniOpts...) + o.cni, err = cni.New(cniOpts...) if err != nil { return nil, err } @@ -250,8 +250,8 @@ type handlerOpts struct { state *specs.State dataStore string rootfs string - ports []gocni.PortMapping - cni gocni.CNI + ports []cni.PortMapping + cni cni.CNI cniNames []string fullID string rootlessKitClient rlkclient.Client @@ -322,10 +322,10 @@ func getNetNSPath(state *specs.State) (string, error) { return s, nil } -func getPortMapOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { +func getPortMapOpts(opts *handlerOpts) ([]cni.NamespaceOpts, error) { if len(opts.ports) > 0 { if !rootlessutil.IsRootlessChild() { - return []gocni.NamespaceOpts{gocni.WithCapabilityPortMap(opts.ports)}, nil + return []cni.NamespaceOpts{cni.WithCapabilityPortMap(opts.ports)}, nil } var ( childIP net.IP @@ -343,7 +343,7 @@ func getPortMapOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { // // We must NOT modify opts.ports here, because we use the unmodified opts.ports for // interaction with RootlessKit API. - ports := make([]gocni.PortMapping, len(opts.ports)) + ports := make([]cni.PortMapping, len(opts.ports)) for i, p := range opts.ports { if hostIP := net.ParseIP(p.HostIP); hostIP != nil && !hostIP.IsUnspecified() { // loopback address is always bindable in the child namespace, but other addresses are unlikely. @@ -361,56 +361,56 @@ func getPortMapOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { } ports[i] = p } - return []gocni.NamespaceOpts{gocni.WithCapabilityPortMap(ports)}, nil + return []cni.NamespaceOpts{cni.WithCapabilityPortMap(ports)}, nil } return nil, nil } -func getIPAddressOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { +func getIPAddressOpts(opts *handlerOpts) ([]cni.NamespaceOpts, error) { if opts.containerIP != "" { if rootlessutil.IsRootlessChild() { log.L.Debug("container IP assignment is not fully supported in rootless mode. The IP is not accessible from the host (but still accessible from other containers).") } - return []gocni.NamespaceOpts{ - gocni.WithLabels(map[string]string{ + return []cni.NamespaceOpts{ + cni.WithLabels(map[string]string{ // Special tick for go-cni. Because go-cni marks all labels and args as same // So, we need add a special label to pass the containerIP to the host-local plugin. // FYI: https://github.com/containerd/go-cni/blob/v1.1.3/README.md?plain=1#L57-L64 "IgnoreUnknown": "1", }), - gocni.WithArgs("IP", opts.containerIP), + cni.WithArgs("IP", opts.containerIP), }, nil } return nil, nil } -func getMACAddressOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { +func getMACAddressOpts(opts *handlerOpts) ([]cni.NamespaceOpts, error) { if opts.containerMAC != "" { - return []gocni.NamespaceOpts{ - gocni.WithLabels(map[string]string{ + return []cni.NamespaceOpts{ + cni.WithLabels(map[string]string{ // allow loose CNI argument verification // FYI: https://github.com/containernetworking/cni/issues/560 "IgnoreUnknown": "1", }), - gocni.WithArgs("MAC", opts.containerMAC), + cni.WithArgs("MAC", opts.containerMAC), }, nil } return nil, nil } -func getIP6AddressOpts(opts *handlerOpts) ([]gocni.NamespaceOpts, error) { +func getIP6AddressOpts(opts *handlerOpts) ([]cni.NamespaceOpts, error) { if opts.containerIP6 != "" { if rootlessutil.IsRootlessChild() { log.L.Debug("container IP6 assignment is not fully supported in rootless mode. The IP6 is not accessible from the host (but still accessible from other containers).") } - return []gocni.NamespaceOpts{ - gocni.WithLabels(map[string]string{ + return []cni.NamespaceOpts{ + cni.WithLabels(map[string]string{ // allow loose CNI argument verification // FYI: https://github.com/containernetworking/cni/issues/560 "IgnoreUnknown": "1", }), - gocni.WithCapability("ips", []string{opts.containerIP6}), + cni.WithCapability("ips", []string{opts.containerIP6}), }, nil } return nil, nil @@ -442,16 +442,16 @@ func applyNetworkSettings(opts *handlerOpts) error { if err != nil { return err } - var namespaceOpts []gocni.NamespaceOpts + var namespaceOpts []cni.NamespaceOpts namespaceOpts = append(namespaceOpts, portMapOpts...) namespaceOpts = append(namespaceOpts, ipAddressOpts...) namespaceOpts = append(namespaceOpts, macAddressOpts...) namespaceOpts = append(namespaceOpts, ip6AddressOpts...) namespaceOpts = append(namespaceOpts, - gocni.WithLabels(map[string]string{ + cni.WithLabels(map[string]string{ "IgnoreUnknown": "1", }), - gocni.WithArgs("NERDCTL_CNI_DHCP_HOSTNAME", opts.state.Annotations[labels.Hostname]), + cni.WithArgs("NERDCTL_CNI_DHCP_HOSTNAME", opts.state.Annotations[labels.Hostname]), ) hsMeta := hostsstore.Meta{ ID: opts.state.ID, @@ -610,7 +610,7 @@ func onPostStop(opts *handlerOpts) error { if err != nil { return err } - var namespaceOpts []gocni.NamespaceOpts + var namespaceOpts []cni.NamespaceOpts namespaceOpts = append(namespaceOpts, portMapOpts...) namespaceOpts = append(namespaceOpts, ipAddressOpts...) namespaceOpts = append(namespaceOpts, macAddressOpts...) diff --git a/pkg/ocihook/rootless_linux.go b/pkg/ocihook/rootless_linux.go index b319d4f0647..5f908e62d15 100644 --- a/pkg/ocihook/rootless_linux.go +++ b/pkg/ocihook/rootless_linux.go @@ -21,12 +21,12 @@ import ( rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" ) -func exposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []gocni.PortMapping) error { +func exposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []cni.PortMapping) error { pm, err := rootlessutil.NewRootlessCNIPortManager(rlkClient) if err != nil { return err @@ -40,7 +40,7 @@ func exposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports return nil } -func unexposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []gocni.PortMapping) error { +func unexposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []cni.PortMapping) error { pm, err := rootlessutil.NewRootlessCNIPortManager(rlkClient) if err != nil { return err diff --git a/pkg/ocihook/rootless_other.go b/pkg/ocihook/rootless_other.go index 4109aed8a03..ed1485a958a 100644 --- a/pkg/ocihook/rootless_other.go +++ b/pkg/ocihook/rootless_other.go @@ -24,13 +24,13 @@ import ( rlkclient "github.com/rootless-containers/rootlesskit/v2/pkg/api/client" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" ) -func exposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []gocni.PortMapping) error { +func exposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []cni.PortMapping) error { return fmt.Errorf("cannot expose ports rootlessly on non-Linux hosts") } -func unexposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []gocni.PortMapping) error { +func unexposePortsRootless(ctx context.Context, rlkClient rlkclient.Client, ports []cni.PortMapping) error { return fmt.Errorf("cannot unexpose ports rootlessly on non-Linux hosts") } diff --git a/pkg/portutil/portutil.go b/pkg/portutil/portutil.go index a901e2051f5..28a1836bb2f 100644 --- a/pkg/portutil/portutil.go +++ b/pkg/portutil/portutil.go @@ -24,7 +24,7 @@ import ( "github.com/docker/go-connections/nat" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/labels" @@ -50,7 +50,7 @@ func splitParts(rawport string) (string, string, string) { // ParseFlagP parse port mapping pair, like "127.0.0.1:3000:8080/tcp", // "127.0.0.1:3000-3001:8080-8081/tcp" and "3000:8080" ... -func ParseFlagP(s string) ([]gocni.PortMapping, error) { +func ParseFlagP(s string) ([]cni.PortMapping, error) { proto := "tcp" splitBySlash := strings.Split(s, "/") switch len(splitBySlash) { @@ -67,11 +67,11 @@ func ParseFlagP(s string) ([]gocni.PortMapping, error) { return nil, fmt.Errorf("failed to parse %q, unexpected slashes", s) } - res := gocni.PortMapping{ + res := cni.PortMapping{ Protocol: proto, } - mr := []gocni.PortMapping{} + mr := []cni.PortMapping{} ip, hostPort, containerPort := splitParts(splitBySlash[0]) @@ -130,13 +130,13 @@ func ParseFlagP(s string) ([]gocni.PortMapping, error) { } // ParsePortsLabel parses JSON-marshalled string from label map -// (under `labels.Ports` key) and returns []gocni.PortMapping. -func ParsePortsLabel(labelMap map[string]string) ([]gocni.PortMapping, error) { +// (under `labels.Ports` key) and returns []cni.PortMapping. +func ParsePortsLabel(labelMap map[string]string) ([]cni.PortMapping, error) { portsJSON := labelMap[labels.Ports] if portsJSON == "" { - return []gocni.PortMapping{}, nil + return []cni.PortMapping{}, nil } - var ports []gocni.PortMapping + var ports []cni.PortMapping if err := json.Unmarshal([]byte(portsJSON), &ports); err != nil { return nil, fmt.Errorf("failed to parse label %q=%q: %s", labels.Ports, portsJSON, err.Error()) } diff --git a/pkg/portutil/portutil_test.go b/pkg/portutil/portutil_test.go index d4c48c05a64..d14c79786c3 100644 --- a/pkg/portutil/portutil_test.go +++ b/pkg/portutil/portutil_test.go @@ -22,7 +22,7 @@ import ( "sort" "testing" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" @@ -38,7 +38,7 @@ func TestTestParseFlagPWithPlatformSpec(t *testing.T) { tests := []struct { name string args args - want []gocni.PortMapping + want []cni.PortMapping wantErr bool }{ { @@ -46,7 +46,7 @@ func TestTestParseFlagPWithPlatformSpec(t *testing.T) { args: args{ s: "3000", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 3000, @@ -61,7 +61,7 @@ func TestTestParseFlagPWithPlatformSpec(t *testing.T) { args: args{ s: "3000-3001", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 3000, @@ -90,7 +90,7 @@ func TestTestParseFlagPWithPlatformSpec(t *testing.T) { args: args{ s: "3000-3001/tcp", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 3000, @@ -111,7 +111,7 @@ func TestTestParseFlagPWithPlatformSpec(t *testing.T) { args: args{ s: "3000-3001/udp", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 3000, @@ -168,7 +168,7 @@ func TestParsePortsLabel(t *testing.T) { tests := []struct { name string labelMap map[string]string - want []gocni.PortMapping + want []cni.PortMapping wantErr bool }{ { @@ -176,7 +176,7 @@ func TestParsePortsLabel(t *testing.T) { labelMap: map[string]string{ labels.Ports: "[{\"HostPort\":12345,\"ContainerPort\":10000,\"Protocol\":\"tcp\",\"HostIP\":\"0.0.0.0\"}]", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 8080, @@ -191,13 +191,13 @@ func TestParsePortsLabel(t *testing.T) { labelMap: map[string]string{ labels.Ports: "", }, - want: []gocni.PortMapping{}, + want: []cni.PortMapping{}, wantErr: false, }, { name: "empty ports (key not exists)", labelMap: map[string]string{}, - want: []gocni.PortMapping{}, + want: []cni.PortMapping{}, wantErr: false, }, { @@ -251,7 +251,7 @@ func TestParseFlagP(t *testing.T) { tests := []struct { name string args args - want []gocni.PortMapping + want []cni.PortMapping wantErr bool }{ { @@ -259,7 +259,7 @@ func TestParseFlagP(t *testing.T) { args: args{ s: "127.0.0.1:3000:8080/tcp", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 8080, @@ -274,7 +274,7 @@ func TestParseFlagP(t *testing.T) { args: args{ s: "127.0.0.1:3000-3001:8080-8081/tcp", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 8080, @@ -303,7 +303,7 @@ func TestParseFlagP(t *testing.T) { args: args{ s: "3000:8080/tcp", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 8080, @@ -318,7 +318,7 @@ func TestParseFlagP(t *testing.T) { args: args{ s: "3000:8080", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 8080, @@ -333,7 +333,7 @@ func TestParseFlagP(t *testing.T) { args: args{ s: "3000:8080/udp", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 8080, @@ -348,7 +348,7 @@ func TestParseFlagP(t *testing.T) { args: args{ s: "3000:8080/sctp", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 3000, ContainerPort: 8080, @@ -363,7 +363,7 @@ func TestParseFlagP(t *testing.T) { args: args{ s: "[::0]:8080:80/tcp", }, - want: []gocni.PortMapping{ + want: []cni.PortMapping{ { HostPort: 8080, ContainerPort: 80, diff --git a/pkg/rootlessutil/port_linux.go b/pkg/rootlessutil/port_linux.go index d885e1263e6..dddf37a6f98 100644 --- a/pkg/rootlessutil/port_linux.go +++ b/pkg/rootlessutil/port_linux.go @@ -24,7 +24,7 @@ import ( "github.com/rootless-containers/rootlesskit/v2/pkg/port" "github.com/containerd/errdefs" - gocni "github.com/containerd/go-cni" + "github.com/containerd/go-cni" ) func NewRootlessCNIPortManager(client client.Client) (*RootlessCNIPortManager, error) { @@ -41,7 +41,7 @@ type RootlessCNIPortManager struct { client.Client } -func (rlcpm *RootlessCNIPortManager) ExposePort(ctx context.Context, cpm gocni.PortMapping) error { +func (rlcpm *RootlessCNIPortManager) ExposePort(ctx context.Context, cpm cni.PortMapping) error { // NOTE: When `nerdctl run -p 8080:80` is being launched, cpm.HostPort is set to 8080 and cpm.ContainerPort is set to 80. // We want to forward the port 8080 of the parent namespace into the port 8080 of the child namespace (which is the "host" // from the point of view of CNI). So we do NOT set sp.ChildPort to cpm.ContainerPort here. @@ -55,7 +55,7 @@ func (rlcpm *RootlessCNIPortManager) ExposePort(ctx context.Context, cpm gocni.P return err } -func (rlcpm *RootlessCNIPortManager) UnexposePort(ctx context.Context, cpm gocni.PortMapping) error { +func (rlcpm *RootlessCNIPortManager) UnexposePort(ctx context.Context, cpm cni.PortMapping) error { pm := rlcpm.Client.PortManager() ports, err := pm.ListPorts(ctx) if err != nil { From f914ea388625cc44ff5251fceb893a7d4118b18a Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 21 Aug 2024 16:20:56 -0700 Subject: [PATCH 0966/1066] gocontext -> context Signed-off-by: apostasie --- pkg/consoleutil/consoleutil_unix.go | 4 ++-- pkg/consoleutil/consoleutil_windows.go | 4 ++-- pkg/signalutil/signals.go | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/consoleutil/consoleutil_unix.go b/pkg/consoleutil/consoleutil_unix.go index d3bd02f0204..5cc05685021 100644 --- a/pkg/consoleutil/consoleutil_unix.go +++ b/pkg/consoleutil/consoleutil_unix.go @@ -19,7 +19,7 @@ package consoleutil import ( - gocontext "context" + "context" "os" "os/signal" @@ -31,7 +31,7 @@ import ( // HandleConsoleResize resizes the console. // From https://github.com/containerd/containerd/blob/v1.7.0-rc.2/cmd/ctr/commands/tasks/tasks_unix.go#L43-L68 -func HandleConsoleResize(ctx gocontext.Context, task resizer, con console.Console) error { +func HandleConsoleResize(ctx context.Context, task resizer, con console.Console) error { // do an initial resize of the console size, err := con.Size() if err != nil { diff --git a/pkg/consoleutil/consoleutil_windows.go b/pkg/consoleutil/consoleutil_windows.go index c8ebf8ee726..4ae19c3cc57 100644 --- a/pkg/consoleutil/consoleutil_windows.go +++ b/pkg/consoleutil/consoleutil_windows.go @@ -17,7 +17,7 @@ package consoleutil import ( - gocontext "context" + "context" "time" "github.com/containerd/console" @@ -26,7 +26,7 @@ import ( // HandleConsoleResize resizes the console. // From https://github.com/containerd/containerd/blob/v1.7.0-rc.2/cmd/ctr/commands/tasks/tasks_windows.go#L34-L61 -func HandleConsoleResize(ctx gocontext.Context, task resizer, con console.Console) error { +func HandleConsoleResize(ctx context.Context, task resizer, con console.Console) error { // do an initial resize of the console size, err := con.Size() if err != nil { diff --git a/pkg/signalutil/signals.go b/pkg/signalutil/signals.go index b35eacbb121..608cd575860 100644 --- a/pkg/signalutil/signals.go +++ b/pkg/signalutil/signals.go @@ -17,7 +17,7 @@ package signalutil import ( - gocontext "context" + "context" "os" "os/signal" "syscall" @@ -29,12 +29,12 @@ import ( // killer is from https://github.com/containerd/containerd/blob/v1.7.0-rc.2/cmd/ctr/commands/signals.go#L30-L32 type killer interface { - Kill(gocontext.Context, syscall.Signal, ...containerd.KillOpts) error + Kill(context.Context, syscall.Signal, ...containerd.KillOpts) error } // ForwardAllSignals forwards signals. // From https://github.com/containerd/containerd/blob/v1.7.0-rc.2/cmd/ctr/commands/signals.go#L34-L55 -func ForwardAllSignals(ctx gocontext.Context, task killer) chan os.Signal { +func ForwardAllSignals(ctx context.Context, task killer) chan os.Signal { sigc := make(chan os.Signal, 128) signal.Notify(sigc) go func() { From e536ed59e1fe137d83841519390da84fe91e45ff Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 3 Dec 2024 16:54:43 -0800 Subject: [PATCH 0967/1066] Increase timeouts on CI Signed-off-by: apostasie --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 46405ac2f93..feba1ca4c26 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,7 @@ env: jobs: # This job builds the dependency target of the test docker image for all supported architectures and cache it in GHA build-dependencies: - timeout-minutes: 10 + timeout-minutes: 15 name: dependencies | ${{ matrix.containerd }} | ${{ matrix.arch }} runs-on: "${{ matrix.runner }}" strategy: @@ -59,7 +59,7 @@ jobs: # Supposed to work: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#example-returning-a-json-data-type # Apparently does not # timeout-minutes: ${{ fromJSON(env.SHORT_TIMEOUT) }} - timeout-minutes: 5 + timeout-minutes: 10 name: unit | ${{ matrix.goos }} runs-on: "${{ matrix.os }}" defaults: @@ -160,7 +160,7 @@ jobs: test-integration-ipv6: needs: build-dependencies - timeout-minutes: 10 + timeout-minutes: 15 name: ipv6 | ${{ matrix.containerd }} | ${{ matrix.ubuntu }} runs-on: "ubuntu-${{ matrix.ubuntu }}" strategy: From 9bbf24dbf36455e1be5225a29547b63cb50e4e65 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 18 Oct 2024 10:22:14 -0700 Subject: [PATCH 0968/1066] Remove dependency on misplaced helper CreateBuildContext for next-gen tests Signed-off-by: apostasie --- cmd/nerdctl/image/image_list_test.go | 11 ++++++++--- cmd/nerdctl/image/image_prune_test.go | 19 ++++++++++++++----- cmd/nerdctl/image/image_pull_linux_test.go | 10 ++++++++-- cmd/nerdctl/ipfs/ipfs_registry_linux_test.go | 7 +++++-- 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index 6aae9354a90..6b8c0aac738 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -19,6 +19,8 @@ package image import ( "errors" "fmt" + "os" + "path/filepath" "runtime" "slices" "strings" @@ -26,7 +28,6 @@ import ( "gotest.tools/v3/assert" - testhelpers "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/tabutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" @@ -144,7 +145,9 @@ LABEL foo=bar LABEL version=0.1 RUN echo "actually creating a layer so that docker sets the createdAt time" `, testutil.CommonImage) - buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) data.Set("buildCtx", buildCtx) }, Cleanup: func(data test.Data, helpers test.Helpers) { @@ -290,7 +293,9 @@ func TestImagesFilterDangling(t *testing.T) { dockerfile := fmt.Sprintf(`FROM %s CMD ["echo", "nerdctl-build-notag-string"] `, testutil.CommonImage) - buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) data.Set("buildCtx", buildCtx) }, Cleanup: func(data test.Data, helpers test.Helpers) { diff --git a/cmd/nerdctl/image/image_prune_test.go b/cmd/nerdctl/image/image_prune_test.go index c4dae8b975e..8a04d24a417 100644 --- a/cmd/nerdctl/image/image_prune_test.go +++ b/cmd/nerdctl/image/image_prune_test.go @@ -18,13 +18,14 @@ package image import ( "fmt" + "os" + "path/filepath" "strings" "testing" "time" "gotest.tools/v3/assert" - testhelpers "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" "github.com/containerd/nerdctl/v2/pkg/testutil/test" @@ -61,7 +62,9 @@ func TestImagePrune(t *testing.T) { CMD ["echo", "nerdctl-test-image-prune"] `, testutil.CommonImage) - buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) helpers.Ensure("build", buildCtx) // After we rebuild with tag, docker will no longer show the version from above // Swapping order does not change anything. @@ -107,7 +110,9 @@ func TestImagePrune(t *testing.T) { CMD ["echo", "nerdctl-test-image-prune"] `, testutil.CommonImage) - buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) helpers.Ensure("build", buildCtx) helpers.Ensure("build", "-t", identifier, buildCtx) imgList := helpers.Capture("images") @@ -149,7 +154,9 @@ func TestImagePrune(t *testing.T) { CMD ["echo", "nerdctl-test-image-prune-filter-label"] LABEL foo=bar LABEL version=0.1`, testutil.CommonImage) - buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) helpers.Ensure("build", "-t", data.Identifier(), buildCtx) imgList := helpers.Capture("images") assert.Assert(t, strings.Contains(imgList, data.Identifier()), "Missing "+data.Identifier()) @@ -187,7 +194,9 @@ LABEL version=0.1`, testutil.CommonImage) dockerfile := fmt.Sprintf(`FROM %s RUN echo "Anything, so that we create actual content for docker to set the current time for CreatedAt" CMD ["echo", "nerdctl-test-image-prune-until"]`, testutil.CommonImage) - buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) helpers.Ensure("build", "-t", data.Identifier(), buildCtx) imgList := helpers.Capture("images") assert.Assert(t, strings.Contains(imgList, data.Identifier()), "Missing "+data.Identifier()) diff --git a/cmd/nerdctl/image/image_pull_linux_test.go b/cmd/nerdctl/image/image_pull_linux_test.go index 611c834b2ed..28aa8b0cb9f 100644 --- a/cmd/nerdctl/image/image_pull_linux_test.go +++ b/cmd/nerdctl/image/image_pull_linux_test.go @@ -18,6 +18,8 @@ package image import ( "fmt" + "os" + "path/filepath" "strconv" "strings" "testing" @@ -56,7 +58,9 @@ func TestImagePullWithCosign(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) helpers.Ensure("build", "-t", testImageRef+":one", buildCtx) helpers.Ensure("build", "-t", testImageRef+":two", buildCtx) helpers.Ensure("push", "--sign=cosign", "--cosign-key="+keyPair.PrivateKey, testImageRef+":one") @@ -120,7 +124,9 @@ func TestImagePullPlainHttpWithDefaultPort(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, testutil.CommonImage) - buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) helpers.Ensure("build", "-t", testImageRef, buildCtx) helpers.Ensure("--insecure-registry", "push", testImageRef) helpers.Ensure("rmi", "-f", testImageRef) diff --git a/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go index a4be0b01aa5..3b4f61183e8 100644 --- a/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_registry_linux_test.go @@ -18,6 +18,8 @@ package ipfs import ( "fmt" + "os" + "path/filepath" "regexp" "strings" "testing" @@ -25,7 +27,6 @@ import ( "gotest.tools/v3/assert" - testhelpers "github.com/containerd/nerdctl/v2/cmd/nerdctl/helpers" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" "github.com/containerd/nerdctl/v2/pkg/testutil/test" @@ -132,7 +133,9 @@ func TestIPFSNerdctlRegistry(t *testing.T) { CMD ["echo", "nerdctl-build-test-string"] `, data.Get(ipfsImageURLKey)) - buildCtx := testhelpers.CreateBuildContext(t, dockerfile) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) helpers.Ensure("build", "-t", data.Identifier("built-image"), buildCtx) }, From 3d944cb5eb84870c6ed4885f6107b91b3a1198ee Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 3 Dec 2024 14:18:40 -0800 Subject: [PATCH 0969/1066] validatePathComponent tests Signed-off-by: apostasie --- pkg/store/filestore_test.go | 59 ++++++++++++++++++++++++++++++++++ pkg/store/filestore_windows.go | 2 +- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/pkg/store/filestore_test.go b/pkg/store/filestore_test.go index 2496b96cbb1..6840443b35f 100644 --- a/pkg/store/filestore_test.go +++ b/pkg/store/filestore_test.go @@ -17,6 +17,8 @@ package store import ( + "fmt" + "runtime" "testing" "time" @@ -218,3 +220,60 @@ func TestFileStoreConcurrent(t *testing.T) { }) assert.NilError(t, lErr, "locking should not error") } + +func TestFileStoreFilesystemRestrictions(t *testing.T) { + invalid := []string{ + "/", + "/start", + "mid/dle", + "end/", + ".", + "..", + "", + fmt.Sprintf("A%0255s", "A"), + } + + valid := []string{ + fmt.Sprintf("A%0254s", "A"), + "test", + "test-hyphen", + ".start.dot", + "mid.dot", + "∞", + } + + if runtime.GOOS == "windows" { + invalid = append(invalid, []string{ + "\\start", + "mid\\dle", + "end\\", + "\\", + "\\.", + "com².whatever", + "lpT2", + "Prn.", + "nUl", + "AUX", + "AA", + "A:A", + "A\"A", + "A|A", + "A?A", + "A*A", + "end.dot.", + "end.space ", + }...) + } + + for _, v := range invalid { + err := validatePathComponent(v) + assert.ErrorIs(t, err, ErrInvalidArgument, v) + } + + for _, v := range valid { + err := validatePathComponent(v) + assert.NilError(t, err, v) + } + +} diff --git a/pkg/store/filestore_windows.go b/pkg/store/filestore_windows.go index 75b18eb42e4..7c599803cb5 100644 --- a/pkg/store/filestore_windows.go +++ b/pkg/store/filestore_windows.go @@ -38,7 +38,7 @@ func validatePlatformSpecific(pathComponent string) error { } if pathComponent[len(pathComponent)-1:] == "." || pathComponent[len(pathComponent)-1:] == " " { - return fmt.Errorf("identifier %q cannot end with a space of dot", pathComponent) + return fmt.Errorf("identifier %q cannot end with a space or dot", pathComponent) } return nil From b8f4d9c2f7578389287f6910d4eacc382da0c1e3 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 2 Dec 2024 20:47:28 -0800 Subject: [PATCH 0970/1066] Cleanup namespace validation Signed-off-by: apostasie --- cmd/nerdctl/main.go | 11 ++++++ pkg/containerutil/containerutil.go | 4 -- pkg/nsutil/nsutil.go | 47 ----------------------- pkg/nsutil/nsutil_test.go | 60 ------------------------------ pkg/store/filestore.go | 8 ++-- pkg/store/filestore_test.go | 4 +- 6 files changed, 17 insertions(+), 117 deletions(-) delete mode 100644 pkg/nsutil/nsutil.go delete mode 100644 pkg/nsutil/nsutil_test.go diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 50797e5b804..1a831a460a1 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -49,6 +49,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/errutil" "github.com/containerd/nerdctl/v2/pkg/logging" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/store" "github.com/containerd/nerdctl/v2/pkg/version" ) @@ -239,6 +240,16 @@ Config file ($NERDCTL_TOML): %s return fmt.Errorf("invalid cgroup-manager %q (supported values: \"systemd\", \"cgroupfs\", \"none\")", cgroupManager) } } + + // Since we store containers' stateful information on the filesystem per namespace, we need namespaces to be + // valid, safe path segments. This is enforced by store.ValidatePathComponent. + // Note that the container runtime will further enforce additional restrictions on namespace names + // (containerd treats namespaces as valid identifiers - eg: alphanumericals + dash, starting with a letter) + // See https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#path-segment-names for + // considerations about path segments identifiers. + if err = store.ValidatePathComponent(globalOptions.Namespace); err != nil { + return err + } if appNeedsRootlessParentMain(cmd, args) { // reexec /proc/self/exe with `nsenter` into RootlessKit namespaces return rootlessutil.ParentMain(globalOptions.HostGatewayIP) diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 8f215ecf679..4f21fa70546 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -46,7 +46,6 @@ import ( "github.com/containerd/nerdctl/v2/pkg/ipcutil" "github.com/containerd/nerdctl/v2/pkg/labels" "github.com/containerd/nerdctl/v2/pkg/labels/k8slabels" - "github.com/containerd/nerdctl/v2/pkg/nsutil" "github.com/containerd/nerdctl/v2/pkg/portutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/signalutil" @@ -529,9 +528,6 @@ func Unpause(ctx context.Context, client *containerd.Client, id string) error { // ContainerStateDirPath returns the path to the Nerdctl-managed state directory for the container with the given ID. func ContainerStateDirPath(ns, dataStore, id string) (string, error) { - if err := nsutil.ValidateNamespaceName(ns); err != nil { - return "", fmt.Errorf("invalid namespace name %q for determining state dir of container %q: %s", ns, id, err) - } return filepath.Join(dataStore, "containers", ns, id), nil } diff --git a/pkg/nsutil/nsutil.go b/pkg/nsutil/nsutil.go deleted file mode 100644 index 9cde4583c87..00000000000 --- a/pkg/nsutil/nsutil.go +++ /dev/null @@ -1,47 +0,0 @@ -/* - 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 nsutil provides utilities for namespaces. -package nsutil - -import ( - "fmt" - "strings" -) - -// Ensures the provided namespace name is valid. -// Namespace names cannot be path-like strings or pre-defined aliases such as "..". -// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#path-segment-names -func ValidateNamespaceName(nsName string) error { - if nsName == "" { - return fmt.Errorf("namespace name cannot be empty") - } - - // Slash and '$' for POSIX and backslash and '%' for Windows. - pathSeparators := "/\\%$" - if strings.ContainsAny(nsName, pathSeparators) { - return fmt.Errorf("namespace name cannot contain any special characters (%q): %s", pathSeparators, nsName) - } - - specialAliases := []string{".", "..", "~"} - for _, alias := range specialAliases { - if nsName == alias { - return fmt.Errorf("namespace name cannot be special path alias %q", alias) - } - } - - return nil -} diff --git a/pkg/nsutil/nsutil_test.go b/pkg/nsutil/nsutil_test.go deleted file mode 100644 index 31d2fdffdc1..00000000000 --- a/pkg/nsutil/nsutil_test.go +++ /dev/null @@ -1,60 +0,0 @@ -/* - 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 nsutil_test - -import ( - "testing" - - "gotest.tools/v3/assert" - - "github.com/containerd/nerdctl/v2/pkg/nsutil" -) - -func TestValidateNamespaceName(t *testing.T) { - testCases := []struct { - inputs []string - errSubstr string - }{ - { - []string{"test", "test-hyphen", ".start.dot", "mid.dot", "end.dot."}, - "", - }, - { - []string{".", "..", "~"}, - "namespace name cannot be special path alias", - }, - { - []string{"$$", "a$VARiable", "a%VAR%iable", "\\.", "\\%", "\\$"}, - "namespace name cannot contain any special characters", - }, - { - []string{"/start", "mid/dle", "end/", "\\start", "mid\\dle", "end\\"}, - "namespace name cannot contain any special characters", - }, - } - - for _, tc := range testCases { - for _, input := range tc.inputs { - err := nsutil.ValidateNamespaceName(input) - if tc.errSubstr == "" { - assert.NilError(t, err) - } else { - assert.ErrorContains(t, err, tc.errSubstr) - } - } - } -} diff --git a/pkg/store/filestore.go b/pkg/store/filestore.go index ec0d98b3585..312155230fa 100644 --- a/pkg/store/filestore.go +++ b/pkg/store/filestore.go @@ -204,7 +204,7 @@ func (vs *fileStore) List(key ...string) ([]string, error) { // Unlike Get, Set and Delete, List can have zero length key for _, k := range key { - if err := validatePathComponent(k); err != nil { + if err := ValidatePathComponent(k); err != nil { return nil, err } } @@ -333,8 +333,8 @@ func (vs *fileStore) GroupSize(key ...string) (int64, error) { return size, nil } -// validatePathComponent will enforce os specific filename restrictions on a single path component -func validatePathComponent(pathComponent string) error { +// ValidatePathComponent will enforce os specific filename restrictions on a single path component +func ValidatePathComponent(pathComponent string) error { // https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits if len(pathComponent) > 255 { return errors.Join(ErrInvalidArgument, errors.New("identifiers must be stricly shorter than 256 characters")) @@ -358,7 +358,7 @@ func validateAllPathComponents(pathComponent ...string) error { } for _, key := range pathComponent { - if err := validatePathComponent(key); err != nil { + if err := ValidatePathComponent(key); err != nil { return err } } diff --git a/pkg/store/filestore_test.go b/pkg/store/filestore_test.go index 6840443b35f..58f4eebeef0 100644 --- a/pkg/store/filestore_test.go +++ b/pkg/store/filestore_test.go @@ -267,12 +267,12 @@ func TestFileStoreFilesystemRestrictions(t *testing.T) { } for _, v := range invalid { - err := validatePathComponent(v) + err := ValidatePathComponent(v) assert.ErrorIs(t, err, ErrInvalidArgument, v) } for _, v := range valid { - err := validatePathComponent(v) + err := ValidatePathComponent(v) assert.NilError(t, err, v) } From d4130581d7ff68da349244fc36d2abaf19ca5abb Mon Sep 17 00:00:00 2001 From: Arjun Raja Yogidas Date: Fri, 29 Nov 2024 21:27:10 +0000 Subject: [PATCH 0971/1066] fix: Fix --env-file flag behavior in nerdctl compose Signed-off-by: Arjun Raja Yogidas --- docs/command-reference.md | 1 + pkg/composer/up_service.go | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/docs/command-reference.md b/docs/command-reference.md index 4f7a314678a..628a1e50b9e 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1391,6 +1391,7 @@ Flags: - :whale: `-p, --project-name`: Specify an alternate project name - :nerd_face: `--ipfs-address`: Multiaddr of IPFS API (default uses `$IPFS_PATH` env variable if defined or local directory `~/.ipfs`) - :whale: `--profile: Specify a profile to enable +- :whale: `--env-file` : Specify an alternate environment file ### :whale: nerdctl compose up diff --git a/pkg/composer/up_service.go b/pkg/composer/up_service.go index 7bd6ea48c92..85010f25ce9 100644 --- a/pkg/composer/up_service.go +++ b/pkg/composer/up_service.go @@ -175,6 +175,10 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse defer os.RemoveAll(tempDir) cidFilename := filepath.Join(tempDir, "cid") + if c.EnvFile != "" { + container.RunArgs = append([]string{"--env-file=" + c.EnvFile}, container.RunArgs...) + } + //add metadata labels to container https://github.com/compose-spec/compose-spec/blob/master/spec.md#labels container.RunArgs = append([]string{ "--cidfile=" + cidFilename, From b4ba0cbdd34dcffa52d0d7404ea50e1f9a53e3f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:11:09 +0000 Subject: [PATCH 0972/1066] build(deps): bump the golang-x group with 6 updates Bumps the golang-x group with 6 updates: | Package | From | To | | --- | --- | --- | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.29.0` | `0.30.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.31.0` | `0.32.0` | | [golang.org/x/sync](https://github.com/golang/sync) | `0.9.0` | `0.10.0` | | [golang.org/x/sys](https://github.com/golang/sys) | `0.27.0` | `0.28.0` | | [golang.org/x/term](https://github.com/golang/term) | `0.26.0` | `0.27.0` | | [golang.org/x/text](https://github.com/golang/text) | `0.20.0` | `0.21.0` | Updates `golang.org/x/crypto` from 0.29.0 to 0.30.0 - [Commits](https://github.com/golang/crypto/compare/v0.29.0...v0.30.0) Updates `golang.org/x/net` from 0.31.0 to 0.32.0 - [Commits](https://github.com/golang/net/compare/v0.31.0...v0.32.0) Updates `golang.org/x/sync` from 0.9.0 to 0.10.0 - [Commits](https://github.com/golang/sync/compare/v0.9.0...v0.10.0) Updates `golang.org/x/sys` from 0.27.0 to 0.28.0 - [Commits](https://github.com/golang/sys/compare/v0.27.0...v0.28.0) Updates `golang.org/x/term` from 0.26.0 to 0.27.0 - [Commits](https://github.com/golang/term/compare/v0.26.0...v0.27.0) Updates `golang.org/x/text` from 0.20.0 to 0.21.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.20.0...v0.21.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 12 ++++++------ go.sum | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index 2341440f07e..6a58a198ad2 100644 --- a/go.mod +++ b/go.mod @@ -65,12 +65,12 @@ require ( github.com/vishvananda/netns v0.0.5 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.5.0 - golang.org/x/crypto v0.29.0 - golang.org/x/net v0.31.0 - golang.org/x/sync v0.9.0 - golang.org/x/sys v0.27.0 - golang.org/x/term v0.26.0 - golang.org/x/text v0.20.0 + golang.org/x/crypto v0.30.0 + golang.org/x/net v0.32.0 + golang.org/x/sync v0.10.0 + golang.org/x/sys v0.28.0 + golang.org/x/term v0.27.0 + golang.org/x/text v0.21.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) diff --git a/go.sum b/go.sum index 2202ce91b04..ba77054b81f 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= @@ -360,16 +360,16 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -385,14 +385,14 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From c2d8b4c6da1793cd47bc3b0bef38daa92d3a6d13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2024 22:45:02 +0000 Subject: [PATCH 0973/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.3.4 to 0.3.5. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Changelog](https://github.com/cyphar/filepath-securejoin/blob/main/CHANGELOG.md) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.3.4...v0.3.5) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6a58a198ad2..9fa6ebe2245 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.8.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.3.4 + github.com/cyphar/filepath-securejoin v0.3.5 github.com/distribution/reference v0.6.0 github.com/docker/cli v27.3.1+incompatible github.com/docker/docker v27.3.1+incompatible diff --git a/go.sum b/go.sum index ba77054b81f..bba108d49e9 100644 --- a/go.sum +++ b/go.sum @@ -80,8 +80,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8= -github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM= +github.com/cyphar/filepath-securejoin v0.3.5 h1:L81NHjquoQmcPgXcttUS9qTSR/+bXry6pbSINQGpjj4= +github.com/cyphar/filepath-securejoin v0.3.5/go.mod h1:edhVd3c6OXKjUmSrVa/tGJRS9joFTxlslFCAyaxigkE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= From e3e6c3dec6d9c3a3485b8794312ff63db0efc85b Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Sat, 7 Dec 2024 22:24:04 +0100 Subject: [PATCH 0974/1066] [doc] rootlesskit port driver configuration Signed-off-by: fahed dorgaa --- docs/rootless.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rootless.md b/docs/rootless.md index 2c0ee7cab5b..62709e50a27 100644 --- a/docs/rootless.md +++ b/docs/rootless.md @@ -141,7 +141,7 @@ Rootless containerd recognizes the following environment variables to configure * `CONTAINERD_ROOTLESS_ROOTLESSKIT_STATE_DIR=DIR`: the rootlesskit state dir. Defaults to `$XDG_RUNTIME_DIR/containerd-rootless`. * `CONTAINERD_ROOTLESS_ROOTLESSKIT_NET=(slirp4netns|vpnkit|lxc-user-nic)`: the rootlesskit network driver. Defaults to "slirp4netns" if slirp4netns (>= v0.4.0) is installed. Otherwise defaults to "vpnkit". * `CONTAINERD_ROOTLESS_ROOTLESSKIT_MTU=NUM`: the MTU value for the rootlesskit network driver. Defaults to 65520 for slirp4netns, 1500 for other drivers. -* `CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=(builtin|slirp4netns)`: the rootlesskit port driver. Defaults to "builtin". +* `CONTAINERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=(builtin|slirp4netns)`: the rootlesskit port driver. Defaults to "builtin" (this driver does not propagate the container's source IP address and always uses 127.0.0.1. Please check [Port Drivers](https://github.com/rootless-containers/rootlesskit/blob/master/docs/port.md#port-drivers) for more details). * `CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SANDBOX=(auto|true|false)`: whether to protect slirp4netns with a dedicated mount namespace. Defaults to "auto". * `CONTAINERD_ROOTLESS_ROOTLESSKIT_SLIRP4NETNS_SECCOMP=(auto|true|false)`: whether to protect slirp4netns with seccomp. Defaults to "auto". * `CONTAINERD_ROOTLESS_ROOTLESSKIT_DETACH_NETNS=(auto|true|false)`: whether to launch rootlesskit with the "detach-netns" mode. From e8bca25104eb224e513ce0a4dc0794a724e56a51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 22:36:14 +0000 Subject: [PATCH 0975/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.3.1+incompatible to 27.4.0+incompatible - [Commits](https://github.com/docker/cli/compare/v27.3.1...v27.4.0) Updates `github.com/docker/docker` from 27.3.1+incompatible to 27.4.0+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.3.1...v27.4.0) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 9fa6ebe2245..f1cccfbac18 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.5 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.3.1+incompatible - github.com/docker/docker v27.3.1+incompatible + github.com/docker/cli v27.4.0+incompatible + github.com/docker/docker v27.4.0+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index bba108d49e9..65effea7602 100644 --- a/go.sum +++ b/go.sum @@ -90,10 +90,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ= -github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= -github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.4.0+incompatible h1:/nJzWkcI1MDMN+U+px/YXnQWJqnu4J+QKGTfD6ptiTc= +github.com/docker/cli v27.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.4.0+incompatible h1:I9z7sQ5qyzO0BfAb9IMOawRkAGxhYsidKiTMcm0DU+A= +github.com/docker/docker v27.4.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From f934774245f3685fcc5401d41f20d1250f23fb9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 22:39:19 +0000 Subject: [PATCH 0976/1066] build(deps): bump tonistiigi/xx from 1.5.0 to 1.6.0 Bumps tonistiigi/xx from 1.5.0 to 1.6.0. --- updated-dependencies: - dependency-name: tonistiigi/xx dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index aecfb5b1cac..51338425ccf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -50,7 +50,7 @@ ARG NYDUS_VERSION=v2.3.0 ARG SOCI_SNAPSHOTTER_VERSION=0.8.0 ARG KUBO_VERSION=v0.31.0 -FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0 AS xx +FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.6.0 AS xx FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm AS build-base-debian From 6dac2cf127966ab30474b6565a9265d9593deb06 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 10 Dec 2024 17:31:06 +0900 Subject: [PATCH 0977/1066] update BuildKit (0.18.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.0 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.1 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.1 diff --git a/Dockerfile b/Dockerfile index 51338425ccf..8d18fbc2ecb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.2.2 ARG CNI_PLUGINS_VERSION=v1.6.1 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.18.0 +ARG BUILDKIT_VERSION=v0.18.1 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.16.2 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.0 deleted file mode 100644 index 937cb0348b0..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.0 +++ /dev/null @@ -1,2 +0,0 @@ -7b4d8d825a23114a20b6ccf87aa674b0792be5cb1b573b8273fe7f3fa01f40d1 buildkit-v0.18.0.linux-amd64.tar.gz -361862432dd3b4961882e5031364ab98be7618be7b80574465207f9e1e18efc3 buildkit-v0.18.0.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.1 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.1 new file mode 100644 index 00000000000..34d303dafcd --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.1 @@ -0,0 +1,2 @@ +02b986569330f09dc837486f80d9818812aba1ac8bd892b337adeb56eafe3794 buildkit-v0.18.1.linux-amd64.tar.gz +484a725519bd15a3b3d1f84c2dfc37749af6f06bc6c40d83395312e4d1fb18f1 buildkit-v0.18.1.linux-arm64.tar.gz From bcc9fa746a91ce7ee28a36edc5e87566432ddf1b Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 10 Dec 2024 17:43:14 +0900 Subject: [PATCH 0978/1066] update containerd-fuse-overlayfs (2.1.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.0.0 | 6 ------ Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.0 | 6 ++++++ 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.0.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.0 diff --git a/Dockerfile b/Dockerfile index 8d18fbc2ecb..2ca1c4cf9ab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ ARG SLIRP4NETNS_VERSION=v1.3.1 ARG BYPASS4NETNS_VERSION=v0.4.1 # Extra deps: FUSE-OverlayFS ARG FUSE_OVERLAYFS_VERSION=v1.14 -ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v2.0.0 +ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v2.1.0 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug diff --git a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.0.0 b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.0.0 deleted file mode 100644 index b6912d6b20b..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.0.0 +++ /dev/null @@ -1,6 +0,0 @@ -dc20341234be8fa44e1308c9f38e30d7239c12350a046c83f4d1c804b682fe6c containerd-fuse-overlayfs-2.0.0-linux-amd64.tar.gz -acfaa3a2caa6316b2c409bcb1c2600b6faee504188c412df8261024435dbfefc containerd-fuse-overlayfs-2.0.0-linux-arm-v7.tar.gz -8b8032a4e0d16aedf7797818944147cebefad32e6657e0b7089501bcfc732e57 containerd-fuse-overlayfs-2.0.0-linux-arm64.tar.gz -b4603139b2a532ac9ed8df3197669d3df5dfd9bebda2aa5f507ad6e6dbb1ed77 containerd-fuse-overlayfs-2.0.0-linux-ppc64le.tar.gz -9e169b401e063cfb0b7b192f911dcb2532ec86a64844d8c052e076fe692017c3 containerd-fuse-overlayfs-2.0.0-linux-riscv64.tar.gz -e8dfe8e2aff5b32f2f5698909baadd0cb36aa85704ff8c568f6bcae186e0ccc5 containerd-fuse-overlayfs-2.0.0-linux-s390x.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.0 b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.0 new file mode 100644 index 00000000000..60d31bb1113 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.0 @@ -0,0 +1,6 @@ +d8629e40e64f16b3b00ee17e393d48e495468d4397437a0a2982e86aaf3e7680 containerd-fuse-overlayfs-2.1.0-linux-amd64.tar.gz +9edbab1e93b2f87efb9532d84e20c67f58af3743adc3626b95fa74272bb0ebc7 containerd-fuse-overlayfs-2.1.0-linux-arm-v7.tar.gz +79d7e94350a4871320e3bca76a6a02860e70872d1ae4a4b8ecc2c655f0e62cb0 containerd-fuse-overlayfs-2.1.0-linux-arm64.tar.gz +fdec57ed7b3effbcb7aa34c6c65604ee94691c791fb6dec29a5055815dfc8816 containerd-fuse-overlayfs-2.1.0-linux-ppc64le.tar.gz +fe7ad1b516ccc87ab53f97de76008aff49d1523ea64c67f2f9da070d5fb3e0c1 containerd-fuse-overlayfs-2.1.0-linux-riscv64.tar.gz +c19b2d544ac4cd304df58baa7e68a1a1a3f93a80299c830f742379f21dd354c8 containerd-fuse-overlayfs-2.1.0-linux-s390x.tar.gz From 9e5a01342eb68bfa896b99515c026e2b5bd94c20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 22:51:38 +0000 Subject: [PATCH 0979/1066] build(deps): bump tonistiigi/xx from 1.6.0 to 1.6.1 Bumps tonistiigi/xx from 1.6.0 to 1.6.1. --- updated-dependencies: - dependency-name: tonistiigi/xx dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2ca1c4cf9ab..5715dcab591 100644 --- a/Dockerfile +++ b/Dockerfile @@ -50,7 +50,7 @@ ARG NYDUS_VERSION=v2.3.0 ARG SOCI_SNAPSHOTTER_VERSION=0.8.0 ARG KUBO_VERSION=v0.31.0 -FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.6.0 AS xx +FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.6.1 AS xx FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm AS build-base-debian From bd66dc0b0e2d111b4d06579ff3fb335e841fbeef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 22:58:00 +0000 Subject: [PATCH 0980/1066] build(deps): bump github.com/containerd/go-cni from 1.1.10 to 1.1.11 Bumps [github.com/containerd/go-cni](https://github.com/containerd/go-cni) from 1.1.10 to 1.1.11. - [Release notes](https://github.com/containerd/go-cni/releases) - [Commits](https://github.com/containerd/go-cni/compare/v1.1.10...v1.1.11) --- updated-dependencies: - dependency-name: github.com/containerd/go-cni dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f1cccfbac18..1402249f5ff 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/containerd/continuity v0.4.5 github.com/containerd/errdefs v1.0.0 github.com/containerd/fifo v1.1.0 - github.com/containerd/go-cni v1.1.10 + github.com/containerd/go-cni v1.1.11 github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.15.0-rc.0 diff --git a/go.sum b/go.sum index 65effea7602..e324dffb347 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,8 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= 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.10 h1:c2U73nld7spSWfiJwSh/8W9DK+/qQwYM2rngIhCyhyg= -github.com/containerd/go-cni v1.1.10/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= +github.com/containerd/go-cni v1.1.11 h1:fWt1K15AmSLsEfa57N+qYw4NeGPiQKYq1pjNGJwV9mc= +github.com/containerd/go-cni v1.1.11/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA= github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U= github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 h1:7OMu5otk5Z2GeQs24JBPOmYbTc50+q6jo02qWNJc0p8= From e3b231e69d9df34e616bc83cab7ce1b3d22bdbfe Mon Sep 17 00:00:00 2001 From: Manu Gupta Date: Tue, 10 Dec 2024 22:22:40 -0800 Subject: [PATCH 0981/1066] 3432: Support --pull flag in nerdctl compose up Signed-off-by: Manu Gupta --- cmd/nerdctl/compose/compose_up.go | 6 +++ cmd/nerdctl/compose/compose_up_linux_test.go | 54 ++++++++++++++++++++ docs/command-reference.md | 1 + pkg/composer/create.go | 2 +- pkg/composer/run.go | 2 +- pkg/composer/up.go | 1 + pkg/composer/up_service.go | 7 ++- 7 files changed, 69 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/compose/compose_up.go b/cmd/nerdctl/compose/compose_up.go index f4670947c3f..0cf2d6bccd2 100644 --- a/cmd/nerdctl/compose/compose_up.go +++ b/cmd/nerdctl/compose/compose_up.go @@ -50,6 +50,7 @@ func newComposeUpCommand() *cobra.Command { composeUpCommand.Flags().Bool("force-recreate", false, "Recreate containers even if their configuration and image haven't changed.") composeUpCommand.Flags().Bool("no-recreate", false, "Don't recreate containers if they exist, conflict with --force-recreate.") composeUpCommand.Flags().StringArray("scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.") + composeUpCommand.Flags().String("pull", "", "Pull image before running (\"always\"|\"missing\"|\"never\")") return composeUpCommand } @@ -96,6 +97,10 @@ func composeUpAction(cmd *cobra.Command, services []string) error { if err != nil { return err } + pull, err := cmd.Flags().GetString("pull") + if err != nil { + return err + } removeOrphans, err := cmd.Flags().GetBool("remove-orphans") if err != nil { return err @@ -154,6 +159,7 @@ func composeUpAction(cmd *cobra.Command, services []string) error { QuietPull: quietPull, RemoveOrphans: removeOrphans, Scale: scale, + Pull: pull, ForceRecreate: forceRecreate, NoRecreate: noRecreate, } diff --git a/cmd/nerdctl/compose/compose_up_linux_test.go b/cmd/nerdctl/compose/compose_up_linux_test.go index 6dbd6b7cf34..6da3162b4b9 100644 --- a/cmd/nerdctl/compose/compose_up_linux_test.go +++ b/cmd/nerdctl/compose/compose_up_linux_test.go @@ -579,3 +579,57 @@ services: } c.Assert(expected) } + +func TestComposeUpPull(t *testing.T) { + base := testutil.NewBase(t) + + var dockerComposeYAML = fmt.Sprintf(` +services: + test: + image: %s + command: sh -euxc "echo hi" +`, testutil.CommonImage) + + comp := testutil.NewComposeDir(t, dockerComposeYAML) + defer comp.CleanUp() + + // Cases where pull is required + for _, pull := range []string{"missing", "always"} { + t.Run(fmt.Sprintf("pull=%s", pull), func(t *testing.T) { + base.Cmd("rmi", "-f", testutil.CommonImage).Run() + base.Cmd("images").AssertOutNotContains(testutil.CommonImage) + t.Cleanup(func() { + base.ComposeCmd("-f", comp.YAMLFullPath(), "down").AssertOK() + }) + base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "--pull", pull).AssertOutContains("hi") + }) + } + + t.Run("pull=never, no pull", func(t *testing.T) { + base.Cmd("rmi", "-f", testutil.CommonImage).Run() + base.Cmd("images").AssertOutNotContains(testutil.CommonImage) + t.Cleanup(func() { + base.ComposeCmd("-f", comp.YAMLFullPath(), "down").AssertOK() + }) + base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "--pull", "never").AssertExitCode(1) + }) +} + +func TestComposeUpServicePullPolicy(t *testing.T) { + base := testutil.NewBase(t) + + var dockerComposeYAML = fmt.Sprintf(` +services: + test: + image: %s + command: sh -euxc "echo hi" + pull_policy: "never" +`, testutil.CommonImage) + + comp := testutil.NewComposeDir(t, dockerComposeYAML) + defer comp.CleanUp() + + base.Cmd("rmi", "-f", testutil.CommonImage).Run() + base.Cmd("images").AssertOutNotContains(testutil.CommonImage) + base.ComposeCmd("-f", comp.YAMLFullPath(), "up").AssertExitCode(1) +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 628a1e50b9e..28c4da551de 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1413,6 +1413,7 @@ Flags: - :whale: `--remove-orphans`: Remove containers for services not defined in the Compose file - :whale: `--force-recreate`: force Compose to stop and recreate all containers - :whale: `--no-recreate`: force Compose to reuse existing containers +- :whale: `--pull`: Pull image before running ("always"|"missing"|"never") Unimplemented `docker-compose up` (V1) flags: `--no-deps`, `--always-recreate-deps`, `--no-start`, `--abort-on-container-exit`, `--attach-dependencies`, `--timeout`, `--renew-anon-volumes`, `--exit-code-from` diff --git a/pkg/composer/create.go b/pkg/composer/create.go index 25d6872590b..a2ae9180160 100644 --- a/pkg/composer/create.go +++ b/pkg/composer/create.go @@ -119,7 +119,7 @@ func (c *Composer) Create(ctx context.Context, opt CreateOptions, services []str return err } for _, ps := range parsedServices { - if err := c.ensureServiceImage(ctx, ps, !opt.NoBuild, opt.Build, BuildOptions{}, false); err != nil { + if err := c.ensureServiceImage(ctx, ps, !opt.NoBuild, opt.Build, BuildOptions{}, false, ""); err != nil { return err } } diff --git a/pkg/composer/run.go b/pkg/composer/run.go index b2e98ea2b1d..0b3c4c72342 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -215,7 +215,7 @@ func (c *Composer) runServices(ctx context.Context, parsedServices []*servicepar // TODO: parallelize loop for ensuring images (make sure not to mess up tty) for _, ps := range parsedServices { - if err := c.ensureServiceImage(ctx, ps, !ro.NoBuild, ro.ForceBuild, BuildOptions{}, ro.QuietPull); err != nil { + if err := c.ensureServiceImage(ctx, ps, !ro.NoBuild, ro.ForceBuild, BuildOptions{}, ro.QuietPull, ""); err != nil { return err } } diff --git a/pkg/composer/up.go b/pkg/composer/up.go index b508b8ddc3d..98106c81ae4 100644 --- a/pkg/composer/up.go +++ b/pkg/composer/up.go @@ -42,6 +42,7 @@ type UpOptions struct { ForceRecreate bool NoRecreate bool Scale map[string]int // map of service name to replicas + Pull string } func (opts UpOptions) recreateStrategy() string { diff --git a/pkg/composer/up_service.go b/pkg/composer/up_service.go index 85010f25ce9..f0da7c9b72a 100644 --- a/pkg/composer/up_service.go +++ b/pkg/composer/up_service.go @@ -41,7 +41,7 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars // TODO: parallelize loop for ensuring images (make sure not to mess up tty) for _, ps := range parsedServices { - if err := c.ensureServiceImage(ctx, ps, !uo.NoBuild, uo.ForceBuild, BuildOptions{}, uo.QuietPull); err != nil { + if err := c.ensureServiceImage(ctx, ps, !uo.NoBuild, uo.ForceBuild, BuildOptions{}, uo.QuietPull, uo.Pull); err != nil { return err } } @@ -101,7 +101,7 @@ func (c *Composer) upServices(ctx context.Context, parsedServices []*servicepars return nil } -func (c *Composer) ensureServiceImage(ctx context.Context, ps *serviceparser.Service, allowBuild, forceBuild bool, bo BuildOptions, quiet bool) error { +func (c *Composer) ensureServiceImage(ctx context.Context, ps *serviceparser.Service, allowBuild, forceBuild bool, bo BuildOptions, quiet bool, pullModeArg string) error { if ps.Build != nil && allowBuild { if ps.Build.Force || forceBuild { return c.buildServiceImage(ctx, ps.Image, ps.Build, ps.Unparsed.Platform, bo) @@ -117,6 +117,9 @@ func (c *Composer) ensureServiceImage(ctx context.Context, ps *serviceparser.Ser } log.G(ctx).Infof("Ensuring image %s", ps.Image) + if pullModeArg != "" { + return c.EnsureImage(ctx, ps.Image, pullModeArg, ps.Unparsed.Platform, ps, quiet) + } return c.EnsureImage(ctx, ps.Image, ps.PullMode, ps.Unparsed.Platform, ps, quiet) } From 1185e8e2a443ba380da7dd22c3d7f7bc5bf69811 Mon Sep 17 00:00:00 2001 From: Hiroshi Miura Date: Sun, 8 Dec 2024 16:03:59 +0900 Subject: [PATCH 0982/1066] docs: add faq tips for buildkit cache folder Help users to find a nerdctl command when they find a dangling cache in buildkit cache folder, as a SEO. Signed-off-by: Hiroshi Miura --- docs/faq.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/faq.md b/docs/faq.md index 7280c503dba..c2313f9ce16 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -32,6 +32,7 @@ - [Containers do not automatically start after rebooting the host](#containers-do-not-automatically-start-after-rebooting-the-host) - [Error `failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: unable to apply cgroup configuration: unable to start unit ... {Name:Slice Value:"user.slice"} {Name:Delegate Value:true} ... Permission denied: unknown`](#error-failed-to-create-shim-task-oci-runtime-create-failed-runc-create-failed-unable-to-start-container-process-unable-to-apply-cgroup-configuration-unable-to-start-unit--nameslice-valueuserslice-namedelegate-valuetrue--permission-denied-unknown) - [How to uninstall ? / Can't remove `~/.local/share/containerd`](#how-to-uninstall---cant-remove-localsharecontainerd) + - [How to clean a dangling cache of buildkit?](#how-to-clean-a-dangling-cache-of-buildkit) @@ -355,3 +356,15 @@ Run the following commands: containerd-rootless-setuptool.sh uninstall rootlesskit rm -rf ~/.local/share/containerd ~/.local/share/nerdctl ~/.config/containerd ``` + +### How to clean a dangling cache of buildkit? + +`buildkit` cache directory is located at `$HOME/.local/share/buildkit/` +in rootless mode, which has same folder structure `/var/lib/buildkit/` in +root mode. + +You can clear the cache objects by running the following command: +``` +nerdctl builder prune +``` +The command produce a progress message of id and size of removed objects. From 5dfc39e9d4e771d12f804026fd57c455248c681e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 22:30:50 +0000 Subject: [PATCH 0983/1066] build(deps): bump golang.org/x/crypto in the golang-x group Bumps the golang-x group with 1 update: [golang.org/x/crypto](https://github.com/golang/crypto). Updates `golang.org/x/crypto` from 0.30.0 to 0.31.0 - [Commits](https://github.com/golang/crypto/compare/v0.30.0...v0.31.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1402249f5ff..9c05ae5fb13 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,7 @@ require ( github.com/vishvananda/netns v0.0.5 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.5.0 - golang.org/x/crypto v0.30.0 + golang.org/x/crypto v0.31.0 golang.org/x/net v0.32.0 golang.org/x/sync v0.10.0 golang.org/x/sys v0.28.0 diff --git a/go.sum b/go.sum index e324dffb347..5660339ab7b 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= -golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= From 8aa71696c3ba32c80c99d993711c305d44440287 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 22:30:57 +0000 Subject: [PATCH 0984/1066] build(deps): bump github.com/containerd/nydus-snapshotter Bumps [github.com/containerd/nydus-snapshotter](https://github.com/containerd/nydus-snapshotter) from 0.15.0-rc.0 to 0.15.0. - [Release notes](https://github.com/containerd/nydus-snapshotter/releases) - [Commits](https://github.com/containerd/nydus-snapshotter/compare/v0.15.0-rc.0...v0.15.0) --- updated-dependencies: - dependency-name: github.com/containerd/nydus-snapshotter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1402249f5ff..5f47b16abe6 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/containerd/go-cni v1.1.11 github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 github.com/containerd/log v0.1.0 - github.com/containerd/nydus-snapshotter v0.15.0-rc.0 + github.com/containerd/nydus-snapshotter v0.15.0 github.com/containerd/platforms v1.0.0-rc.0 github.com/containerd/stargz-snapshotter v0.16.2 github.com/containerd/stargz-snapshotter/estargz v0.16.2 diff --git a/go.sum b/go.sum index e324dffb347..11c807d6514 100644 --- a/go.sum +++ b/go.sum @@ -51,8 +51,8 @@ github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 h1:7OMu5otk5Z2GeQs24JBPOmYbTc50+q6 github.com/containerd/imgcrypt/v2 v2.0.0-rc.1/go.mod h1:3/Ab3iliBt/aBVNYOwecT1YagCqAiHidOmVsrjtHF1A= 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.15.0-rc.0 h1:98s2N35oDdoLqW4DR8q69Hr8Ag9baU7MWuO/Pm19dTE= -github.com/containerd/nydus-snapshotter v0.15.0-rc.0/go.mod h1:biq0ijpeZe0I5yZFSJyHzFSjjRZQ7P7y/OuHyd7hYOw= +github.com/containerd/nydus-snapshotter v0.15.0 h1:RqZRs1GPeM6T3wmuxJV9u+2Rg4YETVMwTmiDeX+iWC8= +github.com/containerd/nydus-snapshotter v0.15.0/go.mod h1:biq0ijpeZe0I5yZFSJyHzFSjjRZQ7P7y/OuHyd7hYOw= github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA= github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= From db82f095ea97bc2453700c593895723d40a6e4aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 22:31:06 +0000 Subject: [PATCH 0985/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.4.5 to 2.4.6. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.4.5...v2.4.6) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1402249f5ff..2645a0ef45c 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.1 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.9 - github.com/compose-spec/compose-go/v2 v2.4.5 + github.com/compose-spec/compose-go/v2 v2.4.6 github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.4 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index e324dffb347..be395f2cbe8 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.4.5 h1:p4ih4Jb6VgGPLPxh3fSFVKAjFHtZd+7HVLCSFzcFx9Y= -github.com/compose-spec/compose-go/v2 v2.4.5/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.4.6 h1:QiqXQ2L/f0OCbAl41bPpeiGAWVRIQ+GEDrYxO+dRPhQ= +github.com/compose-spec/compose-go/v2 v2.4.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.4 h1:2fs7l3P0Qxb1nKWuJNFiwhp2CqiKzho71DQkDrHJIo4= From e30a362c8e99d9687d7e3d681f7b8a3f43d9dc8c Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 3 Dec 2024 23:29:52 -0800 Subject: [PATCH 0986/1066] Rewrite cp Signed-off-by: apostasie --- cmd/nerdctl/container/container_cp_linux.go | 8 +- pkg/cmd/container/cp_linux.go | 19 +- pkg/containerutil/cp_linux.go | 379 +++++++++-------- pkg/containerutil/cp_resolve_linux.go | 444 ++++++++++++++++++++ 4 files changed, 658 insertions(+), 192 deletions(-) create mode 100644 pkg/containerutil/cp_resolve_linux.go diff --git a/cmd/nerdctl/container/container_cp_linux.go b/cmd/nerdctl/container/container_cp_linux.go index 21ab42cc0c7..e9af6a7282d 100644 --- a/cmd/nerdctl/container/container_cp_linux.go +++ b/cmd/nerdctl/container/container_cp_linux.go @@ -115,16 +115,16 @@ func processCpOptions(cmd *cobra.Command, args []string) (types.ContainerCpOptio } container2host := srcSpec.Container != nil - var container string + var containerReq string if container2host { - container = *srcSpec.Container + containerReq = *srcSpec.Container } else { - container = *destSpec.Container + containerReq = *destSpec.Container } return types.ContainerCpOptions{ GOptions: globalOptions, Container2Host: container2host, - ContainerReq: container, + ContainerReq: containerReq, DestPath: destSpec.Path, SrcPath: srcSpec.Path, FollowSymLink: flagL, diff --git a/pkg/cmd/container/cp_linux.go b/pkg/cmd/container/cp_linux.go index 5d883a47565..0763a376793 100644 --- a/pkg/cmd/container/cp_linux.go +++ b/pkg/cmd/container/cp_linux.go @@ -39,17 +39,22 @@ func Cp(ctx context.Context, client *containerd.Client, options types.ContainerC ctx, client, found.Container, - options.Container2Host, - options.DestPath, - options.SrcPath, - options.GOptions.Snapshotter, - options.FollowSymLink) + options) }, } count, err := walker.Walk(ctx, options.ContainerReq) - if count < 1 { - err = fmt.Errorf("could not find container: %s, with error: %w", options.ContainerReq, err) + if count == -1 { + if err == nil { + panic("nil error and count == -1 from ContainerWalker.Walk should never happen") + } + err = fmt.Errorf("unable to copy: %w", err) + } else if count == 0 { + if err != nil { + err = fmt.Errorf("unable to retrieve containers with error: %w", err) + } else { + err = fmt.Errorf("no container found for: %s", options.ContainerReq) + } } return err diff --git a/pkg/containerutil/cp_linux.go b/pkg/containerutil/cp_linux.go index 2036b677630..77425aa57be 100644 --- a/pkg/containerutil/cp_linux.go +++ b/pkg/containerutil/cp_linux.go @@ -17,163 +17,200 @@ package containerutil import ( + "bytes" "context" "errors" "fmt" - "io/fs" "os" "os/exec" - "path" "path/filepath" "strconv" "strings" - securejoin "github.com/cyphar/filepath-securejoin" - containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/tarutil" ) -// CopyFiles implements `nerdctl cp`. // See https://docs.docker.com/engine/reference/commandline/cp/ for the specification. -func CopyFiles(ctx context.Context, client *containerd.Client, container containerd.Container, container2host bool, dst, src string, snapshotter string, followSymlink bool) error { + +var ( + // Generic and system errors + ErrFilesystem = errors.New("filesystem error") // lstat hard errors, etc + ErrContainerVanished = errors.New("the container you are trying to copy to/from has been deleted") + ErrRootlessCannotCp = errors.New("cannot use cp with stopped containers in rootless mode") // rootless cp with a stopped container + ErrFailedMountingSnapshot = errors.New("failed mounting snapshot") // failure to mount a stopped container snapshot + + // CP specific errors + ErrTargetIsReadOnly = errors.New("cannot copy into read-only location") // ... + ErrSourceIsNotADir = errors.New("source is not a directory") // cp SOMEFILE/ foo:/ + ErrDestinationIsNotADir = errors.New("destination is not a directory") // * cp ./ foo:/etc/issue/bah + ErrSourceDoesNotExist = errors.New("source does not exist") // cp NONEXISTENT foo:/ + ErrDestinationParentMustExist = errors.New("destination parent does not exist") // nerdctl cp VALID_PATH foo:/NONEXISTENT/NONEXISTENT + ErrDestinationDirMustExist = errors.New("the destination directory must exist to be able to copy a file") // * cp SOMEFILE foo:/NONEXISTENT/ + ErrCannotCopyDirToFile = errors.New("cannot copy a directory to a file") // cp SOMEDIR foo:/etc/issue +) + +// getRoot will tentatively return the root of the container on the host (/proc/pid/root), along with the pid, +// (eg: doable when the container is running) +func getRoot(ctx context.Context, container containerd.Container) (string, int, error) { + task, err := container.Task(ctx, nil) + if err != nil { + return "", 0, err + } + + status, err := task.Status(ctx) + if err != nil { + return "", 0, err + } + + if status.Status != containerd.Running { + return "", 0, nil + } + pid := int(task.Pid()) + + return fmt.Sprintf("/proc/%d/root", pid), pid, nil +} + +// CopyFiles implements `nerdctl cp` +// It currently depends on the following assumptions: +// - linux only +// - tar binary exists on the system +// - nsenter binary exists on the system +// - if rootless, the container is running (aka: /proc/pid/root) +func CopyFiles(ctx context.Context, client *containerd.Client, container containerd.Container, options types.ContainerCpOptions) (err error) { + // We do rely on the tar binary as a shortcut - could also be replaced by archive/tar, though that would mean + // we need to replace nsenter calls with re-exec tarBinary, isGNUTar, err := tarutil.FindTarBinary() if err != nil { return err } + log.G(ctx).Debugf("Detected tar binary %q (GNU=%v)", tarBinary, isGNUTar) - var srcFull, dstFull, root, mountDestination, containerPath string - var cleanup func() - task, err := container.Task(ctx, nil) + + // This can happen if the container being passed has been deleted since in a racy way + conSpec, err := container.Spec(ctx) if err != nil { - // FIXME: Rootless does not support copying into/out of stopped/created containers as we need to nsenter into the user namespace of the - // pid of the running container with --preserve-credentials to preserve uid/gid mapping and copy files into the container. + return errors.Join(ErrContainerVanished, err) + } + + // Try to get a running container root + root, pid, err := getRoot(ctx, container) + // If the task is "not found" (for example, if the container stopped), we will try to mount the snapshot + // Any other type of error from Task() is fatal here. + if err != nil && !errdefs.IsNotFound(err) { + return errors.Join(ErrContainerVanished, err) + } + + log.G(ctx).Debugf("We have root %s and pid %d", root, pid) + + // If we have no root: + // - bail out for rootless + // - mount the snapshot for rootful + if root == "" { + // FIXME: Rootless does not support copying into/out of stopped/created containers as we need to nsenter into + // the user namespace of the pid of the running container with --preserve-credentials to preserve uid/gid + // mapping and copy files into the container. if rootlessutil.IsRootless() { - return errors.New("cannot use cp with stopped containers in rootless mode") - } - // if the task is simply not found, we should try to mount the snapshot. any other type of error from Task() is fatal here. - if !errdefs.IsNotFound(err) { - return err + return ErrRootlessCannotCp } - if container2host { - containerPath = src - } else { - containerPath = dst - } - // Check if containerPath is in a volume - root, mountDestination, err = getContainerMountInfo(ctx, container, containerPath, container2host) + + // See similar situation above. This may happen if we are racing against container deletion + var conInfo containers.Container + conInfo, err = container.Info(ctx) if err != nil { - return err + return errors.Join(ErrContainerVanished, err) } - // if containerPath is in a volume and not read-only in case of host2container copy then handle volume paths, - // else containerPath is not in volume so mount container snapshot for copy - if root != "" { - dst, src = handleVolumePaths(container2host, dst, src, mountDestination) - } else { - root, cleanup, err = mountSnapshotForContainer(ctx, client, container, snapshotter) - if cleanup != nil { - defer cleanup() - } - if err != nil { - return err - } + + var cleanup func() error + root, cleanup, err = mountSnapshotForContainer(ctx, client, conInfo, options.GOptions.Snapshotter) + if cleanup != nil { + defer func() { + err = errors.Join(err, cleanup()) + }() } - } else { - status, err := task.Status(ctx) + if err != nil { - return err - } - if status.Status == containerd.Running { - root = fmt.Sprintf("/proc/%d/root", task.Pid()) - } else { - if rootlessutil.IsRootless() { - return fmt.Errorf("cannot use cp with stopped containers in rootless mode") - } - if container2host { - containerPath = src - } else { - containerPath = dst - } - root, mountDestination, err = getContainerMountInfo(ctx, container, containerPath, container2host) - if err != nil { - return err - } - // if containerPath is in a volume and not read-only in case of host2container copy then handle volume paths, - // else containerPath is not in volume so mount container snapshot for copy - if root != "" { - dst, src = handleVolumePaths(container2host, dst, src, mountDestination) - } else { - root, cleanup, err = mountSnapshotForContainer(ctx, client, container, snapshotter) - if cleanup != nil { - defer cleanup() - } - if err != nil { - return err - } - } + return errors.Join(ErrFailedMountingSnapshot, err) } + + log.G(ctx).Debugf("Got new root %s", root) } - if container2host { - srcFull, err = securejoin.SecureJoin(root, src) - dstFull = dst + + var sourceSpec, destinationSpec *pathSpecifier + var sourceErr, destErr error + if options.Container2Host { + sourceSpec, sourceErr = getPathSpecFromContainer(options.SrcPath, conSpec, root) + destinationSpec, destErr = getPathSpecFromHost(options.DestPath) } else { - srcFull = src - dstFull, err = securejoin.SecureJoin(root, dst) + sourceSpec, sourceErr = getPathSpecFromHost(options.SrcPath) + destinationSpec, destErr = getPathSpecFromContainer(options.DestPath, conSpec, root) } - if err != nil { - return err + + if destErr != nil { + if errors.Is(destErr, errDoesNotExist) { + return ErrDestinationParentMustExist + } else if errors.Is(destErr, errIsNotADir) { + return ErrDestinationIsNotADir + } + + return errors.Join(ErrFilesystem, destErr) } - var ( - srcIsDir bool - dstExists bool - dstExistsAsDir bool - st fs.FileInfo - ) - st, err = os.Stat(srcFull) - if err != nil { - return err + + if sourceErr != nil { + if errors.Is(sourceErr, errDoesNotExist) { + return ErrSourceDoesNotExist + } else if errors.Is(sourceErr, errIsNotADir) { + return ErrSourceIsNotADir + } + + return errors.Join(ErrFilesystem, sourceErr) } - srcIsDir = st.IsDir() - // dst may not exist yet, so err is negligible - if st, err := os.Stat(dstFull); err == nil { - dstExists = true - dstExistsAsDir = st.IsDir() + // Now, resolve cp shenanigans + // First, cannot copy a non-existent resource + if !sourceSpec.exists { + return ErrSourceDoesNotExist } - dstEndsWithSep := strings.HasSuffix(dst, string(os.PathSeparator)) - srcEndsWithSlashDot := strings.HasSuffix(src, string(os.PathSeparator)+".") - if !srcIsDir && dstEndsWithSep && !dstExistsAsDir { - // The error is specified in https://docs.docker.com/engine/reference/commandline/cp/ - // See the `DEST_PATH does not exist and ends with /` case. - return fmt.Errorf("the destination directory must exists: %w", err) + + // Second, cannot copy into a readonly destination + if destinationSpec.readOnly { + return ErrTargetIsReadOnly } - if !srcIsDir && srcEndsWithSlashDot { - return fmt.Errorf("the source is not a directory") + + // Cannot copy a dir into a file + if sourceSpec.isADir && destinationSpec.exists && !destinationSpec.isADir { + return ErrCannotCopyDirToFile } - if srcIsDir && dstExists && !dstExistsAsDir { - return fmt.Errorf("cannot copy a directory to a file") + + // A file cannot be copied inside a non-existent directory with a trailing slash, or slash+dot + if !sourceSpec.isADir && !destinationSpec.exists && (destinationSpec.endsWithSeparator || destinationSpec.endsWithSeparatorDot) { + return ErrDestinationDirMustExist } - if srcIsDir && !dstExists { - if err := os.MkdirAll(dstFull, 0o755); err != nil { - return err + + // XXX FIXME: this seems wrong. What about ownership? We could be doing that inside a container + if !destinationSpec.exists { + if err = os.Mkdir(destinationSpec.resolvedPath, 0o755); err != nil { + return errors.Join(ErrFilesystem, err) } } var tarCDir, tarCArg string - if srcIsDir { - if !dstExists || srcEndsWithSlashDot { + if sourceSpec.isADir { + if !destinationSpec.exists || sourceSpec.endsWithSeparatorDot { // the content of the source directory is copied into this directory - tarCDir = srcFull + tarCDir = sourceSpec.resolvedPath tarCArg = "." } else { // the source directory is copied into this directory - tarCDir = filepath.Dir(srcFull) - tarCArg = filepath.Base(srcFull) + tarCDir = filepath.Dir(sourceSpec.resolvedPath) + tarCArg = filepath.Base(sourceSpec.resolvedPath) } } else { // Prepare a single-file directory to create an archive of the source file @@ -184,16 +221,16 @@ func CopyFiles(ctx context.Context, client *containerd.Client, container contain defer os.RemoveAll(td) tarCDir = td cp := []string{"cp", "-a"} - if followSymlink { + if options.FollowSymLink { cp = append(cp, "-L") } - if dstEndsWithSep || dstExistsAsDir { - tarCArg = filepath.Base(srcFull) + if destinationSpec.endsWithSeparator || (destinationSpec.exists && destinationSpec.isADir) { + tarCArg = filepath.Base(sourceSpec.resolvedPath) } else { // Handle `nerdctl cp /path/to/file some-container:/path/to/file-with-another-name` - tarCArg = filepath.Base(dstFull) + tarCArg = filepath.Base(destinationSpec.resolvedPath) } - cp = append(cp, srcFull, filepath.Join(td, tarCArg)) + cp = append(cp, sourceSpec.resolvedPath, filepath.Join(td, tarCArg)) cpCmd := exec.CommandContext(ctx, cp[0], cp[1:]...) log.G(ctx).Debugf("executing %v", cpCmd.Args) if out, err := cpCmd.CombinedOutput(); err != nil { @@ -201,30 +238,33 @@ func CopyFiles(ctx context.Context, client *containerd.Client, container contain } } tarC := []string{tarBinary} - if followSymlink { + if options.FollowSymLink { tarC = append(tarC, "-h") } tarC = append(tarC, "-c", "-f", "-", tarCArg) - tarXDir := dstFull - if !srcIsDir && !dstEndsWithSep && !dstExistsAsDir { - tarXDir = filepath.Dir(dstFull) + tarXDir := destinationSpec.resolvedPath + if !sourceSpec.isADir && !destinationSpec.endsWithSeparator && !(destinationSpec.exists && destinationSpec.isADir) { + tarXDir = filepath.Dir(destinationSpec.resolvedPath) } tarX := []string{tarBinary, "-x"} - if container2host && isGNUTar { + if options.Container2Host && isGNUTar { tarX = append(tarX, "--no-same-owner") } tarX = append(tarX, "-f", "-") if rootlessutil.IsRootless() { - nsenter := []string{"nsenter", "-t", strconv.Itoa(int(task.Pid())), "-U", "--preserve-credentials", "--"} - if container2host { + nsenter := []string{"nsenter", "-t", strconv.Itoa(pid), "-U", "--preserve-credentials", "--"} + if options.Container2Host { tarC = append(nsenter, tarC...) } else { tarX = append(nsenter, tarX...) } } + // FIXME: moving to archive/tar should allow better error management than this + // WARNING: some of our testing on stderr might not be portable across different versions of tar + // In these cases (readonly target), we will just get the straight tar output instead tarCCmd := exec.CommandContext(ctx, tarC[0], tarC[1:]...) tarCCmd.Dir = tarCDir tarCCmd.Stdin = nil @@ -237,97 +277,74 @@ func CopyFiles(ctx context.Context, client *containerd.Client, container contain return err } tarXCmd.Stdout = os.Stderr - tarXCmd.Stderr = os.Stderr + var tarErr bytes.Buffer + tarXCmd.Stderr = &tarErr log.G(ctx).Debugf("executing %v in %q", tarCCmd.Args, tarCCmd.Dir) if err := tarCCmd.Start(); err != nil { - return fmt.Errorf("failed to execute %v: %w", tarCCmd.Args, err) + return errors.Join(fmt.Errorf("failed to execute %v", tarCCmd.Args), err) } + log.G(ctx).Debugf("executing %v in %q", tarXCmd.Args, tarXCmd.Dir) if err := tarXCmd.Start(); err != nil { - return fmt.Errorf("failed to execute %v: %w", tarXCmd.Args, err) + if strings.Contains(err.Error(), "permission denied") { + return ErrTargetIsReadOnly + } + + // Other errors, just put them back on stderr + _, fpErr := fmt.Fprint(os.Stderr, tarErr.String()) + if fpErr != nil { + return errors.Join(fpErr, err) + } + + return errors.Join(fmt.Errorf("failed to execute %v", tarXCmd.Args), err) } + if err := tarCCmd.Wait(); err != nil { return fmt.Errorf("failed to wait %v: %w", tarCCmd.Args, err) } + if err := tarXCmd.Wait(); err != nil { - return fmt.Errorf("failed to wait %v: %w", tarXCmd.Args, err) + if strings.Contains(tarErr.String(), "Read-only file system") { + return ErrTargetIsReadOnly + } + + // Other errors, just put them back on stderr + _, fpErr := fmt.Fprint(os.Stderr, tarErr.String()) + if fpErr != nil { + return errors.Join(fpErr, err) + } + + return errors.Join(fmt.Errorf("failed to wait %v", tarXCmd.Args), err) } + return nil } -func mountSnapshotForContainer(ctx context.Context, client *containerd.Client, container containerd.Container, snapshotter string) (string, func(), error) { - cinfo, err := container.Info(ctx) - if err != nil { - return "", nil, err - } - snapKey := cinfo.SnapshotKey +func mountSnapshotForContainer(ctx context.Context, client *containerd.Client, conInfo containers.Container, snapshotter string) (string, func() error, error) { + snapKey := conInfo.SnapshotKey resp, err := client.SnapshotService(snapshotter).Mounts(ctx, snapKey) if err != nil { return "", nil, err } + tempDir, err := os.MkdirTemp("", "nerdctl-cp-") if err != nil { return "", nil, err } + err = mount.All(resp, tempDir) if err != nil { - return "", nil, fmt.Errorf("failed to mount snapshot with error %s", err.Error()) + return "", nil, err } - cleanup := func() { + + cleanup := func() error { err = mount.Unmount(tempDir, 0) if err != nil { - log.G(ctx).Warnf("failed to unmount %s with error %s", tempDir, err.Error()) - return - } - os.RemoveAll(tempDir) - } - return tempDir, cleanup, nil -} - -func getContainerMountInfo(ctx context.Context, con containerd.Container, containerPath string, container2host bool) (string, string, error) { - filePath := filepath.Clean(containerPath) - spec, err := con.Spec(ctx) - if err != nil { - return "", "", err - } - // read-only applies only while copying into container from host - if !container2host && spec.Root.Readonly { - return "", "", fmt.Errorf("container rootfs: %s is marked read-only", spec.Root.Path) - } - - for _, mount := range spec.Mounts { - if isSelfOrAscendant(filePath, mount.Destination) { - // read-only applies only while copying into container from host - if !container2host { - for _, option := range mount.Options { - if option == "ro" { - return "", "", fmt.Errorf("mount point %s is marked read-only", filePath) - } - } - } - return mount.Source, mount.Destination, nil + return err } + return os.RemoveAll(tempDir) } - return "", "", nil -} -func isSelfOrAscendant(filePath, potentialAncestor string) bool { - if filePath == "/" || filePath == "" || potentialAncestor == "" { - return false - } - filePath = filepath.Clean(filePath) - potentialAncestor = filepath.Clean(potentialAncestor) - if filePath == potentialAncestor { - return true - } - return isSelfOrAscendant(path.Dir(filePath), potentialAncestor) -} - -// When the path is in volume remove directory that volume is mounted on from the path -func handleVolumePaths(container2host bool, dst string, src string, mountDestination string) (string, string) { - if container2host { - return dst, strings.TrimPrefix(filepath.Clean(src), mountDestination) - } - return strings.TrimPrefix(filepath.Clean(dst), mountDestination), src + return tempDir, cleanup, nil } diff --git a/pkg/containerutil/cp_resolve_linux.go b/pkg/containerutil/cp_resolve_linux.go new file mode 100644 index 00000000000..ab22abaf38e --- /dev/null +++ b/pkg/containerutil/cp_resolve_linux.go @@ -0,0 +1,444 @@ +/* + 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 containerutil + +import ( + "errors" + "io/fs" + "os" + "path/filepath" + "runtime" + "slices" + "strings" + "syscall" + + "github.com/opencontainers/runtime-spec/specs-go" + + "github.com/containerd/containerd/v2/pkg/oci" +) + +// volumeNameLen returns length of the leading volume name on Windows. +// It returns 0 elsewhere. +// FIXME: whenever we will want to port cp to windows, we will need the windows implementation of volumeNameLen +func volumeNameLen(_ string) int { + return 0 +} + +var ( + errDoesNotExist = errors.New("resource does not exist") // when a path parent dir does not exist + errIsNotADir = errors.New("is not a dir") // when a path is a file, ending with path separator + errCannotResolvePathNoCwd = errors.New("unable to resolve path against undefined current working directory") // relative host path, no cwd +) + +// pathSpecifier represents a path to be used by cp +// besides exposing relevant properties (endsWithSeparator, etc), it also provides a fully resolved *host* path to +// access the resource +type pathSpecifier struct { + originalPath string + endsWithSeparator bool + endsWithSeparatorDot bool + exists bool + isADir bool + readOnly bool + resolvedPath string +} + +// getPathSpecFromHost builds a pathSpecifier from a host location +// errors with errDoesNotExist, errIsNotADir, "EvalSymlinks: too many links", or other hard filesystem errors from lstat/stat +func getPathSpecFromHost(originalPath string) (*pathSpecifier, error) { + pathSpec := &pathSpecifier{ + originalPath: originalPath, + endsWithSeparator: strings.HasSuffix(originalPath, string(os.PathSeparator)), + endsWithSeparatorDot: filepath.Base(originalPath) == ".", + } + + path := originalPath + + // Path may still be relative at this point. If it is, figure out getwd. + if !filepath.IsAbs(path) { + cwd, err := os.Getwd() + if err != nil { + return nil, errors.Join(errCannotResolvePathNoCwd, err) + } + path = cwd + string(os.PathSeparator) + path + } + + // Try to fully resolve the path + resolvedPath, err := filepath.EvalSymlinks(path) + if err != nil && !errors.Is(err, os.ErrNotExist) { + if errors.Is(err, syscall.ENOTDIR) { + return nil, errors.Join(errIsNotADir, err) + } + + // Other errors: + // - "EvalSymlinks: too many links" + // - any other error coming from lstat + return nil, err + } + + pathSpec.exists = err == nil + + // Ensure the parent exists if the path itself does not + if !pathSpec.exists { + // Try the parent - obtain it by removing any trailing / or /., then the base + cleaned := strings.TrimRight(strings.TrimSuffix(path, string(os.PathSeparator)+"."), string(os.PathSeparator)) + for len(cleaned) < len(path) { + path = cleaned + cleaned = strings.TrimRight(strings.TrimSuffix(path, string(os.PathSeparator)+"."), string(os.PathSeparator)) + } + + base := filepath.Base(path) + path = strings.TrimSuffix(path, string(os.PathSeparator)+base) + + // Resolve it + resolvedPath, err = filepath.EvalSymlinks(path) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil, errors.Join(errDoesNotExist, err) + } else if errors.Is(err, syscall.ENOTDIR) { + return nil, errors.Join(errIsNotADir, err) + } + + return nil, err + } + + resolvedPath = filepath.Join(resolvedPath, base) + } else { + // If it exists, we can check if it is a dir + var st os.FileInfo + st, err = os.Stat(path) + if err != nil { + return nil, err + } + pathSpec.isADir = st.IsDir() + } + + pathSpec.resolvedPath = resolvedPath + + return pathSpec, nil +} + +// getPathSpecFromHost builds a pathSpecifier from a container location +func getPathSpecFromContainer(originalPath string, conSpec *oci.Spec, containerHostRoot string) (*pathSpecifier, error) { + pathSpec := &pathSpecifier{ + originalPath: originalPath, + endsWithSeparator: strings.HasSuffix(originalPath, string(os.PathSeparator)), + endsWithSeparatorDot: filepath.Base(originalPath) == ".", + } + + path := originalPath + + // Path may still be relative at this point. If it is, join it to the root + // NOTE: this is specifically called out in the docker reference. Paths in the container are assumed + // relative to the root, and not to the current (container) working directory. + // Though this seems like a questionable decision, it is set. + if !filepath.IsAbs(path) { + path = string(os.PathSeparator) + path + } + + // Now, fully resolve the path - resolving all symlinks and cleaning-up the end result, following across mounts + pathResolver := newResolver(conSpec, containerHostRoot) + resolvedContainerPath, err := pathResolver.resolvePath(path) + + // Errors we get from that are from Lstat or Readlink + // Either the object does not exist, or we have a dangling symlink, or otherwise hosed filesystem entries + if err != nil && !errors.Is(err, os.ErrNotExist) { + if errors.Is(err, syscall.ENOTDIR) { + return nil, errors.Join(errIsNotADir, err) + } + + // errors.New("EvalSymlinks: too many links") + // other errors would come from lstat + return nil, err + } + + pathSpec.exists = err == nil + + // If the resource does not exist + if !pathSpec.exists { + // Try the parent + cleaned := strings.TrimRight(strings.TrimSuffix(path, string(os.PathSeparator)+"."), string(os.PathSeparator)) + for len(cleaned) < len(path) { + path = cleaned + cleaned = strings.TrimRight(strings.TrimSuffix(path, string(os.PathSeparator)+"."), string(os.PathSeparator)) + } + + base := filepath.Base(path) + path = strings.TrimSuffix(path, string(os.PathSeparator)+base) + + resolvedContainerPath, err = pathResolver.resolvePath(path) + + // Error? That is the end + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil, errors.Join(errDoesNotExist, err) + } else if errors.Is(err, syscall.ENOTDIR) { + return nil, errors.Join(errIsNotADir, err) + } + + return nil, err + } + + resolvedContainerPath = filepath.Join(resolvedContainerPath, base) + } + + // Now, finally get the location of the fully resolved containerPath (in the root? in a volume?) + containerMount, relativePath := pathResolver.getMount(resolvedContainerPath) + pathSpec.resolvedPath = filepath.Join(containerMount.hostPath, relativePath) + // If the endpoint is readonly, flag it as such + if containerMount.readonly { + pathSpec.readOnly = true + } + + // If it exists, we can check if it is a dir + if pathSpec.exists { + var st os.FileInfo + st, err = os.Stat(pathSpec.resolvedPath) + if err != nil { + return nil, err + } + + pathSpec.isADir = st.IsDir() + } + + return pathSpec, nil +} + +// resolver provides methods to fully resolve any given container given path to a host location +// accounting for rootfs and mounts location +type resolver struct { + root *specs.Root + mounts []specs.Mount + hostRoot string +} + +// locator represents a container mount +type locator struct { + containerPath string + hostPath string + readonly bool +} + +func isParent(child []string, candidate []string) (bool, []string) { + if len(child) < len(candidate) { + return false, child + } + return slices.Equal(child[0:len(candidate)], candidate), child[len(candidate):] +} + +// newResolver returns a resolver struct +func newResolver(conSpec *oci.Spec, hostRoot string) *resolver { + return &resolver{ + root: conSpec.Root, + mounts: conSpec.Mounts, + hostRoot: hostRoot, + } +} + +// pathOnHost will return the *host* location of a container path, accounting for volumes. +// The provided path must be fully resolved, as returned by `resolvePath`. +func (res *resolver) pathOnHost(path string) string { + hostRoot := res.hostRoot + path = filepath.Clean(path) + itemized := strings.Split(path, string(os.PathSeparator)) + + containerRoot := "/" + sub := itemized + + for _, mnt := range res.mounts { + if candidateIsParent, subPath := isParent(itemized, strings.Split(mnt.Destination, string(os.PathSeparator))); candidateIsParent { + if len(mnt.Destination) > len(containerRoot) { + containerRoot = mnt.Destination + hostRoot = mnt.Source + sub = subPath + } + } + } + + return filepath.Join(append([]string{hostRoot}, sub...)...) +} + +// getMount returns the mount locator for a given fully-resolved path, along with the corresponding subpath of the path +// relative to the locator +func (res *resolver) getMount(path string) (*locator, string) { + itemized := strings.Split(path, string(os.PathSeparator)) + + loc := &locator{ + containerPath: "/", + hostPath: res.hostRoot, + readonly: res.root.Readonly, + } + + sub := itemized + + for _, mnt := range res.mounts { + if candidateIsParent, subPath := isParent(itemized, strings.Split(mnt.Destination, string(os.PathSeparator))); candidateIsParent { + if len(mnt.Destination) > len(loc.containerPath) { + loc.readonly = false + for _, option := range mnt.Options { + if option == "ro" { + loc.readonly = true + } + } + loc.containerPath = mnt.Destination + loc.hostPath = mnt.Source + sub = subPath + } + } + } + + return loc, filepath.Join(sub...) +} + +// resolvePath is adapted from https://cs.opensource.google/go/go/+/go1.23.0:src/path/filepath/path.go;l=147 +// The (only) changes are on Lstat and ReadLink, which are fed the actual host path, that is computed by `res.pathOnHost` +func (res *resolver) resolvePath(path string) (string, error) { + volLen := volumeNameLen(path) + pathSeparator := string(os.PathSeparator) + + if volLen < len(path) && os.IsPathSeparator(path[volLen]) { + volLen++ + } + vol := path[:volLen] + dest := vol + linksWalked := 0 + //nolint:ineffassign + for start, end := volLen, volLen; start < len(path); start = end { + for start < len(path) && os.IsPathSeparator(path[start]) { + start++ + } + end = start + for end < len(path) && !os.IsPathSeparator(path[end]) { + end++ + } + + // On Windows, "." can be a symlink. + // We look it up, and use the value if it is absolute. + // If not, we just return ".". + //nolint:staticcheck + isWindowsDot := runtime.GOOS == "windows" && path[volumeNameLen(path):] == "." + + // The next path component is in path[start:end]. + if end == start { + // No more path components. + break + } else if path[start:end] == "." && !isWindowsDot { + // Ignore path component ".". + continue + } else if path[start:end] == ".." { + // Back up to previous component if possible. + // Note that volLen includes any leading slash. + + // Set r to the index of the last slash in dest, + // after the volume. + var r int + for r = len(dest) - 1; r >= volLen; r-- { + if os.IsPathSeparator(dest[r]) { + break + } + } + if r < volLen || dest[r+1:] == ".." { + // Either path has no slashes + // (it's empty or just "C:") + // or it ends in a ".." we had to keep. + // Either way, keep this "..". + if len(dest) > volLen { + dest += pathSeparator + } + dest += ".." + } else { + // Discard everything since the last slash. + dest = dest[:r] + } + continue + } + + // Ordinary path component. Add it to result. + + if len(dest) > volumeNameLen(dest) && !os.IsPathSeparator(dest[len(dest)-1]) { + dest += pathSeparator + } + + dest += path[start:end] + + // Resolve symlink. + hostPath := res.pathOnHost(dest) + fi, err := os.Lstat(hostPath) + if err != nil { + return "", err + } + + if fi.Mode()&fs.ModeSymlink == 0 { + if !fi.Mode().IsDir() && end < len(path) { + return "", syscall.ENOTDIR + } + continue + } + + // Found symlink. + linksWalked++ + if linksWalked > 255 { + return "", errors.New("EvalSymlinks: too many links") + } + + link, err := os.Readlink(hostPath) + if err != nil { + return "", err + } + + if isWindowsDot && !filepath.IsAbs(link) { + // On Windows, if "." is a relative symlink, + // just return ".". + break + } + + path = link + path[end:] + + v := volumeNameLen(link) + if v > 0 { + // Symlink to drive name is an absolute path. + if v < len(link) && os.IsPathSeparator(link[v]) { + v++ + } + vol = link[:v] + dest = vol + end = len(vol) + } else if len(link) > 0 && os.IsPathSeparator(link[0]) { + // Symlink to absolute path. + dest = link[:1] + end = 1 + vol = link[:1] + volLen = 1 + } else { + // Symlink to relative path; replace last + // path component in dest. + var r int + for r = len(dest) - 1; r >= volLen; r-- { + if os.IsPathSeparator(dest[r]) { + break + } + } + if r < volLen { + dest = vol + } else { + dest = dest[:r] + } + end = 0 + } + } + return filepath.Clean(dest), nil +} From 47d6d0ad26d1fe1f7f58d0bc5c2eb31373fef8f0 Mon Sep 17 00:00:00 2001 From: apostasie Date: Tue, 3 Dec 2024 23:30:14 -0800 Subject: [PATCH 0987/1066] cp integration tests Signed-off-by: apostasie --- .../container/container_cp_acid_linux_test.go | 181 +++ .../container/container_cp_linux_test.go | 1277 ++++++++++++----- 2 files changed, 1088 insertions(+), 370 deletions(-) create mode 100644 cmd/nerdctl/container/container_cp_acid_linux_test.go diff --git a/cmd/nerdctl/container/container_cp_acid_linux_test.go b/cmd/nerdctl/container/container_cp_acid_linux_test.go new file mode 100644 index 00000000000..fc30c4ab314 --- /dev/null +++ b/cmd/nerdctl/container/container_cp_acid_linux_test.go @@ -0,0 +1,181 @@ +/* + 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 container + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" + + "github.com/containerd/nerdctl/v2/pkg/containerutil" + "github.com/containerd/nerdctl/v2/pkg/rootlessutil" + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +// This is a separate set of tests for cp specifically meant to test corner or extreme cases that do not fit in the normal testing rig +// because of their complexity + +func TestCopyAcid(t *testing.T) { + t.Parallel() + + t.Run("Travelling along volumes w/o read-only", func(t *testing.T) { + t.Parallel() + testID := testutil.Identifier(t) + tempDir := t.TempDir() + base := testutil.NewBase(t) + base.Dir = tempDir + + sourceFile := filepath.Join(tempDir, "hostfile") + sourceFileContent := []byte(testID) + + roContainer := testID + "-ro" + rwContainer := testID + "-rw" + + setup := func() { + base.Cmd("volume", "create", testID+"-1-ro").AssertOK() + base.Cmd("volume", "create", testID+"-2-rw").AssertOK() + base.Cmd("volume", "create", testID+"-3-rw").AssertOK() + base.Cmd("run", "-d", "-w", containerCwd, "--name", roContainer, "--read-only", + "-v", fmt.Sprintf("%s:%s:ro", testID+"-1-ro", "/vol1/dir1/ro"), + "-v", fmt.Sprintf("%s:%s", testID+"-2-rw", "/vol2/dir2/rw"), + testutil.CommonImage, "sleep", "Inf", + ).AssertOK() + base.Cmd("run", "-d", "-w", containerCwd, "--name", rwContainer, + "-v", fmt.Sprintf("%s:%s:ro", testID+"-1-ro", "/vol1/dir1/ro"), + "-v", fmt.Sprintf("%s:%s", testID+"-3-rw", "/vol3/dir3/rw"), + testutil.CommonImage, "sleep", "Inf", + ).AssertOK() + + base.Cmd("exec", rwContainer, "sh", "-euxc", "cd /vol3/dir3/rw; ln -s ../../../ relativelinktoroot").AssertOK() + base.Cmd("exec", rwContainer, "sh", "-euxc", "cd /vol3/dir3/rw; ln -s / absolutelinktoroot").AssertOK() + base.Cmd("exec", roContainer, "sh", "-euxc", "cd /vol2/dir2/rw; ln -s ../../../ relativelinktoroot").AssertOK() + base.Cmd("exec", roContainer, "sh", "-euxc", "cd /vol2/dir2/rw; ln -s / absolutelinktoroot").AssertOK() + // Create file on the host + err := os.WriteFile(sourceFile, sourceFileContent, filePerm) + assert.NilError(t, err) + } + + tearDown := func() { + base.Cmd("rm", "-f", roContainer).Run() + base.Cmd("rm", "-f", rwContainer).Run() + base.Cmd("volume", "rm", testID+"-1-ro").Run() + base.Cmd("volume", "rm", testID+"-2-rw").Run() + base.Cmd("volume", "rm", testID+"-3-rw").Run() + } + + t.Cleanup(tearDown) + tearDown() + + setup() + + expectedErr := containerutil.ErrTargetIsReadOnly.Error() + if testutil.GetTarget() == testutil.Docker { + expectedErr = "" + } + + t.Run("Cannot copy into a read-only root", func(t *testing.T) { + t.Parallel() + + base.Cmd("cp", sourceFile, roContainer+":/").Assert(icmd.Expected{ + ExitCode: 1, + Err: expectedErr, + }) + }) + + t.Run("Cannot copy into a read-only mount, in a rw container", func(t *testing.T) { + t.Parallel() + + base.Cmd("cp", sourceFile, rwContainer+":/vol1/dir1/ro").Assert(icmd.Expected{ + ExitCode: 1, + Err: expectedErr, + }) + }) + + t.Run("Can copy into a read-write mount in a read-only container", func(t *testing.T) { + t.Parallel() + + base.Cmd("cp", sourceFile, roContainer+":/vol2/dir2/rw").Assert(icmd.Expected{ + ExitCode: 0, + }) + }) + + t.Run("Traverse read-only locations to a read-write location", func(t *testing.T) { + t.Parallel() + + base.Cmd("cp", sourceFile, roContainer+":/vol1/dir1/ro/../../../vol2/dir2/rw").Assert(icmd.Expected{ + ExitCode: 0, + }) + }) + + t.Run("Follow an absolute symlink inside a read-write mount to a read-only root", func(t *testing.T) { + t.Parallel() + + base.Cmd("cp", sourceFile, roContainer+":/vol2/dir2/rw/absolutelinktoroot").Assert(icmd.Expected{ + ExitCode: 1, + Err: expectedErr, + }) + }) + + t.Run("Follow am absolute symlink inside a read-write mount to a read-only mount", func(t *testing.T) { + t.Parallel() + + base.Cmd("cp", sourceFile, rwContainer+":/vol3/dir3/rw/absolutelinktoroot/vol1/dir1/ro").Assert(icmd.Expected{ + ExitCode: 1, + Err: expectedErr, + }) + }) + + t.Run("Follow a relative symlink inside a read-write location to a read-only root", func(t *testing.T) { + t.Parallel() + + base.Cmd("cp", sourceFile, roContainer+":/vol2/dir2/rw/relativelinktoroot").Assert(icmd.Expected{ + ExitCode: 1, + Err: expectedErr, + }) + }) + + t.Run("Follow a relative symlink inside a read-write location to a read-only mount", func(t *testing.T) { + t.Parallel() + + base.Cmd("cp", sourceFile, rwContainer+":/vol3/dir3/rw/relativelinktoroot/vol1/dir1/ro").Assert(icmd.Expected{ + ExitCode: 1, + Err: expectedErr, + }) + }) + + t.Run("Cannot copy into a HOST read-only location", func(t *testing.T) { + t.Parallel() + + // Root will just ignore the 000 permission on the host directory. + if !rootlessutil.IsRootless() { + t.Skip("This test does not work rootful") + } + + err := os.MkdirAll(filepath.Join(tempDir, "rotest"), 0o000) + assert.NilError(t, err) + base.Cmd("cp", roContainer+":/etc/issue", filepath.Join(tempDir, "rotest")).Assert(icmd.Expected{ + ExitCode: 1, + Err: expectedErr, + }) + }) + + }) +} diff --git a/cmd/nerdctl/container/container_cp_linux_test.go b/cmd/nerdctl/container/container_cp_linux_test.go index a94f46561b2..a584b722243 100644 --- a/cmd/nerdctl/container/container_cp_linux_test.go +++ b/cmd/nerdctl/container/container_cp_linux_test.go @@ -25,396 +25,933 @@ import ( "testing" "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" + "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/testutil" ) +// For the test matrix, see https://docs.docker.com/engine/reference/commandline/cp/ +// Obviously, none of this is fully windows ready - obviously `nerdctl cp` itself is not either, so, ok for now. +const ( + // Use this to poke the testing rig for improper path handling + // TODO: fuzz this more seriously + // FIXME: the following will break the test (anything that will evaluate on the shell, obviously): + // - ` + // - $a, ${a}, etc + complexify = "" // = "-~a0-_.(){}[]*#! \"'∞" + + pathDoesNotExistRelative = "does-not-exist" + complexify + pathDoesNotExistAbsolute = string(os.PathSeparator) + "does-not-exist" + complexify + pathIsAFileRelative = "is-a-file" + complexify + pathIsAFileAbsolute = string(os.PathSeparator) + "is-a-file" + complexify + pathIsADirRelative = "is-a-dir" + complexify + pathIsADirAbsolute = string(os.PathSeparator) + "is-a-dir" + complexify + pathIsAVolumeMount = string(os.PathSeparator) + "is-a-volume-mount" + complexify + + srcFileName = "test-file" + complexify + + // Since nerdctl cp must NOT obey container wd, but instead resolve paths against the root, we set this + // explicitly to ensure we do the right thing wrt that. + containerCwd = "/nerdctl/cp/test" + + dirPerm = 0o755 + filePerm = 0o644 +) + +var srcDirName = filepath.Join("three-levels-src-dir", "test-dir", "dir"+complexify) + +type testgroup struct { + description string // parent test description + toContainer bool // copying to, or from container + + // sourceSpec as specified by the user (without the container: part) - can be relative or absolute - + // if sourceSpec points to a file, you must use srcFileName for filename + sourceSpec string + sourceIsAFile bool // whether the provided sourceSpec points to a file or a dir + testCases []testcases // testcases +} + +type testcases struct { + description string // textual description of what the test is doing + destinationSpec string // destination path as specified by the user (without the container: part) - can be relative or absolute + expect icmd.Expected // expectation + + // Optional + catFile string // path that we "cat" - defaults to destinationSpec if not specified + setup func(base *testutil.Base, container string, destPath string) // additional test setup if needed + tearDown func() // additional cleanup if needed + volume func(base *testutil.Base, id string) (string, string, bool) // volume creation function if needed (should return the volume name, mountPoint, readonly flag) +} + func TestCopyToContainer(t *testing.T) { t.Parallel() - base := testutil.NewBase(t) - testContainer := testutil.Identifier(t) - testStoppedContainer := "stopped-container-" + testutil.Identifier(t) - - base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", "1h").AssertOK() - defer base.Cmd("rm", "-f", testContainer).Run() - - base.Cmd("run", "-d", "--name", testStoppedContainer, testutil.CommonImage, "sleep", "1h").AssertOK() - defer base.Cmd("rm", "-f", testStoppedContainer).Run() - // Stop container immediately after starting for testing copying into stopped container - base.Cmd("stop", testStoppedContainer).AssertOK() - srcUID := os.Geteuid() - srcDir := t.TempDir() - srcFile := filepath.Join(srcDir, "test-file") - srcFileContent := []byte("test-file-content") - err := os.WriteFile(srcFile, srcFileContent, 0o644) - assert.NilError(t, err) - - assertCat := func(catPath string, testContainer string, stopped bool) { - if stopped { - base.Cmd("start", testContainer).AssertOK() - defer base.Cmd("stop", testContainer).AssertOK() - } - t.Logf("catPath=%q", catPath) - base.Cmd("exec", testContainer, "cat", catPath).AssertOutExactly(string(srcFileContent)) - base.Cmd("exec", testContainer, "stat", "-c", "%u", catPath).AssertOutExactly(fmt.Sprintf("%d\n", srcUID)) + + testGroups := []*testgroup{ + { + description: "Copying to container, SRC_PATH is a file, absolute", + sourceSpec: filepath.Join(string(os.PathSeparator), srcDirName, srcFileName), + sourceIsAFile: true, + toContainer: true, + testCases: []testcases{ + { + description: "DEST_PATH does not exist, relative", + destinationSpec: pathDoesNotExistRelative, + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH does not exist, absolute", + destinationSpec: pathDoesNotExistAbsolute, + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH does not exist, relative, and ends with " + string(os.PathSeparator), + destinationSpec: pathDoesNotExistRelative + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrDestinationDirMustExist.Error(), + }, + }, + { + description: "DEST_PATH does not exist, absolute, and ends with " + string(os.PathSeparator), + destinationSpec: pathDoesNotExistAbsolute + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrDestinationDirMustExist.Error(), + }, + }, + + { + description: "DEST_PATH is a file, relative", + destinationSpec: pathIsAFileRelative, + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "touch", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a file, absolute", + destinationSpec: pathIsAFileAbsolute, + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "touch", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a file, relative, ends with improper " + string(os.PathSeparator), + destinationSpec: pathIsAFileRelative + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrDestinationIsNotADir.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "touch", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a file, absolute, ends with improper " + string(os.PathSeparator), + destinationSpec: pathIsAFileAbsolute + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + // FIXME: it is unclear why the code path with absolute (this test) versus relative (just above) + // yields a different error. Both should ideally be ErrCannotCopyDirToFile + // This is probably happening somewhere in resolve. + // This is not a deal killer, as both DO error with a reasonable explanation, but a bit + // frustrating + Err: containerutil.ErrDestinationIsNotADir.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "touch", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a directory, relative", + destinationSpec: pathIsADirRelative, + catFile: filepath.Join(pathIsADirRelative, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "mkdir", "-p", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a directory, absolute", + destinationSpec: pathIsADirAbsolute, + catFile: filepath.Join(pathIsADirAbsolute, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "mkdir", "-p", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a directory, relative, ends with " + string(os.PathSeparator), + destinationSpec: pathIsADirRelative + string(os.PathSeparator), + catFile: filepath.Join(pathIsADirRelative, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "mkdir", "-p", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a directory, absolute, ends with " + string(os.PathSeparator), + destinationSpec: pathIsADirAbsolute + string(os.PathSeparator), + catFile: filepath.Join(pathIsADirAbsolute, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "mkdir", "-p", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a volume mount-point", + destinationSpec: pathIsAVolumeMount, + catFile: filepath.Join(pathIsAVolumeMount, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + // FIXME the way we handle volume is not right - too complicated for the test author + volume: func(base *testutil.Base, id string) (string, string, bool) { + base.Cmd("volume", "create", id).Run() + return id, pathIsAVolumeMount, false + }, + }, + { + description: "DEST_PATH is a read-only volume mount-point", + destinationSpec: pathIsAVolumeMount, + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrTargetIsReadOnly.Error(), + }, + volume: func(base *testutil.Base, id string) (string, string, bool) { + base.Cmd("volume", "create", id).Run() + return id, pathIsAVolumeMount, true + }, + }, + }, + }, + { + description: "Copying to container, SRC_PATH is a directory", + sourceSpec: srcDirName, + toContainer: true, + testCases: []testcases{ + { + description: "DEST_PATH does not exist, relative", + destinationSpec: pathDoesNotExistRelative, + catFile: filepath.Join(pathDoesNotExistRelative, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH does not exist, absolute", + destinationSpec: pathDoesNotExistAbsolute, + catFile: filepath.Join(pathDoesNotExistAbsolute, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH does not exist, relative, and ends with " + string(os.PathSeparator), + destinationSpec: pathDoesNotExistRelative + string(os.PathSeparator), + catFile: filepath.Join(pathDoesNotExistRelative, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH does not exist, absolute, and ends with " + string(os.PathSeparator), + destinationSpec: pathDoesNotExistAbsolute + string(os.PathSeparator), + catFile: filepath.Join(pathDoesNotExistAbsolute, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH is a file, relative", + destinationSpec: pathIsAFileRelative, + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrCannotCopyDirToFile.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "touch", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a file, absolute", + destinationSpec: pathIsAFileAbsolute, + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrCannotCopyDirToFile.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "touch", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a file, relative, ends with improper " + string(os.PathSeparator), + destinationSpec: pathIsAFileRelative + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrDestinationIsNotADir.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "touch", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a file, absolute, ends with improper " + string(os.PathSeparator), + destinationSpec: pathIsAFileAbsolute + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + // FIXME: it is unclear why the code path with absolute (this test) versus relative (just above) + // yields a different error. Both should ideally be ErrCannotCopyDirToFile + // This is probably happening somewhere in resolve. + // This is not a deal killer, as both DO error with a reasonable explanation, but a bit + // frustrating + Err: containerutil.ErrDestinationIsNotADir.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "touch", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a directory, relative", + destinationSpec: pathIsADirRelative, + catFile: filepath.Join(pathIsADirRelative, filepath.Base(srcDirName), srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "mkdir", "-p", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a directory, absolute", + destinationSpec: pathIsADirAbsolute, + catFile: filepath.Join(pathIsADirAbsolute, filepath.Base(srcDirName), srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "mkdir", "-p", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a directory, relative, ends with " + string(os.PathSeparator), + destinationSpec: pathIsADirRelative + string(os.PathSeparator), + catFile: filepath.Join(pathIsADirRelative, filepath.Base(srcDirName), srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "mkdir", "-p", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a directory, absolute, ends with " + string(os.PathSeparator), + destinationSpec: pathIsADirAbsolute + string(os.PathSeparator), + catFile: filepath.Join(pathIsADirAbsolute, filepath.Base(srcDirName), srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "mkdir", "-p", destPath).AssertOK() + }, + }, + }, + }, + { + description: "Copying to container, SRC_PATH is a directory ending with /.", + sourceSpec: srcDirName + string(os.PathSeparator) + ".", + toContainer: true, + testCases: []testcases{ + { + description: "DEST_PATH is a directory, relative", + destinationSpec: pathIsADirRelative, + catFile: filepath.Join(pathIsADirRelative, srcFileName), + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "mkdir", "-p", destPath).AssertOK() + }, + }, + { + description: "DEST_PATH is a directory, absolute", + destinationSpec: pathIsADirAbsolute, + catFile: filepath.Join(pathIsADirAbsolute, srcFileName), + setup: func(base *testutil.Base, container string, destPath string) { + base.Cmd("exec", container, "mkdir", "-p", destPath).AssertOK() + }, + }, + }, + }, } - // For the test matrix, see https://docs.docker.com/engine/reference/commandline/cp/ - t.Run("SRC_PATH specifies a file", func(t *testing.T) { - srcPath := srcFile - t.Run("DEST_PATH does not exist", func(t *testing.T) { - destPath := "/dest-no-exist-no-slash" - base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() - catPath := destPath - assertCat(catPath, testContainer, false) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() - assertCat(catPath, testStoppedContainer, true) - }) - t.Run("DEST_PATH does not exist and ends with /", func(t *testing.T) { - destPath := "/dest-no-exist-with-slash/" - base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertFail() - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertFail() - }) - t.Run("DEST_PATH exists and is a file", func(t *testing.T) { - destPath := "/dest-file-exists" - base.Cmd("exec", testContainer, "touch", destPath).AssertOK() - base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() - catPath := destPath - assertCat(catPath, testContainer, false) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() - assertCat(catPath, testStoppedContainer, true) - }) - t.Run("DEST_PATH exists and is a directory", func(t *testing.T) { - destPath := "/dest-dir-exists" - base.Cmd("exec", testContainer, "mkdir", "-p", destPath).AssertOK() - base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() - catPath := filepath.Join(destPath, filepath.Base(srcFile)) - assertCat(catPath, testContainer, false) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("start", testStoppedContainer).AssertOK() - base.Cmd("exec", testStoppedContainer, "mkdir", "-p", destPath).AssertOK() - base.Cmd("stop", testStoppedContainer).AssertOK() - base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() - assertCat(catPath, testStoppedContainer, true) - }) - t.Run("DEST_PATH is in a volume", func(t *testing.T) { - // Create a volume - vol := "somevol" - base.Cmd("volume", "create", vol).AssertOK() - defer base.Cmd("volume", "rm", vol).Run() - con := fmt.Sprintf("%s-with-volume", testContainer) - mountDir := "/some_dir" - base.Cmd("run", "-d", "--name", con, "-v", fmt.Sprintf("%s:%s", vol, mountDir), testutil.CommonImage, "sleep", "1h").AssertOK() - defer base.Cmd("rm", "-f", con).Run() - catPath := filepath.Join(mountDir, filepath.Base(srcFile)) - // Running container test - base.Cmd("cp", srcPath, con+":"+mountDir).AssertOK() - assertCat(catPath, con, false) - - // Skip for rootless - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - // Stopped container test - // Delete previously copied file - base.Cmd("exec", con, "rm", catPath).AssertOK() - base.Cmd("stop", con).AssertOK() - base.Cmd("cp", srcPath, con+":"+mountDir).AssertOK() - assertCat(catPath, con, true) - }) - t.Run("Destination path is a read-only", func(t *testing.T) { - vol := "somevol" - base.Cmd("volume", "create", vol).AssertOK() - defer base.Cmd("volume", "rm", vol).Run() - con := fmt.Sprintf("%s-with-read-only-volume", testContainer) - mountDir := "/some_dir" - // Create container with read-only volume mounted - base.Cmd("run", "-d", "--name", con, "-v", fmt.Sprintf("%s:%s:ro", vol, mountDir), testutil.CommonImage, "sleep", "1h").AssertOK() - defer base.Cmd("rm", "-f", con).Run() - base.Cmd("cp", srcPath, con+":"+mountDir).AssertFail() - - // Skip for rootless - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - - // Stopped container test - // Delete previously copied file - base.Cmd("stop", con).AssertOK() - base.Cmd("cp", srcPath, con+":"+mountDir).AssertFail() - }) - t.Run("Destination path is a read-only and default tmpfs mount point", func(t *testing.T) { - vol := "somevol" - base.Cmd("volume", "create", vol).AssertOK() - defer base.Cmd("volume", "rm", vol).Run() - con := fmt.Sprintf("%s-with-read-only-volume", testContainer) - - // /tmp is from rootfs of alpine - mountDir := "/tmp" - // Create container with read-only mounted volume mounted at /tmp - base.Cmd("run", "-d", "--name", con, "-v", fmt.Sprintf("%s:%s:ro", vol, mountDir), testutil.CommonImage, "sleep", "1h").AssertOK() - defer base.Cmd("rm", "-f", con).Run() - base.Cmd("cp", srcPath, con+":"+mountDir).AssertFail() - - // Skip for rootless - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - - // Stopped container test - // Delete previously copied file - base.Cmd("stop", con).AssertOK() - base.Cmd("cp", srcPath, con+":"+mountDir).AssertFail() - }) - }) - t.Run("SRC_PATH specifies a directory", func(t *testing.T) { - srcPath := srcDir - t.Run("DEST_PATH does not exist", func(t *testing.T) { - destPath := "/dest2-no-exist" - base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() - catPath := filepath.Join(destPath, filepath.Base(srcFile)) - assertCat(catPath, testContainer, false) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() - assertCat(catPath, testStoppedContainer, true) - }) - t.Run("DEST_PATH exists and is a file", func(t *testing.T) { - destPath := "/dest2-file-exists" - base.Cmd("exec", testContainer, "touch", destPath).AssertOK() - base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertFail() - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("start", testStoppedContainer).AssertOK() - base.Cmd("exec", testStoppedContainer, "touch", destPath).AssertOK() - base.Cmd("stop", testStoppedContainer).AssertOK() - base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertFail() - }) - t.Run("DEST_PATH exists and is a directory", func(t *testing.T) { - t.Run("SRC_PATH does not end with `/.`", func(t *testing.T) { - destPath := "/dest2-dir-exists" - base.Cmd("exec", testContainer, "mkdir", "-p", destPath).AssertOK() - base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() - catPath := filepath.Join(destPath, strings.TrimPrefix(srcFile, filepath.Dir(srcDir)+"/")) - assertCat(catPath, testContainer, false) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("start", testStoppedContainer).AssertOK() - base.Cmd("exec", testStoppedContainer, "mkdir", "-p", destPath).AssertOK() - base.Cmd("stop", testStoppedContainer).AssertOK() - base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() - assertCat(catPath, testStoppedContainer, true) - }) - t.Run("SRC_PATH does end with `/.`", func(t *testing.T) { - srcPath += "/." - destPath := "/dest2-dir2-exists" - base.Cmd("exec", testContainer, "mkdir", "-p", destPath).AssertOK() - base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertOK() - catPath := filepath.Join(destPath, filepath.Base(srcFile)) - t.Logf("catPath=%q", catPath) - assertCat(catPath, testContainer, false) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("start", testStoppedContainer).AssertOK() - base.Cmd("exec", testStoppedContainer, "mkdir", "-p", destPath).AssertOK() - base.Cmd("stop", testStoppedContainer).AssertOK() - base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertOK() - assertCat(catPath, testStoppedContainer, true) - }) - }) - }) + for _, tg := range testGroups { + cpTestHelper(t, tg) + } } func TestCopyFromContainer(t *testing.T) { t.Parallel() - base := testutil.NewBase(t) - testContainer := testutil.Identifier(t) - testStoppedContainer := "stopped-container-" + testutil.Identifier(t) - base.Cmd("run", "-d", "--name", testContainer, testutil.CommonImage, "sleep", "1h").AssertOK() - defer base.Cmd("rm", "-f", testContainer).Run() - - base.Cmd("run", "-d", "--name", testStoppedContainer, testutil.CommonImage, "sleep", "1h").AssertOK() - defer base.Cmd("rm", "-f", testStoppedContainer).Run() - - euid := os.Geteuid() - srcUID := 42 - srcDir := "/test-dir" - srcFile := filepath.Join(srcDir, "test-file") - srcFileContent := []byte("test-file-content") - mkSrcScript := fmt.Sprintf("mkdir -p %q && echo -n %q >%q && chown %d %q", srcDir, srcFileContent, srcFile, srcUID, srcFile) - base.Cmd("exec", testContainer, "sh", "-euc", mkSrcScript).AssertOK() - base.Cmd("exec", testStoppedContainer, "sh", "-euc", mkSrcScript).AssertOK() - // Stop container for testing copying out of stopped container - base.Cmd("stop", testStoppedContainer) - - assertCat := func(catPath string) { - t.Logf("catPath=%q", catPath) + + testGroups := []*testgroup{ + { + description: "Copying from container, SRC_PATH specifies a file", + sourceSpec: srcFileName, + sourceIsAFile: true, + testCases: []testcases{ + { + description: "DEST_PATH does not exist, relative", + destinationSpec: pathDoesNotExistRelative, + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH does not exist, absolute", + destinationSpec: pathDoesNotExistAbsolute, + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH does not exist, relative, and ends with a path separator", + destinationSpec: pathDoesNotExistRelative + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrDestinationDirMustExist.Error(), + }, + }, + { + description: "DEST_PATH does not exist, absolute, and ends with a path separator", + destinationSpec: pathDoesNotExistAbsolute + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrDestinationDirMustExist.Error(), + }, + }, + { + description: "DEST_PATH is a file, relative", + destinationSpec: pathIsAFileRelative, + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.WriteFile(destPath, []byte(""), filePerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a file, absolute", + destinationSpec: pathIsAFileAbsolute, + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.WriteFile(destPath, []byte(""), filePerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a file, relative, improperly ends with a separator", + destinationSpec: pathIsAFileRelative + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrDestinationIsNotADir.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.WriteFile(destPath, []byte(""), filePerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a file, absolute, improperly ends with a separator", + destinationSpec: pathIsAFileAbsolute + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrDestinationIsNotADir.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.WriteFile(destPath, []byte(""), filePerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a directory, relative", + destinationSpec: pathIsADirRelative, + catFile: filepath.Join(pathIsADirRelative, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(destPath, dirPerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a directory, absolute", + destinationSpec: pathIsADirAbsolute, + catFile: filepath.Join(pathIsADirAbsolute, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(destPath, dirPerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a directory, relative, ending with a path separator", + destinationSpec: pathIsADirRelative + string(os.PathSeparator), + catFile: filepath.Join(pathIsADirRelative, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(destPath, dirPerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a directory, absolute, ending with a path separator", + destinationSpec: pathIsADirAbsolute + string(os.PathSeparator), + catFile: filepath.Join(pathIsADirAbsolute, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(destPath, dirPerm) + assert.NilError(t, err) + }, + }, + }, + }, + { + description: "Copying from container, SRC_PATH specifies a dir", + sourceSpec: srcDirName, + testCases: []testcases{ + { + description: "DEST_PATH does not exist, relative", + destinationSpec: pathDoesNotExistRelative, + catFile: filepath.Join(pathDoesNotExistRelative, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH does not exist, absolute", + destinationSpec: pathDoesNotExistAbsolute, + catFile: filepath.Join(pathDoesNotExistAbsolute, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH does not exist, relative, ends with path separator", + destinationSpec: pathDoesNotExistRelative + string(os.PathSeparator), + catFile: filepath.Join(pathDoesNotExistRelative, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH does not exist, absolute, ends with path separator", + destinationSpec: pathDoesNotExistAbsolute + string(os.PathSeparator), + catFile: filepath.Join(pathDoesNotExistAbsolute, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + }, + { + description: "DEST_PATH is a file, relative", + destinationSpec: pathIsAFileRelative, + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrCannotCopyDirToFile.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(filepath.Dir(destPath), dirPerm) + assert.NilError(t, err) + err = os.WriteFile(destPath, []byte(""), filePerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a file, absolute", + destinationSpec: pathIsAFileAbsolute, + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrCannotCopyDirToFile.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(filepath.Dir(destPath), dirPerm) + assert.NilError(t, err) + err = os.WriteFile(destPath, []byte(""), filePerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a file, relative, improperly ends with path separator", + destinationSpec: pathIsAFileRelative + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrDestinationIsNotADir.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(filepath.Dir(destPath), dirPerm) + assert.NilError(t, err) + err = os.WriteFile(destPath, []byte(""), filePerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a file, absolute, improperly ends with path separator", + destinationSpec: pathIsAFileAbsolute + string(os.PathSeparator), + expect: icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrDestinationIsNotADir.Error(), + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(filepath.Dir(destPath), dirPerm) + assert.NilError(t, err) + err = os.WriteFile(destPath, []byte(""), filePerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a directory, relative", + destinationSpec: pathIsADirRelative, + catFile: filepath.Join(pathIsADirRelative, filepath.Base(srcDirName), srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(destPath, dirPerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a directory, absolute", + destinationSpec: pathIsADirAbsolute, + catFile: filepath.Join(pathIsADirAbsolute, filepath.Base(srcDirName), srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(destPath, dirPerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a directory, relative, ends with path separator", + destinationSpec: pathIsADirRelative + string(os.PathSeparator), + catFile: filepath.Join(pathIsADirRelative, filepath.Base(srcDirName), srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(destPath, dirPerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a directory, absolute, ends with path separator", + destinationSpec: pathIsADirAbsolute + string(os.PathSeparator), + catFile: filepath.Join(pathIsADirAbsolute, filepath.Base(srcDirName), srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(destPath, dirPerm) + assert.NilError(t, err) + }, + }, + }, + }, + + { + description: "SRC_PATH is a dir, with a trailing slash/dot", + sourceSpec: srcDirName + string(os.PathSeparator) + ".", + testCases: []testcases{ + { + description: "DEST_PATH is a directory, relative", + destinationSpec: pathIsADirRelative, + catFile: filepath.Join(pathIsADirRelative, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(destPath, dirPerm) + assert.NilError(t, err) + }, + }, + { + description: "DEST_PATH is a directory, absolute", + destinationSpec: pathIsADirAbsolute, + catFile: filepath.Join(pathIsADirAbsolute, srcFileName), + expect: icmd.Expected{ + ExitCode: 0, + }, + setup: func(base *testutil.Base, container string, destPath string) { + err := os.MkdirAll(destPath, dirPerm) + assert.NilError(t, err) + }, + }, + }, + }, + } + + for _, tg := range testGroups { + cpTestHelper(t, tg) + } +} + +func assertCatHelper(base *testutil.Base, catPath string, fileContent []byte, container string, expectedUID int, containerIsStopped bool) { + base.T.Logf("catPath=%q", catPath) + if container != "" && containerIsStopped { + base.Cmd("start", container).AssertOK() + defer base.Cmd("stop", container).AssertOK() + } + + if container == "" { got, err := os.ReadFile(catPath) - assert.NilError(t, err) - assert.DeepEqual(t, srcFileContent, got) + assert.NilError(base.T, err, "Failed reading from file") + assert.DeepEqual(base.T, fileContent, got) st, err := os.Stat(catPath) - assert.NilError(t, err) + assert.NilError(base.T, err) stSys := st.Sys().(*syscall.Stat_t) - // stSys.Uid matches euid, not srcUID - assert.DeepEqual(t, uint32(euid), stSys.Uid) + expected := uint32(expectedUID) + actual := stSys.Uid + assert.DeepEqual(base.T, expected, actual) + } else { + base.Cmd("exec", container, "sh", "-c", "--", fmt.Sprintf("ls -lA /; echo %q; cat %q", catPath, catPath)).AssertOutContains(string(fileContent)) + base.Cmd("exec", container, "stat", "-c", "%u", catPath).AssertOutExactly(fmt.Sprintf("%d\n", expectedUID)) } +} - td := t.TempDir() - // For the test matrix, see https://docs.docker.com/engine/reference/commandline/cp/ - t.Run("SRC_PATH specifies a file", func(t *testing.T) { - srcPath := srcFile - t.Run("DEST_PATH does not exist", func(t *testing.T) { - destPath := filepath.Join(td, "dest-no-exist-no-slash") - base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() - catPath := destPath - assertCat(catPath) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() - assertCat(catPath) - }) - t.Run("DEST_PATH does not exist and ends with /", func(t *testing.T) { - destPath := td + "/dest-no-exist-with-slash/" // Avoid filepath.Join, to forcibly append "/" - base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertFail() - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertFail() - }) - t.Run("DEST_PATH exists and is a file", func(t *testing.T) { - destPath := filepath.Join(td, "dest-file-exists") - err := os.WriteFile(destPath, []byte(""), 0o644) - assert.NilError(t, err) - base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() - catPath := destPath - assertCat(catPath) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() - assertCat(catPath) - }) - t.Run("DEST_PATH exists and is a directory", func(t *testing.T) { - destPath := filepath.Join(td, "dest-dir-exists") - err := os.Mkdir(destPath, 0o755) - assert.NilError(t, err) - base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() - catPath := filepath.Join(destPath, filepath.Base(srcFile)) - assertCat(catPath) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() - assertCat(catPath) - }) - t.Run("SRC_PATH is in a volume", func(t *testing.T) { - // Setup - // Create a volume - vol := "somevol" - base.Cmd("volume", "create", vol).AssertOK() - defer base.Cmd("volume", "rm", "-f", vol).Run() - - // Create container for test - con := fmt.Sprintf("%s-with-volume", testContainer) - - mountDir := "/some_dir" - base.Cmd("run", "-d", "--name", con, "-v", fmt.Sprintf("%s:%s", vol, mountDir), testutil.CommonImage, "sleep", "1h").AssertOK() - defer base.Cmd("rm", "-f", con).Run() - - // Create a file to mounted volume - mountedVolFile := filepath.Join(mountDir, "test-file") - mkSrcScript = fmt.Sprintf("echo -n %q >%q && chown %d %q", srcFileContent, mountedVolFile, srcUID, mountedVolFile) - base.Cmd("exec", con, "sh", "-euc", mkSrcScript).AssertOK() - - // Create destination directory on host for copy - destPath := filepath.Join(td, "dest-dir") - err := os.Mkdir(destPath, 0o700) - assert.NilError(t, err) - - catPath := filepath.Join(destPath, filepath.Base(mountedVolFile)) - - // Running container test - base.Cmd("cp", con+":"+mountedVolFile, destPath).AssertOK() - assertCat(catPath) - - // Skip for rootless - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - // Stopped container test - base.Cmd("stop", con).AssertOK() - base.Cmd("cp", con+":"+mountedVolFile, destPath).AssertOK() - assertCat(catPath) - }) - }) - t.Run("SRC_PATH specifies a directory", func(t *testing.T) { - srcPath := srcDir - t.Run("DEST_PATH does not exist", func(t *testing.T) { - destPath := filepath.Join(td, "dest2-no-exist") - base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() - catPath := filepath.Join(destPath, filepath.Base(srcFile)) - assertCat(catPath) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() - assertCat(catPath) - }) - t.Run("DEST_PATH exists and is a file", func(t *testing.T) { - destPath := filepath.Join(td, "dest2-file-exists") - err := os.WriteFile(destPath, []byte(""), 0o644) - assert.NilError(t, err) - base.Cmd("cp", srcPath, testContainer+":"+destPath).AssertFail() - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") - } - base.Cmd("cp", srcPath, testStoppedContainer+":"+destPath).AssertFail() - }) - t.Run("DEST_PATH exists and is a directory", func(t *testing.T) { - t.Run("SRC_PATH does not end with `/.`", func(t *testing.T) { - destPath := filepath.Join(td, "dest2-dir-exists") - err := os.Mkdir(destPath, 0o755) - assert.NilError(t, err) - base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() - catPath := filepath.Join(destPath, strings.TrimPrefix(srcFile, filepath.Dir(srcDir)+"/")) - assertCat(catPath) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") +func cpTestHelper(t *testing.T, tg *testgroup) { + // Get the source path + groupSourceSpec := tg.sourceSpec + groupSourceDir := groupSourceSpec + if tg.sourceIsAFile { + groupSourceDir = filepath.Dir(groupSourceSpec) + } + + // Copy direction + copyToContainer := tg.toContainer + // Description + description := tg.description + // Test cases + testCases := tg.testCases + + // Compute UIDs dependent on cp direction + var srcUID, destUID int + if copyToContainer { + srcUID = os.Geteuid() + destUID = srcUID + } else { + srcUID = 42 + destUID = os.Geteuid() + } + + t.Run(description, func(t *testing.T) { + t.Parallel() + + for _, tc := range testCases { + testCase := tc + + t.Run(testCase.description, func(t *testing.T) { + t.Parallel() + + // Compute test-specific values + testID := testutil.Identifier(t) + containerRunning := testID + "-r" + containerStopped := testID + "-s" + sourceFileContent := []byte(testID) + tempDir := t.TempDir() + + base := testutil.NewBase(t) + // Change working directory for commands to execute to the newly created temp directory on the host + // Note that ChDir won't do in a parallel context - and that setup func on the host below + // has to deal with that problem separately by making sure relative paths are resolved against temp + base.Dir = tempDir + + // Prepare the specs and derived variables + sourceSpec := groupSourceSpec + destinationSpec := testCase.destinationSpec + + // If the test case does not specify a catFile, start with the destination spec + catFile := testCase.catFile + if catFile == "" { + catFile = destinationSpec } - base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() - assertCat(catPath) - }) - t.Run("SRC_PATH does end with `/.`", func(t *testing.T) { - srcPath += "/." - destPath := filepath.Join(td, "dest2-dir2-exists") - err := os.Mkdir(destPath, 0o755) - assert.NilError(t, err) - base.Cmd("cp", testContainer+":"+srcPath, destPath).AssertOK() - catPath := filepath.Join(destPath, filepath.Base(srcFile)) - assertCat(catPath) - if rootlessutil.IsRootless() { - t.Skip("Test skipped in rootless mode for testStoppedContainer") + + sourceFile := filepath.Join(groupSourceDir, srcFileName) + if copyToContainer { + // Use an absolute path for evaluation + if !filepath.IsAbs(catFile) { + catFile = filepath.Join(string(os.PathSeparator), catFile) + } + // If the sourceFile is still relative, make it absolute to the temp + sourceFile = filepath.Join(tempDir, sourceFile) + // If the spec path for source on the host was absolute, make sure we put that under tempDir + if filepath.IsAbs(sourceSpec) { + sourceSpec = tempDir + sourceSpec + } + } else { + // If we are copying to host, we need to make sure we have an absolute path to cat, relative to temp, + // whether it is relative, or "absolute" + catFile = filepath.Join(tempDir, catFile) + // If the spec for destination on the host was absolute, make sure we put that under tempDir + if filepath.IsAbs(destinationSpec) { + destinationSpec = tempDir + destinationSpec + } + } + + // Teardown: clean-up containers and optional volume + tearDown := func() { + base.Cmd("rm", "-f", containerRunning).Run() + base.Cmd("rm", "-f", containerStopped).Run() + if testCase.volume != nil { + volID, _, _ := testCase.volume(base, testID) + base.Cmd("volume", "rm", volID).Run() + } + } + + createFileOnHost := func() { + // Create file on the host + err := os.MkdirAll(filepath.Dir(sourceFile), dirPerm) + assert.NilError(t, err) + err = os.WriteFile(sourceFile, sourceFileContent, filePerm) + assert.NilError(t, err) + } + + // Setup: create volume, containers, create the source file + setup := func() { + args := []string{"run", "-d", "-w", containerCwd} + if testCase.volume != nil { + vol, mount, ro := testCase.volume(base, testID) + volArg := fmt.Sprintf("%s:%s", vol, mount) + if ro { + volArg += ":ro" + } + args = append(args, "-v", volArg) + } + base.Cmd(append(args, "--name", containerRunning, testutil.CommonImage, "sleep", "Inf")...).AssertOK() + base.Cmd(append(args, "--name", containerStopped, testutil.CommonImage, "sleep", "Inf")...).AssertOK() + + if copyToContainer { + createFileOnHost() + } else { + // Create file content in the container + // Note: cd /, otherwise we end-up in the container cwd, which is NOT obeyed by cp + mkSrcScript := fmt.Sprintf("cd /; mkdir -p %q && echo -n %q >%q && chown %d %q", filepath.Dir(sourceFile), sourceFileContent, sourceFile, srcUID, sourceFile) + base.Cmd("exec", containerRunning, "sh", "-euc", mkSrcScript).AssertOK() + base.Cmd("exec", containerStopped, "sh", "-euc", mkSrcScript).AssertOK() + } + + // If we have optional setup, run that now + if testCase.setup != nil { + // Some specs may come with a trailing slash (proper or improper) + // Setup should still work in all cases (including if its a file), and get through to the actual test + setupDest := destinationSpec + setupDest = strings.TrimSuffix(setupDest, string(os.PathSeparator)) + if !filepath.IsAbs(setupDest) { + if copyToContainer { + setupDest = filepath.Join(string(os.PathSeparator), setupDest) + } else { + setupDest = filepath.Join(tempDir, setupDest) + } + } + testCase.setup(base, containerRunning, setupDest) + testCase.setup(base, containerStopped, setupDest) + } + + // Stop the "stopped" container + base.Cmd("stop", containerStopped).AssertOK() + } + + tearDown() + t.Cleanup(tearDown) + // If we have custom teardown, do that + if testCase.tearDown != nil { + testCase.tearDown() + t.Cleanup(testCase.tearDown) + } + + // Do the setup + setup() + + // If Docker, removes the err part of expectation + if testutil.GetTarget() == testutil.Docker { + testCase.expect.Err = "" + } + + // Build the final src and dest specifiers, including `containerXYZ:` + container := "" + if copyToContainer { + container = containerRunning + base.Cmd("cp", sourceSpec, containerRunning+":"+destinationSpec).Assert(testCase.expect) + } else { + base.Cmd("cp", containerRunning+":"+sourceSpec, destinationSpec).Assert(testCase.expect) + } + + // Run the actual test for the running container + // If we expect the op to be a success, also check the destination file + if testCase.expect.ExitCode == 0 { + assertCatHelper(base, catFile, sourceFileContent, container, destUID, false) + } + + // When copying container > host, we get shadowing from the previous container, possibly hiding failures + // Solution: clear-up the tempDir + if copyToContainer { + err := os.RemoveAll(tempDir) + assert.NilError(t, err) + err = os.MkdirAll(tempDir, dirPerm) + assert.NilError(t, err) + createFileOnHost() + defer os.RemoveAll(tempDir) + } + + // ... and for the stopped container + container = "" + var cmd *testutil.Cmd + if copyToContainer { + container = containerStopped + cmd = base.Cmd("cp", sourceSpec, containerStopped+":"+destinationSpec) + } else { + cmd = base.Cmd("cp", containerStopped+":"+sourceSpec, destinationSpec) + } + + if rootlessutil.IsRootless() && testutil.GetTarget() == testutil.Nerdctl { + cmd.Assert( + icmd.Expected{ + ExitCode: 1, + Err: containerutil.ErrRootlessCannotCp.Error(), + }) + return + } + + cmd.Assert(testCase.expect) + if testCase.expect.ExitCode == 0 { + assertCatHelper(base, catFile, sourceFileContent, container, destUID, true) } - base.Cmd("cp", testStoppedContainer+":"+srcPath, destPath).AssertOK() - assertCat(catPath) }) - }) + } }) } From a252d355464ee8f8d7a8bb6983e263e382d1fb02 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 22:44:14 +0000 Subject: [PATCH 0988/1066] build(deps): bump the stargz group with 3 updates Bumps the stargz group with 3 updates: [github.com/containerd/stargz-snapshotter](https://github.com/containerd/stargz-snapshotter), [github.com/containerd/stargz-snapshotter/estargz](https://github.com/containerd/stargz-snapshotter) and [github.com/containerd/stargz-snapshotter/ipfs](https://github.com/containerd/stargz-snapshotter). Updates `github.com/containerd/stargz-snapshotter` from 0.16.2 to 0.16.3 - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/compare/v0.16.2...v0.16.3) Updates `github.com/containerd/stargz-snapshotter/estargz` from 0.16.2 to 0.16.3 - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/compare/v0.16.2...v0.16.3) Updates `github.com/containerd/stargz-snapshotter/ipfs` from 0.16.2 to 0.16.3 - [Release notes](https://github.com/containerd/stargz-snapshotter/releases) - [Commits](https://github.com/containerd/stargz-snapshotter/compare/v0.16.2...v0.16.3) --- updated-dependencies: - dependency-name: github.com/containerd/stargz-snapshotter dependency-type: direct:production update-type: version-update:semver-patch dependency-group: stargz - dependency-name: github.com/containerd/stargz-snapshotter/estargz dependency-type: direct:production update-type: version-update:semver-patch dependency-group: stargz - dependency-name: github.com/containerd/stargz-snapshotter/ipfs dependency-type: direct:production update-type: version-update:semver-patch dependency-group: stargz ... Signed-off-by: dependabot[bot] --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 8b2a979fee5..9045b80a218 100644 --- a/go.mod +++ b/go.mod @@ -25,9 +25,9 @@ require ( github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.15.0 github.com/containerd/platforms v1.0.0-rc.0 - github.com/containerd/stargz-snapshotter v0.16.2 - github.com/containerd/stargz-snapshotter/estargz v0.16.2 - github.com/containerd/stargz-snapshotter/ipfs v0.16.2 + github.com/containerd/stargz-snapshotter v0.16.3 + github.com/containerd/stargz-snapshotter/estargz v0.16.3 + github.com/containerd/stargz-snapshotter/ipfs v0.16.3 github.com/containerd/typeurl/v2 v2.2.3 github.com/containernetworking/cni v1.2.3 github.com/containernetworking/plugins v1.5.1 diff --git a/go.sum b/go.sum index f68a1f3014f..cc1081caebd 100644 --- a/go.sum +++ b/go.sum @@ -57,12 +57,12 @@ github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yu github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= -github.com/containerd/stargz-snapshotter v0.16.2 h1:Fx8t+rxUknxUah+yOnmoNRZF0tPdTXXR1YBwnZxlSE0= -github.com/containerd/stargz-snapshotter v0.16.2/go.mod h1:9cMoG3xVkegdJ5IoxDnTrRxgCht7GteV1w+ik/xZFTw= -github.com/containerd/stargz-snapshotter/estargz v0.16.2 h1:DMcqm1rd1ak2hFghkyHlquacSo+zRe+cysRR3CmSpGk= -github.com/containerd/stargz-snapshotter/estargz v0.16.2/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= -github.com/containerd/stargz-snapshotter/ipfs v0.16.2 h1:+jDyBydg+7USzVXQ2V7ahGK3+S4BM1DZchGdgwBH3n8= -github.com/containerd/stargz-snapshotter/ipfs v0.16.2/go.mod h1:d4EuGnC3RteInKAdddUbDOL88uw3vZySSLZ44pbriGM= +github.com/containerd/stargz-snapshotter v0.16.3 h1:zbQMm8dRuPHEOD4OqAYGajJJUwCeUzt4j7w9Iaw58u4= +github.com/containerd/stargz-snapshotter v0.16.3/go.mod h1:XPOl2oa9zjWidTM2IX191smolwWc3/zkKtp02TzTFb0= +github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8= +github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= +github.com/containerd/stargz-snapshotter/ipfs v0.16.3 h1:d6IBSzYo0vlFcujwTqJRwpI3cZgX3E2I6Ev7LtMaZ4M= +github.com/containerd/stargz-snapshotter/ipfs v0.16.3/go.mod h1:d4EuGnC3RteInKAdddUbDOL88uw3vZySSLZ44pbriGM= github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= From db52916436fbb1095a13440a5df716857ddaf4c3 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 6 Dec 2024 20:02:45 -0800 Subject: [PATCH 0989/1066] Switch github actions to commit sha Signed-off-by: apostasie --- .../ghcr-image-build-and-publish.yml | 12 +++--- .github/workflows/lint.yml | 10 ++--- .github/workflows/project.yml | 6 +-- .github/workflows/release.yml | 4 +- .github/workflows/test-canary.yml | 8 ++-- .github/workflows/test-kube.yml | 2 +- .github/workflows/test.yml | 40 +++++++++---------- 7 files changed, 41 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index e0b812946a8..d57db42cb98 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -31,19 +31,19 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4.2.2 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 # Login against a Docker registry except on PR # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} if: github.event_name != 'pull_request' - uses: docker/login-action@v3.3.0 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -53,14 +53,14 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v5.6.1 + uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5.6.1 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@v6.10.0 + uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 with: context: . platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 433922ed207..0d557eec84b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -36,7 +36,7 @@ jobs: env: GOOS: "${{ matrix.goos }}" steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - name: Set GO env @@ -46,13 +46,13 @@ jobs: . ./hack/build-integration-canary.sh canary::golang::latest fi - - uses: actions/setup-go@v5 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GO_VERSION }} check-latest: true cache: true - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@774c35bcccffb734694af9e921f12f57d882ef74 # v6.1.1 with: args: --verbose other: @@ -60,10 +60,10 @@ jobs: name: yaml | shell | imports order runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GO_VERSION }} check-latest: true diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml index ebeef72caec..bdb34f52d5f 100644 --- a/.github/workflows/project.yml +++ b/.github/workflows/project.yml @@ -13,15 +13,15 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: src/github.com/containerd/nerdctl fetch-depth: 100 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GO_VERSION }} cache-dependency-path: src/github.com/containerd/nerdctl - - uses: containerd/project-checks@v1.1.0 + - uses: containerd/project-checks@434a07157608eeaa1d5c8d4dd506154204cd9401 # v1.1.0 with: working-directory: src/github.com/containerd/nerdctl repo-access-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4043288037c..b3a17aa0813 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,8 +10,8 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 40 steps: - - uses: actions/checkout@v4.2.2 - - uses: actions/setup-go@v5 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: 1.23.x - name: "Compile binaries" diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index 152097cd0fc..c63cdf6fc12 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -19,7 +19,7 @@ jobs: runs-on: "ubuntu-24.04" timeout-minutes: 40 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - name: "Prepare integration test environment" @@ -55,7 +55,7 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - name: Set GO env @@ -70,7 +70,7 @@ jobs: . ./hack/build-integration-canary.sh canary::golang::latest - - uses: actions/setup-go@v5 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GO_VERSION }} cache: true @@ -79,7 +79,7 @@ jobs: - run: go install -v gotest.tools/gotestsum@v1 # This here is solely to get the cni install script, which has not been modified in 3+ years. # There is little to no reason to update this to latest containerd - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: containerd/containerd ref: "v1.7.24" diff --git a/.github/workflows/test-kube.yml b/.github/workflows/test-kube.yml index 2bd0d00f28c..580a9a2181a 100644 --- a/.github/workflows/test-kube.yml +++ b/.github/workflows/test-kube.yml @@ -17,7 +17,7 @@ jobs: env: ROOTFUL: true steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - name: "Run Kubernetes integration tests" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index feba1ca4c26..74c8fd941d2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,11 +40,11 @@ jobs: CONTAINERD_VERSION: "${{ matrix.containerd }}" ARCH: "${{ matrix.arch }}" steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - name: "Expose GitHub Runtime variables for gha" - uses: crazy-max/ghaction-github-runtime@v3 + uses: crazy-max/ghaction-github-runtime@b3a9207c0e1ef41f4cf215303c976869d0c2c1c4 # v3.0.0 - name: "Build dependencies for the integration test environment image" run: | docker buildx create --name with-gha --use @@ -73,16 +73,16 @@ jobs: - os: ubuntu-24.04 goos: linux steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GO_VERSION }} check-latest: true cache: true - if: ${{ matrix.goos=='windows' }} - uses: actions/checkout@v4.2.2 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: containerd/containerd ref: v1.7.24 @@ -126,11 +126,11 @@ jobs: ARCH: "${{ matrix.arch }}" UBUNTU_VERSION: "${{ matrix.ubuntu }}" steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - name: "Expose GitHub Runtime variables for gha" - uses: crazy-max/ghaction-github-runtime@v3 + uses: crazy-max/ghaction-github-runtime@b3a9207c0e1ef41f4cf215303c976869d0c2c1c4 # v3.0.0 - name: "Prepare integration test environment" run: | docker buildx create --name with-gha --use @@ -175,7 +175,7 @@ jobs: ARCH: "${{ matrix.arch }}" UBUNTU_VERSION: "${{ matrix.ubuntu }}" steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - name: Enable ipv4 and ipv6 forwarding @@ -183,7 +183,7 @@ jobs: sudo sysctl -w net.ipv6.conf.all.forwarding=1 sudo sysctl -w net.ipv4.ip_forward=1 - name: "Expose GitHub Runtime variables for gha" - uses: crazy-max/ghaction-github-runtime@v3 + uses: crazy-max/ghaction-github-runtime@b3a9207c0e1ef41f4cf215303c976869d0c2c1c4 # v3.0.0 - name: Enable IPv6 for Docker, and configure docker to use containerd for gha run: | sudo mkdir -p /etc/docker @@ -271,7 +271,7 @@ jobs: } EOT sudo systemctl restart apparmor.service - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - name: "Register QEMU (tonistiigi/binfmt)" @@ -284,7 +284,7 @@ jobs: docker run --privileged --rm tonistiigi/binfmt --install linux/arm64 docker run --privileged --rm tonistiigi/binfmt --install linux/arm/v7 - name: "Expose GitHub Runtime variables for gha" - uses: crazy-max/ghaction-github-runtime@v3 + uses: crazy-max/ghaction-github-runtime@b3a9207c0e1ef41f4cf215303c976869d0c2c1c4 # v3.0.0 - name: "Prepare (network driver=slirp4netns, port driver=builtin)" run: | docker buildx create --name with-gha --use @@ -313,10 +313,10 @@ jobs: matrix: go-version: ["1.22.x", "1.23.x"] steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ matrix.go-version }} cache: true @@ -329,10 +329,10 @@ jobs: name: docker runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GO_VERSION }} cache: true @@ -365,17 +365,17 @@ jobs: run: shell: bash steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GO_VERSION }} cache: true check-latest: true - run: go install ./cmd/nerdctl - run: go install -v gotest.tools/gotestsum@v1 - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: containerd/containerd ref: v1.7.24 @@ -399,10 +399,10 @@ jobs: # ubuntu-24.04 lacks the vagrant package runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/cache@v4 + - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 with: path: /root/.vagrant.d key: vagrant-${{ matrix.box }} From 6e913a6356960fe22f088bfbef65b786624257d7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 6 Dec 2024 20:26:46 -0800 Subject: [PATCH 0990/1066] Remove spurious cache true, default for action/go Signed-off-by: apostasie --- .github/workflows/lint.yml | 2 -- .github/workflows/test-canary.yml | 1 - .github/workflows/test.yml | 4 ---- 3 files changed, 7 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0d557eec84b..37766a246a9 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -50,7 +50,6 @@ jobs: with: go-version: ${{ env.GO_VERSION }} check-latest: true - cache: true - name: golangci-lint uses: golangci/golangci-lint-action@774c35bcccffb734694af9e921f12f57d882ef74 # v6.1.1 with: @@ -67,7 +66,6 @@ jobs: with: go-version: ${{ env.GO_VERSION }} check-latest: true - cache: true - name: yaml run: make lint-yaml - name: shell diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index c63cdf6fc12..b222ad2120e 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -73,7 +73,6 @@ jobs: - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GO_VERSION }} - cache: true check-latest: true - run: go install ./cmd/nerdctl - run: go install -v gotest.tools/gotestsum@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 74c8fd941d2..5aa31126a8a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -80,7 +80,6 @@ jobs: with: go-version: ${{ env.GO_VERSION }} check-latest: true - cache: true - if: ${{ matrix.goos=='windows' }} uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: @@ -319,7 +318,6 @@ jobs: - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ matrix.go-version }} - cache: true check-latest: true - name: "build" run: GO_VERSION="$(echo ${{ matrix.go-version }} | sed -e s/.x//)" make binaries @@ -335,7 +333,6 @@ jobs: - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GO_VERSION }} - cache: true check-latest: true - name: "Register QEMU (tonistiigi/binfmt)" run: | @@ -371,7 +368,6 @@ jobs: - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GO_VERSION }} - cache: true check-latest: true - run: go install ./cmd/nerdctl - run: go install -v gotest.tools/gotestsum@v1 From 7a69f5d854dddffc6229ab41f5d15ef216cb15a7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 16 Dec 2024 13:51:43 -0800 Subject: [PATCH 0991/1066] When the port is 443, also save credentials without port Signed-off-by: apostasie --- pkg/cmd/login/login.go | 11 +++++++++++ pkg/imgutil/dockerconfigresolver/defaults.go | 7 ++++--- pkg/imgutil/dockerconfigresolver/hostsstore.go | 2 +- pkg/imgutil/dockerconfigresolver/registryurl.go | 8 ++++---- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 6f4492ae71b..773bf8edc76 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -92,6 +92,17 @@ func Login(ctx context.Context, options types.LoginCommandOptions, stdout io.Wri return fmt.Errorf("error saving credentials: %w", err) } + // When the port is the https default (443), other clients cannot be expected to necessarily lookup the variants with port + // so save it both with and without port. + // This is the case for at least buildctl: https://github.com/containerd/nerdctl/issues/3748 + if registryURL.Port() == dockerconfigresolver.StandardHTTPSPort { + registryURL.Host = registryURL.Hostname() + err = credStore.Store(registryURL, credentials) + if err != nil { + return fmt.Errorf("error saving credentials: %w", err) + } + } + _, err = fmt.Fprintln(stdout, "Login Succeeded") return err diff --git a/pkg/imgutil/dockerconfigresolver/defaults.go b/pkg/imgutil/dockerconfigresolver/defaults.go index db78f3f70f7..ea91279e3a9 100644 --- a/pkg/imgutil/dockerconfigresolver/defaults.go +++ b/pkg/imgutil/dockerconfigresolver/defaults.go @@ -21,9 +21,10 @@ import "errors" type scheme string const ( - standardHTTPSPort = "443" - schemeHTTP scheme = "http" - schemeHTTPS scheme = "https" + StandardHTTPSPort = "443" + + schemeHTTPS scheme = "https" + schemeHTTP scheme = "http" // schemeNerdctlExperimental is currently provisional, to unlock namespace based host authentication // This may change or break without notice, and you should have no expectations that credentials saved like that // will be supported in the future diff --git a/pkg/imgutil/dockerconfigresolver/hostsstore.go b/pkg/imgutil/dockerconfigresolver/hostsstore.go index 0273a9cd7a6..12df6961455 100644 --- a/pkg/imgutil/dockerconfigresolver/hostsstore.go +++ b/pkg/imgutil/dockerconfigresolver/hostsstore.go @@ -55,7 +55,7 @@ func hostDirsFromRoot(registryURL *RegistryURL, dirs []string) (string, error) { return found, err } // If not found, and the port is standard, try again without the port - if registryURL.Port() == standardHTTPSPort { + if registryURL.Port() == StandardHTTPSPort { found, err = config.HostDirFromRoot(hostsDir)(registryURL.Hostname()) if (err != nil && !errors.Is(err, errdefs.ErrNotFound)) || (found != "") { return found, err diff --git a/pkg/imgutil/dockerconfigresolver/registryurl.go b/pkg/imgutil/dockerconfigresolver/registryurl.go index 4a1ecfccbdf..ec195e1068c 100644 --- a/pkg/imgutil/dockerconfigresolver/registryurl.go +++ b/pkg/imgutil/dockerconfigresolver/registryurl.go @@ -50,7 +50,7 @@ func Parse(address string) (*RegistryURL, error) { } // If it has no port, add the standard port explicitly if u.Port() == "" { - u.Host = u.Hostname() + ":" + standardHTTPSPort + u.Host = u.Hostname() + ":" + StandardHTTPSPort } reg := &RegistryURL{URL: *u} queryParams := u.Query() @@ -74,7 +74,7 @@ type RegistryURL struct { // CanonicalIdentifier returns the identifier expected to be used to save credentials to docker auth config func (rn *RegistryURL) CanonicalIdentifier() string { // If it is the docker index over https, port 443, on the /v1/ path, we use the docker fully qualified identifier - if rn.Scheme == string(schemeHTTPS) && rn.Hostname() == "index.docker.io" && rn.Path == "/v1/" && rn.Port() == standardHTTPSPort || + if rn.Scheme == string(schemeHTTPS) && rn.Hostname() == "index.docker.io" && rn.Path == "/v1/" && rn.Port() == StandardHTTPSPort || rn.URL.String() == dockerIndexServer { return dockerIndexServer } @@ -102,7 +102,7 @@ func (rn *RegistryURL) AllIdentifiers() []string { // Docker behavior: if the domain was index.docker.io over 443, we are allowed to additionally read the canonical // docker credentials - if rn.Port() == standardHTTPSPort { + if rn.Port() == StandardHTTPSPort { if rn.Hostname() == "index.docker.io" || rn.Hostname() == "registry-1.docker.io" { fullList = append(fullList, dockerIndexServer) } @@ -116,7 +116,7 @@ func (rn *RegistryURL) AllIdentifiers() []string { // Note that docker does not try to be smart wrt explicit port vs. implied port // If standard port, allow retrieving credentials from the variant without a port as well - if rn.Port() == standardHTTPSPort { + if rn.Port() == StandardHTTPSPort { fullList = append( fullList, rn.Hostname(), From 2ae8ca7eaaa8aeec5c3fdb138ffd3226b7f361cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:17:33 +0000 Subject: [PATCH 0992/1066] build(deps): bump github.com/containerd/containerd/v2 Bumps [github.com/containerd/containerd/v2](https://github.com/containerd/containerd) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v2.0.0...v2.0.1) --- updated-dependencies: - dependency-name: github.com/containerd/containerd/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9045b80a218..865b8b56b99 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/cgroups/v3 v3.0.4 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0 - github.com/containerd/containerd/v2 v2.0.0 + github.com/containerd/containerd/v2 v2.0.1 github.com/containerd/continuity v0.4.5 github.com/containerd/errdefs v1.0.0 github.com/containerd/fifo v1.1.0 diff --git a/go.sum b/go.sum index cc1081caebd..f3df1c63ed8 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,8 @@ github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= -github.com/containerd/containerd/v2 v2.0.0 h1:qLDdFaAykQrIyLiqwQrNLLz95wiC36bAZVwioUwqShM= -github.com/containerd/containerd/v2 v2.0.0/go.mod h1:j25kDy9P48/ngb1sxWIFfK6GsnqOHoSqo1EpAod20VQ= +github.com/containerd/containerd/v2 v2.0.1 h1:xqSar9cjkGhfQ2YvanCu7FMLk6+pNCFMCAroM2ALPp0= +github.com/containerd/containerd/v2 v2.0.1/go.mod h1:A9DyAg+lXTiSBOsBTqQtJL4O3AGaM1aa4UHmVh4uFhM= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= From ad495507843d0f1d75c65b90e71e6e9212f8d45f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:17:44 +0000 Subject: [PATCH 0993/1066] build(deps): bump github.com/containerd/imgcrypt/v2 Bumps [github.com/containerd/imgcrypt/v2](https://github.com/containerd/imgcrypt) from 2.0.0-rc.1 to 2.0.0. - [Release notes](https://github.com/containerd/imgcrypt/releases) - [Changelog](https://github.com/containerd/imgcrypt/blob/main/CHANGES) - [Commits](https://github.com/containerd/imgcrypt/compare/v2.0.0-rc.1...v2.0.0) --- updated-dependencies: - dependency-name: github.com/containerd/imgcrypt/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 8 +++---- go.sum | 69 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 9045b80a218..763f477580c 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/containerd/errdefs v1.0.0 github.com/containerd/fifo v1.1.0 github.com/containerd/go-cni v1.1.11 - github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 + github.com/containerd/imgcrypt/v2 v2.0.0 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.15.0 github.com/containerd/platforms v1.0.0-rc.0 @@ -85,7 +85,7 @@ require ( github.com/containerd/go-runc v1.1.0 // indirect github.com/containerd/plugin v1.0.0 // indirect github.com/containerd/ttrpc v1.2.6 // indirect - github.com/containers/ocicrypt v1.2.0 // indirect + github.com/containers/ocicrypt v1.2.1 // indirect github.com/djherbis/times v1.6.0 // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect @@ -121,6 +121,7 @@ require ( github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect + github.com/smallstep/pkcs7 v0.1.1 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect @@ -129,7 +130,6 @@ require ( github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect - go.mozilla.org/pkcs7 v0.9.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/otel v1.31.0 // indirect @@ -138,7 +138,7 @@ require ( golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/grpc v1.68.0 // indirect + google.golang.org/grpc v1.68.1 // indirect google.golang.org/protobuf v1.35.2 // indirect lukechampine.com/blake3 v1.3.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index cc1081caebd..f44b3f0f859 100644 --- a/go.sum +++ b/go.sum @@ -47,8 +47,8 @@ github.com/containerd/go-cni v1.1.11 h1:fWt1K15AmSLsEfa57N+qYw4NeGPiQKYq1pjNGJwV github.com/containerd/go-cni v1.1.11/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA= github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U= -github.com/containerd/imgcrypt/v2 v2.0.0-rc.1 h1:7OMu5otk5Z2GeQs24JBPOmYbTc50+q6jo02qWNJc0p8= -github.com/containerd/imgcrypt/v2 v2.0.0-rc.1/go.mod h1:3/Ab3iliBt/aBVNYOwecT1YagCqAiHidOmVsrjtHF1A= +github.com/containerd/imgcrypt/v2 v2.0.0 h1:vd2ByN6cXeearzXCQljH1eYe77FgFO5/B9+dK14mng0= +github.com/containerd/imgcrypt/v2 v2.0.0/go.mod h1:S4kOVvPZRerVueZULagcwkJK7sKc/wQI/ixcmyj26uY= 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.15.0 h1:RqZRs1GPeM6T3wmuxJV9u+2Rg4YETVMwTmiDeX+iWC8= @@ -71,8 +71,8 @@ github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8F github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M= github.com/containernetworking/plugins v1.5.1 h1:T5ji+LPYjjgW0QM+KyrigZbLsZ8jaX+E5J/EcKOE4gQ= github.com/containernetworking/plugins v1.5.1/go.mod h1:MIQfgMayGuHYs0XdNudf31cLLAC+i242hNm6KuDGqCM= -github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sirVuPM= -github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U= +github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM= +github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ= github.com/coreos/go-iptables v0.8.0 h1:MPc2P89IhuVpLI7ETL/2tx3XZ61VeICZjYqDEgNsPRc= github.com/coreos/go-iptables v0.8.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -277,6 +277,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU= +github.com/smallstep/pkcs7 v0.1.1/go.mod h1:dL6j5AIz9GHjVEBTXtW+QliALcgM19RtXaTeyxI+AfA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= @@ -295,8 +297,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= @@ -320,8 +322,7 @@ github.com/yuchanns/srslog v1.1.0 h1:CEm97Xxxd8XpJThE0gc/XsqUGgPufh5u5MUjC27/KOk github.com/yuchanns/srslog v1.1.0/go.mod h1:HsLjdv3XV02C3kgBW2bTyW6i88OQE+VYJZIxrPKPPak= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.mozilla.org/pkcs7 v0.9.0 h1:yM4/HS9dYv7ri2biPtxt8ikvB37a980dg69/pKmS+eI= -go.mozilla.org/pkcs7 v0.9.0/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 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.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s= @@ -339,6 +340,11 @@ go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -349,6 +355,11 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -360,6 +371,13 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -368,6 +386,11 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -376,21 +399,43 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -401,6 +446,10 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -419,8 +468,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= -google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= +google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0= +google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 2d79e100d18a2ff89e975274d7470f9e10767e45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:20:55 +0000 Subject: [PATCH 0994/1066] build(deps): bump golangci/golangci-lint-action Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 774c35bcccffb734694af9e921f12f57d882ef74 to 9937fdf7189f2958a2dc9f6d585e5d65e3326d20. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/774c35bcccffb734694af9e921f12f57d882ef74...9937fdf7189f2958a2dc9f6d585e5d65e3326d20) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 37766a246a9..718a4b713ac 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -51,7 +51,7 @@ jobs: go-version: ${{ env.GO_VERSION }} check-latest: true - name: golangci-lint - uses: golangci/golangci-lint-action@774c35bcccffb734694af9e921f12f57d882ef74 # v6.1.1 + uses: golangci/golangci-lint-action@9937fdf7189f2958a2dc9f6d585e5d65e3326d20 # v6.1.1 with: args: --verbose other: From 98e939cef8c3bd8e78a9bcf6c84934b76b0a9ec5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:20:58 +0000 Subject: [PATCH 0995/1066] build(deps): bump docker/setup-buildx-action from 3.7.1 to 3.8.0 Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3.7.1 to 3.8.0. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/c47758b77c9736f4b2ef4073d4d51994fabfe349...6524bf65af31da8d45b59e8c27de4bd072b392f5) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index d57db42cb98..0eb8331875f 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -37,7 +37,7 @@ jobs: uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 + uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0 # Login against a Docker registry except on PR # https://github.com/docker/login-action From ef02692a91c04006d5750ae81516a40ff3bb6450 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 17 Dec 2024 06:34:03 +0000 Subject: [PATCH 0996/1066] update containerd (2.0.1), runc (1.2.3), buildKit (0.18.2), stargz-snapshotter (0.16.3) Signed-off-by: Kay Yan --- .github/workflows/test.yml | 12 ++++++------ Dockerfile | 10 +++++----- Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.1 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.2 | 2 ++ Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.2 | 3 --- Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.3 | 3 +++ 6 files changed, 16 insertions(+), 16 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.2 delete mode 100644 Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.2 create mode 100644 Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.3 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5aa31126a8a..29eb8273674 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,10 +31,10 @@ jobs: containerd: v1.7.24 arch: amd64 - runner: ubuntu-24.04 - containerd: v2.0.0 + containerd: v2.0.1 arch: amd64 - runner: arm64-8core-32gb - containerd: v2.0.0 + containerd: v2.0.1 arch: arm64 env: CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -113,11 +113,11 @@ jobs: runner: "ubuntu-22.04" arch: amd64 - ubuntu: 24.04 - containerd: v2.0.0 + containerd: v2.0.1 runner: "ubuntu-24.04" arch: amd64 - ubuntu: 24.04 - containerd: v2.0.0 + containerd: v2.0.1 runner: arm64-8core-32gb arch: arm64 env: @@ -167,7 +167,7 @@ jobs: matrix: include: - ubuntu: 24.04 - containerd: v2.0.0 + containerd: v2.0.1 arch: amd64 env: CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -239,7 +239,7 @@ jobs: target: rootless arch: amd64 - ubuntu: 24.04 - containerd: v2.0.0 + containerd: v2.0.1 rootlesskit: v2.3.1 target: rootless arch: amd64 diff --git a/Dockerfile b/Dockerfile index 5715dcab591..e7870b673a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,16 +18,16 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v2.0.0 -ARG RUNC_VERSION=v1.2.2 +ARG CONTAINERD_VERSION=v2.0.1 +ARG RUNC_VERSION=v1.2.3 ARG CNI_PLUGINS_VERSION=v1.6.1 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.18.1 +ARG BUILDKIT_VERSION=v0.18.2 # Extra deps: Lazy-pulling -ARG STARGZ_SNAPSHOTTER_VERSION=v0.16.2 +ARG STARGZ_SNAPSHOTTER_VERSION=v0.16.3 # Extra deps: Encryption -ARG IMGCRYPT_VERSION=v2.0.0-rc.1 +ARG IMGCRYPT_VERSION=v2.0.0 # Extra deps: Rootless ARG ROOTLESSKIT_VERSION=v2.3.1 ARG SLIRP4NETNS_VERSION=v1.3.1 diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.1 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.1 deleted file mode 100644 index 34d303dafcd..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.1 +++ /dev/null @@ -1,2 +0,0 @@ -02b986569330f09dc837486f80d9818812aba1ac8bd892b337adeb56eafe3794 buildkit-v0.18.1.linux-amd64.tar.gz -484a725519bd15a3b3d1f84c2dfc37749af6f06bc6c40d83395312e4d1fb18f1 buildkit-v0.18.1.linux-arm64.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.2 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.2 new file mode 100644 index 00000000000..5a2660e6c67 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.2 @@ -0,0 +1,2 @@ +5662f23cfa5e475ff50932dd2b71d2c5812928fad631d1e8c9f8f5592a4c1568 buildkit-v0.18.2.linux-amd64.tar.gz +de0ae01abc689102de6a765f8f40a30e86203897d3a7b44511a3aa66824bbc48 buildkit-v0.18.2.linux-arm64.tar.gz \ No newline at end of file diff --git a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.2 b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.2 deleted file mode 100644 index c1aba6628f2..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.2 +++ /dev/null @@ -1,3 +0,0 @@ -1958c8eb6275fccc3f7a987eab286fefb68045d79c331660d7253e7f5be20bc0 stargz-snapshotter-v0.16.2-linux-amd64.tar.gz -fc518ac49bb97708b2a0751bedce1bc2c146a9cec7ffdd9c0830a4dc0fd97e17 stargz-snapshotter-v0.16.2-linux-arm64.tar.gz -f1cf855870af16a653d8acb9daa3edf84687c2c05323cb958f078fb148af3eec stargz-snapshotter.service diff --git a/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.3 b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.3 new file mode 100644 index 00000000000..e9b2bfa457c --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/stargz-snapshotter-v0.16.3 @@ -0,0 +1,3 @@ +516984d13e10396f7f6090c51e4e42cc1af9a0d4b16aa81837bcdb1d5a5608d6 stargz-snapshotter-v0.16.3-linux-amd64.tar.gz +d3ac8215603cfd002901c88c568ff5c0685d6953c012fa6ff709deb50f90b023 stargz-snapshotter-v0.16.3-linux-arm64.tar.gz +f1cf855870af16a653d8acb9daa3edf84687c2c05323cb958f078fb148af3eec stargz-snapshotter.service From 98ea42dc0dccaf505785f5f882990c1b6074732b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 22:37:35 +0000 Subject: [PATCH 0997/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.3.5 to 0.3.6. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Changelog](https://github.com/cyphar/filepath-securejoin/blob/main/CHANGELOG.md) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.3.5...v0.3.6) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9f7fce48888..751a791b2fb 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.8.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.3.5 + github.com/cyphar/filepath-securejoin v0.3.6 github.com/distribution/reference v0.6.0 github.com/docker/cli v27.4.0+incompatible github.com/docker/docker v27.4.0+incompatible diff --git a/go.sum b/go.sum index 2d0a48823f8..2b92edc7cc8 100644 --- a/go.sum +++ b/go.sum @@ -80,8 +80,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.3.5 h1:L81NHjquoQmcPgXcttUS9qTSR/+bXry6pbSINQGpjj4= -github.com/cyphar/filepath-securejoin v0.3.5/go.mod h1:edhVd3c6OXKjUmSrVa/tGJRS9joFTxlslFCAyaxigkE= +github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= +github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= From 49bf063ef8c1553e25e5e6e05b7128d0c3277aa0 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 18 Dec 2024 11:35:32 -0800 Subject: [PATCH 0998/1066] Fix wrong commit sha for golangci action Signed-off-by: apostasie --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 718a4b713ac..87ad6b3dcda 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -51,7 +51,7 @@ jobs: go-version: ${{ env.GO_VERSION }} check-latest: true - name: golangci-lint - uses: golangci/golangci-lint-action@9937fdf7189f2958a2dc9f6d585e5d65e3326d20 # v6.1.1 + uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 with: args: --verbose other: From b777a65f41f3ade8102f9b68831cac29fa044e0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2024 22:28:39 +0000 Subject: [PATCH 0999/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.4.0+incompatible to 27.4.1+incompatible - [Commits](https://github.com/docker/cli/compare/v27.4.0...v27.4.1) Updates `github.com/docker/docker` from 27.4.0+incompatible to 27.4.1+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.4.0...v27.4.1) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 751a791b2fb..5d9a62e3adf 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.3.6 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.4.0+incompatible - github.com/docker/docker v27.4.0+incompatible + github.com/docker/cli v27.4.1+incompatible + github.com/docker/docker v27.4.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 2b92edc7cc8..9b1e70b7afd 100644 --- a/go.sum +++ b/go.sum @@ -90,10 +90,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.4.0+incompatible h1:/nJzWkcI1MDMN+U+px/YXnQWJqnu4J+QKGTfD6ptiTc= -github.com/docker/cli v27.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.4.0+incompatible h1:I9z7sQ5qyzO0BfAb9IMOawRkAGxhYsidKiTMcm0DU+A= -github.com/docker/docker v27.4.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.4.1+incompatible h1:VzPiUlRJ/xh+otB75gva3r05isHMo5wXDfPRi5/b4hI= +github.com/docker/cli v27.4.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.4.1+incompatible h1:ZJvcY7gfwHn1JF48PfbyXg7Jyt9ZCWDW+GGXOIxEwp4= +github.com/docker/docker v27.4.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 25e4f3fdaa56ad70be3480ca9e8c367e5b692c49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 22:14:32 +0000 Subject: [PATCH 1000/1066] build(deps): bump golang.org/x/net in the golang-x group Bumps the golang-x group with 1 update: [golang.org/x/net](https://github.com/golang/net). Updates `golang.org/x/net` from 0.32.0 to 0.33.0 - [Commits](https://github.com/golang/net/compare/v0.32.0...v0.33.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5d9a62e3adf..a3f978e5ee9 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.5.0 golang.org/x/crypto v0.31.0 - golang.org/x/net v0.32.0 + golang.org/x/net v0.33.0 golang.org/x/sync v0.10.0 golang.org/x/sys v0.28.0 golang.org/x/term v0.27.0 diff --git a/go.sum b/go.sum index 9b1e70b7afd..1690e58cc3d 100644 --- a/go.sum +++ b/go.sum @@ -378,8 +378,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= From 8b5bb67331fc7f8d8e5b9b4ce5881efb15e556ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 22:14:47 +0000 Subject: [PATCH 1001/1066] build(deps): bump github.com/containerd/cgroups/v3 from 3.0.4 to 3.0.5 Bumps [github.com/containerd/cgroups/v3](https://github.com/containerd/cgroups) from 3.0.4 to 3.0.5. - [Release notes](https://github.com/containerd/cgroups/releases) - [Commits](https://github.com/containerd/cgroups/compare/v3.0.4...v3.0.5) --- updated-dependencies: - dependency-name: github.com/containerd/cgroups/v3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5d9a62e3adf..8fe8f705c75 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/Microsoft/hcsshim v0.12.9 github.com/compose-spec/compose-go/v2 v2.4.6 github.com/containerd/accelerated-container-image v1.2.3 - github.com/containerd/cgroups/v3 v3.0.4 + github.com/containerd/cgroups/v3 v3.0.5 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0 github.com/containerd/containerd/v2 v2.0.1 diff --git a/go.sum b/go.sum index 9b1e70b7afd..1111f23dce0 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,8 @@ github.com/compose-spec/compose-go/v2 v2.4.6 h1:QiqXQ2L/f0OCbAl41bPpeiGAWVRIQ+GE github.com/compose-spec/compose-go/v2 v2.4.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= -github.com/containerd/cgroups/v3 v3.0.4 h1:2fs7l3P0Qxb1nKWuJNFiwhp2CqiKzho71DQkDrHJIo4= -github.com/containerd/cgroups/v3 v3.0.4/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= +github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= +github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= 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/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= From 3dbd24cfd21aa47c1b396554aa4431264276bec1 Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Tue, 17 Dec 2024 05:14:29 +0000 Subject: [PATCH 1002/1066] fix pull image process output from stderr to stdout Signed-off-by: Kay Yan --- cmd/nerdctl/image/image_pull.go | 5 ++-- cmd/nerdctl/image/image_pull_linux_test.go | 33 ++++++++++++++++++++++ pkg/api/types/image_types.go | 7 +++-- pkg/imgutil/imgutil.go | 3 ++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/image/image_pull.go b/cmd/nerdctl/image/image_pull.go index 9b1f961d8e1..cedef1af639 100644 --- a/cmd/nerdctl/image/image_pull.go +++ b/cmd/nerdctl/image/image_pull.go @@ -129,8 +129,9 @@ func processPullCommandFlags(cmd *cobra.Command) (types.ImagePullOptions, error) RFlags: types.RemoteSnapshotterFlags{ SociIndexDigest: sociIndexDigest, }, - Stdout: cmd.OutOrStdout(), - Stderr: cmd.OutOrStderr(), + Stdout: cmd.OutOrStdout(), + Stderr: cmd.OutOrStderr(), + ProgressOutputToStdout: true, }, nil } diff --git a/cmd/nerdctl/image/image_pull_linux_test.go b/cmd/nerdctl/image/image_pull_linux_test.go index 28aa8b0cb9f..c350d1e71a4 100644 --- a/cmd/nerdctl/image/image_pull_linux_test.go +++ b/cmd/nerdctl/image/image_pull_linux_test.go @@ -236,3 +236,36 @@ func TestImagePullSoci(t *testing.T) { testCase.Run(t) } + +func TestImagePullProcessOutput(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + SubTests: []*test.Case{ + { + Description: "Pull Image - output should be in stdout", + NoParallel: true, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", testutil.BusyboxImage) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("pull", testutil.BusyboxImage) + }, + Expected: test.Expects(0, nil, test.Contains(testutil.BusyboxImage)), + }, + { + Description: "Run Container with image pull - output should be in stderr", + NoParallel: true, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", testutil.BusyboxImage) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--rm", testutil.BusyboxImage) + }, + Expected: test.Expects(0, nil, test.DoesNotContain(testutil.BusyboxImage)), + }, + }, + } + + testCase.Run(t) +} diff --git a/pkg/api/types/image_types.go b/pkg/api/types/image_types.go index 30e0d65c31c..0a723ca2cd2 100644 --- a/pkg/api/types/image_types.go +++ b/pkg/api/types/image_types.go @@ -189,8 +189,11 @@ type RemoteSnapshotterFlags struct { // ImagePullOptions specifies options for `nerdctl (image) pull`. type ImagePullOptions struct { - Stdout io.Writer - Stderr io.Writer + Stdout io.Writer + Stderr io.Writer + // ProgressOutputToStdout directs progress output to stdout instead of stderr + ProgressOutputToStdout bool + GOptions GlobalCommandOptions VerifyOptions ImageVerifyOptions // Unpack the image for the current single platform. diff --git a/pkg/imgutil/imgutil.go b/pkg/imgutil/imgutil.go index 09ca283b5dc..3f8076df9f4 100644 --- a/pkg/imgutil/imgutil.go +++ b/pkg/imgutil/imgutil.go @@ -207,6 +207,9 @@ func PullImage(ctx context.Context, client *containerd.Client, resolver remotes. } if !options.Quiet { config.ProgressOutput = options.Stderr + if options.ProgressOutputToStdout { + config.ProgressOutput = options.Stdout + } } // unpack(B) if given 1 platform unless specified by `unpack` From b26474b2753bf9de892034afbb7c819916d4d1b9 Mon Sep 17 00:00:00 2001 From: ningmingxiao Date: Thu, 19 Dec 2024 10:01:23 +0800 Subject: [PATCH 1003/1066] doc:add some doc for ulimit Signed-off-by: ningmingxiao --- docs/command-reference.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/command-reference.md b/docs/command-reference.md index 28c4da551de..27380f4832b 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -378,6 +378,26 @@ Ulimit flags: - :whale: `--ulimit`: Set ulimit +--ulimit can be used to restrict the following types of resources. + +| type | describe| value range | +|----|----|----| +| core | limits the core file size (KB)| A 64-bit integer (INT64), with no units. It can be 0, negative, where -1 represents UNLIMITED (i.e., no limit is applied), and any other negative values will be forcibly converted to a large positive integer.| +| cpu | max CPU time (MIN)| same as above| +| data |max data size (KB) | same as above| +| fsize | maximum filesize (KB)| same as above| +| locks | max number of file locks the user can hold | same as above| +| memlock | max locked-in-memory address space (KB) | same as above| +| msgqueue | max memory used by POSIX message queues (bytes)| same as above| +| nice | nice priority | same as above | +| nproc | max number of processes | same as above| +| rss | max resident set size (KB)| same as above| +| rtprio | max realtime priority| same as above| +| rttime | realtime timeout | same as above| +| sigpending | max number of pending signals| same as above| +| stack | max stack size (KB) | same as above| +| nofile | max number of open file descriptors| A 64-bit integer (int64), with no units. It cannot be negative; negative values will be forcibly converted to a large number, and an "Operation not permitted" error will occur during setting| + Verify flags: - :nerd_face: `--verify`: Verify the image (none|cosign|notation). See [`./cosign.md`](./cosign.md) and [`./notation.md`](./notation.md) for details. From f3f83100abff07028cb63620ac70d5207f4e908b Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Sun, 22 Dec 2024 18:53:48 -0700 Subject: [PATCH 1004/1066] Add nerdctl build --add-host option support This change refactors the parse extra hosts logic from container run command and adds support for image build add-host flag. Signed-off-by: Austin Vazquez --- cmd/nerdctl/builder/builder_build.go | 6 ++ cmd/nerdctl/builder/builder_build_test.go | 29 ++++++++ docs/command-reference.md | 3 +- pkg/api/types/builder_types.go | 2 + pkg/cmd/builder/build.go | 9 +++ pkg/cmd/container/create.go | 21 ++---- pkg/containerutil/containerutil.go | 34 ++++++++++ pkg/containerutil/containerutil_test.go | 83 +++++++++++++++++++++++ 8 files changed, 170 insertions(+), 17 deletions(-) create mode 100644 pkg/containerutil/containerutil_test.go diff --git a/cmd/nerdctl/builder/builder_build.go b/cmd/nerdctl/builder/builder_build.go index 096a86df668..f22bcb8d517 100644 --- a/cmd/nerdctl/builder/builder_build.go +++ b/cmd/nerdctl/builder/builder_build.go @@ -45,6 +45,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container SilenceErrors: true, } helpers.AddStringFlag(buildCommand, "buildkit-host", nil, "", "BUILDKIT_HOST", "BuildKit address") + buildCommand.Flags().StringArray("add-host", nil, "Add a custom host-to-IP mapping (format: \"host:ip\")") buildCommand.Flags().StringArrayP("tag", "t", nil, "Name and optionally a tag in the 'name:tag' format") buildCommand.Flags().StringP("file", "f", "", "Name of the Dockerfile") buildCommand.Flags().String("target", "", "Set the target build stage to build") @@ -92,6 +93,10 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu if err != nil { return types.BuilderBuildOptions{}, err } + extraHosts, err := cmd.Flags().GetStringArray("add-host") + if err != nil { + return types.BuilderBuildOptions{}, err + } platform, err := cmd.Flags().GetStringSlice("platform") if err != nil { return types.BuilderBuildOptions{}, err @@ -232,6 +237,7 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu Stdin: cmd.InOrStdin(), NetworkMode: network, ExtendedBuildContext: extendedBuildCtx, + ExtraHosts: extraHosts, }, nil } diff --git a/cmd/nerdctl/builder/builder_build_test.go b/cmd/nerdctl/builder/builder_build_test.go index e3d736f9435..407804f904d 100644 --- a/cmd/nerdctl/builder/builder_build_test.go +++ b/cmd/nerdctl/builder/builder_build_test.go @@ -957,3 +957,32 @@ func TestBuildAttestation(t *testing.T) { testCase.Run(t) } + +func TestBuildAddHost(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Require: test.Require( + nerdtest.Build, + ), + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rmi", "-f", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + dockerfile := fmt.Sprintf(`FROM %s +RUN ping -c 5 alpha +RUN ping -c 5 beta +`, testutil.CommonImage) + buildCtx := data.TempDir() + err := os.WriteFile(filepath.Join(buildCtx, "Dockerfile"), []byte(dockerfile), 0o600) + assert.NilError(helpers.T(), err) + data.Set("buildCtx", buildCtx) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("build", data.Get("buildCtx"), "-t", data.Identifier(), "--add-host", "alpha:127.0.0.1", "--add-host", "beta:127.0.0.1") + }, + Expected: test.Expects(0, nil, nil), + } + + testCase.Run(t) +} diff --git a/docs/command-reference.md b/docs/command-reference.md index 28c4da551de..8f7ce1b18a7 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -714,8 +714,9 @@ Flags: - :whale: `--label`: Set metadata for an image - :whale: `--network=(default|host|none)`: Set the networking mode for the RUN instructions during build.(compatible with `buildctl build`) - :whale: `--build-context`: Set additional contexts for build (e.g. dir2=/path/to/dir2, myorg/myapp=docker-image://path/to/myorg/myapp) +- :whale: `--add-host`: Add a custom host-to-IP mapping (format: `host:ip`) -Unimplemented `docker build` flags: `--add-host`, `--squash` +Unimplemented `docker build` flags: `--squash` ### :whale: nerdctl commit diff --git a/pkg/api/types/builder_types.go b/pkg/api/types/builder_types.go index c68ec7c44b7..b9574aebcc6 100644 --- a/pkg/api/types/builder_types.go +++ b/pkg/api/types/builder_types.go @@ -71,6 +71,8 @@ type BuilderBuildOptions struct { NetworkMode string // Pull determines if we should try to pull latest image from remote. Default is buildkit's default. Pull *bool + // ExtraHosts is a set of custom host-to-IP mappings. + ExtraHosts []string } // BuilderPruneOptions specifies options for `nerdctl builder prune`. diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 9d1f0f7b05f..2ab6df0e8cb 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -40,6 +40,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/api/types" "github.com/containerd/nerdctl/v2/pkg/buildkitutil" "github.com/containerd/nerdctl/v2/pkg/clientutil" + "github.com/containerd/nerdctl/v2/pkg/containerutil" "github.com/containerd/nerdctl/v2/pkg/platformutil" "github.com/containerd/nerdctl/v2/pkg/referenceutil" "github.com/containerd/nerdctl/v2/pkg/strutil" @@ -453,6 +454,14 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option } } + if len(options.ExtraHosts) > 0 { + extraHosts, err := containerutil.ParseExtraHosts(options.ExtraHosts, options.GOptions.HostGatewayIP, "=") + if err != nil { + return "", nil, false, "", nil, nil, err + } + buildctlArgs = append(buildctlArgs, "--opt=add-hosts="+strings.Join(extraHosts, ",")) + } + return buildctlBinary, buildctlArgs, needsLoading, metaFile, tags, cleanup, nil } diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 946203ad1e3..37d625b1da5 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -30,7 +30,6 @@ import ( "strings" dockercliopts "github.com/docker/cli/opts" - dockeropts "github.com/docker/docker/opts" "github.com/opencontainers/runtime-spec/specs-go" containerd "github.com/containerd/containerd/v2/client" @@ -323,22 +322,12 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa } internalLabels.name = options.Name internalLabels.pidFile = options.PidFile - internalLabels.extraHosts = strutil.DedupeStrSlice(netManager.NetworkOptions().AddHost) - for i, host := range internalLabels.extraHosts { - if _, err := dockercliopts.ValidateExtraHost(host); err != nil { - return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err - } - parts := strings.SplitN(host, ":", 2) - // If the IP Address is a string called "host-gateway", replace this value with the IP address stored - // in the daemon level HostGateway IP config variable. - if len(parts) == 2 && parts[1] == dockeropts.HostGatewayName { - if options.GOptions.HostGatewayIP == "" { - return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), fmt.Errorf("unable to derive the IP value for host-gateway") - } - parts[1] = options.GOptions.HostGatewayIP - internalLabels.extraHosts[i] = fmt.Sprintf(`%s:%s`, parts[0], parts[1]) - } + + extraHosts, err := containerutil.ParseExtraHosts(netManager.NetworkOptions().AddHost, options.GOptions.HostGatewayIP, ":") + if err != nil { + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), err } + internalLabels.extraHosts = extraHosts internalLabels.rm = containerutil.EncodeContainerRmOptLabel(options.Rm) diff --git a/pkg/containerutil/containerutil.go b/pkg/containerutil/containerutil.go index 4f21fa70546..fca15cb6669 100644 --- a/pkg/containerutil/containerutil.go +++ b/pkg/containerutil/containerutil.go @@ -28,6 +28,8 @@ import ( "strings" "time" + dockercliopts "github.com/docker/cli/opts" + dockeropts "github.com/docker/docker/opts" "github.com/moby/sys/signal" "github.com/opencontainers/runtime-spec/specs-go" @@ -49,6 +51,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/portutil" "github.com/containerd/nerdctl/v2/pkg/rootlessutil" "github.com/containerd/nerdctl/v2/pkg/signalutil" + "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/taskutil" ) @@ -606,3 +609,34 @@ func EncodeContainerRmOptLabel(rmOpt bool) string { func DecodeContainerRmOptLabel(rmOptLabel string) (bool, error) { return strconv.ParseBool(rmOptLabel) } + +// ParseExtraHosts takes an array of host-to-IP mapping strings, e.g. "localhost:127.0.0.1", +// and a hostGatewayIP for resolving mappings to "host-gateway". +// +// Returns a map of host-to-IPs or errors if any mapping strings are not correctly formatted. +func ParseExtraHosts(extraHosts []string, hostGatewayIP, separator string) ([]string, error) { + hosts := make([]string, 0, len(extraHosts)) + for _, hostToIP := range strutil.DedupeStrSlice(extraHosts) { + if _, err := dockercliopts.ValidateExtraHost(hostToIP); err != nil { + return nil, err + } + + parts := strings.SplitN(hostToIP, ":", 2) + if len(parts) != 2 { + return nil, fmt.Errorf("invalid host-to-IP map %s", hostToIP) + } + + host, ip := parts[0], parts[1] + + // If the IP address is a string called "host-gateway", replace this value with the IP address stored + // in the daemon level HostGatewayIP config variable. + if ip == dockeropts.HostGatewayName && hostGatewayIP == "" { + return nil, errors.New("unable to derive the IP value for host-gateway") + } else if ip == dockeropts.HostGatewayName { + ip = hostGatewayIP + } + + hosts = append(hosts, host+separator+ip) + } + return hosts, nil +} diff --git a/pkg/containerutil/containerutil_test.go b/pkg/containerutil/containerutil_test.go new file mode 100644 index 00000000000..88d6c42be94 --- /dev/null +++ b/pkg/containerutil/containerutil_test.go @@ -0,0 +1,83 @@ +/* + 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 containerutil + +import ( + "reflect" + "testing" +) + +func TestParseExtraHosts(t *testing.T) { + tests := []struct { + name string + extraHosts []string + hostGateway string + separator string + expected []string + expectedErrStr string + }{ + { + name: "NoExtraHosts", + expected: []string{}, + }, + { + name: "ExtraHosts", + extraHosts: []string{"localhost:127.0.0.1", "localhost:[::1]"}, + separator: ":", + expected: []string{"localhost:127.0.0.1", "localhost:[::1]"}, + }, + { + name: "EqualsSeperator", + extraHosts: []string{"localhost:127.0.0.1", "localhost:[::1]"}, + separator: "=", + expected: []string{"localhost=127.0.0.1", "localhost=[::1]"}, + }, + { + name: "InvalidExtraHostFormat", + extraHosts: []string{"localhost"}, + expectedErrStr: "bad format for add-host: \"localhost\"", + }, + { + name: "ErrorOnHostGatewayExtraHostWithNoHostGatewayIPSet", + extraHosts: []string{"localhost:host-gateway"}, + separator: ":", + expectedErrStr: "unable to derive the IP value for host-gateway", + }, + { + name: "HostGatewayIP", + extraHosts: []string{"localhost:host-gateway"}, + hostGateway: "10.10.0.1", + separator: ":", + expected: []string{"localhost:10.10.0.1"}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + extraHosts, err := ParseExtraHosts(test.extraHosts, test.hostGateway, test.separator) + if err != nil && err.Error() != test.expectedErrStr { + t.Fatalf("expected '%s', actual '%v'", test.expectedErrStr, err) + } else if err == nil && test.expectedErrStr != "" { + t.Fatalf("expected error '%s' but got none", test.expectedErrStr) + } + + if !reflect.DeepEqual(test.expected, extraHosts) { + t.Fatalf("expected %v, actual %v", test.expected, extraHosts) + } + }) + } +} From eaa8df0b507b463b29b403c197ef7559933b0a3a Mon Sep 17 00:00:00 2001 From: fengwei0328 Date: Tue, 10 Dec 2024 11:21:55 +0800 Subject: [PATCH 1005/1066] Fix duplicate image entries in k8s.io namespaces The same imageId underk8s.io is showing multiple results: repo:tag, repo:digest, configID. We expect to display only repo:tag, consistent with other namespaces and CRI. e.g. nerdctl -n k8s.io images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE centos 7 be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB centos be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB expect: nerdctl --kube-hide-dupe -n k8s.io images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE centos 7 be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB Of course, even after deduplicating the images displayed, there are still issues with deleting the images. It is necessary to distinguish between repo:tag and configId, as well as repoDigest. Considering the situation with tags, we need to ensure that all repo:tags under the same imageId are cleaned up before proceeding to clean up the configId and repoDigest. see: https://github.com/containerd/nerdctl/issues/3702 Signed-off-by: fengwei0328 --- cmd/nerdctl/helpers/flagutil.go | 5 + cmd/nerdctl/image/image_list_test.go | 67 ++++++++++ cmd/nerdctl/image/image_remove_test.go | 170 +++++++++++++++++++++++++ cmd/nerdctl/main.go | 1 + docs/config.md | 1 + pkg/cmd/image/list.go | 44 ++++++- pkg/cmd/image/remove.go | 54 +++++++- pkg/config/config.go | 2 + pkg/idutil/imagewalker/imagewalker.go | 120 ++++++++++++++++- 9 files changed, 460 insertions(+), 4 deletions(-) diff --git a/cmd/nerdctl/helpers/flagutil.go b/cmd/nerdctl/helpers/flagutil.go index ef3dd22aada..871b018a024 100644 --- a/cmd/nerdctl/helpers/flagutil.go +++ b/cmd/nerdctl/helpers/flagutil.go @@ -103,6 +103,10 @@ func ProcessRootCmdFlags(cmd *cobra.Command) (types.GlobalCommandOptions, error) if err != nil { return types.GlobalCommandOptions{}, err } + kubeHideDupe, err := cmd.Flags().GetBool("kube-hide-dupe") + if err != nil { + return types.GlobalCommandOptions{}, err + } return types.GlobalCommandOptions{ Debug: debug, DebugFull: debugFull, @@ -118,6 +122,7 @@ func ProcessRootCmdFlags(cmd *cobra.Command) (types.GlobalCommandOptions, error) Experimental: experimental, HostGatewayIP: hostGatewayIP, BridgeIP: bridgeIP, + KubeHideDupe: kubeHideDupe, }, nil } diff --git a/cmd/nerdctl/image/image_list_test.go b/cmd/nerdctl/image/image_list_test.go index 6aae9354a90..a4384c997ad 100644 --- a/cmd/nerdctl/image/image_list_test.go +++ b/cmd/nerdctl/image/image_list_test.go @@ -317,3 +317,70 @@ CMD ["echo", "nerdctl-build-notag-string"] testCase.Run(t) } + +func TestImagesKubeWithKubeHideDupe(t *testing.T) { + nerdtest.Setup() + + testCase := &test.Case{ + Require: test.Require( + nerdtest.OnlyKubernetes, + ), + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "--quiet", testutil.BusyboxImage) + }, + SubTests: []*test.Case{ + { + Description: "The same imageID will not print no-repo:tag in k8s.io with kube-hide-dupe", + Command: test.Command("--kube-hide-dupe", "images"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + var imageID string + var skipLine int + lines := strings.Split(strings.TrimSpace(stdout), "\n") + header := "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tPLATFORM\tSIZE\tBLOB SIZE" + if nerdtest.IsDocker() { + header = "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tSIZE" + } + tab := tabutil.NewReader(header) + err := tab.ParseHeader(lines[0]) + assert.NilError(t, err, info) + found := true + for i, line := range lines[1:] { + repo, _ := tab.ReadRow(line, "REPOSITORY") + tag, _ := tab.ReadRow(line, "TAG") + if repo+":"+tag == testutil.BusyboxImage { + skipLine = i + imageID, _ = tab.ReadRow(line, "IMAGE ID") + break + } + } + for i, line := range lines[1:] { + if i == skipLine { + continue + } + id, _ := tab.ReadRow(line, "IMAGE ID") + if id == imageID { + found = false + break + } + } + assert.Assert(t, found, info) + }, + } + }, + }, + { + Description: "the same imageId will print no-repo:tag in k8s.io without kube-hide-dupe", + Command: test.Command("images"), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: test.Contains(""), + } + }, + }, + }, + } + + testCase.Run(t) +} diff --git a/cmd/nerdctl/image/image_remove_test.go b/cmd/nerdctl/image/image_remove_test.go index ff3d33cbb71..e7e0e4d2c92 100644 --- a/cmd/nerdctl/image/image_remove_test.go +++ b/cmd/nerdctl/image/image_remove_test.go @@ -351,3 +351,173 @@ func TestIssue3016(t *testing.T) { testCase.Run(t) } + +func TestRemoveKubeWithKubeHideDupe(t *testing.T) { + var numTags, numNoTags int + testCase := nerdtest.Setup() + testCase.NoParallel = true + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("--kube-hide-dupe", "rmi", "-f", testutil.BusyboxImage) + } + testCase.Setup = func(data test.Data, helpers test.Helpers) { + numTags = len(strings.Split(strings.TrimSpace(helpers.Capture("--kube-hide-dupe", "images")), "\n")) + numNoTags = len(strings.Split(strings.TrimSpace(helpers.Capture("images")), "\n")) + } + testCase.Require = test.Require( + nerdtest.OnlyKubernetes, + ) + testCase.SubTests = []*test.Case{ + { + Description: "After removing the tag without kube-hide-dupe, repodigest is shown as ", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.BusyboxImage) + }, + Command: test.Command("rmi", "-f", testutil.BusyboxImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Errors: []error{}, + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("--kube-hide-dupe", "images").Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) == numTags+1, info) + }, + }) + helpers.Command("images").Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) == numNoTags+1, info) + }, + }) + }, + } + }, + }, + { + Description: "If there are other tags, the Repodigest will not be deleted", + NoParallel: true, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("--kube-hide-dupe", "rmi", data.Identifier()) + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.BusyboxImage) + helpers.Ensure("tag", testutil.BusyboxImage, data.Identifier()) + }, + Command: test.Command("--kube-hide-dupe", "rmi", testutil.BusyboxImage), + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Errors: []error{}, + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("--kube-hide-dupe", "images").Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) == numTags+1, info) + }, + }) + helpers.Command("images").Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) == numNoTags+2, info) + }, + }) + }, + } + }, + }, + { + Description: "After deleting all repo:tag entries, all repodigests will be cleaned up", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.BusyboxImage) + helpers.Ensure("tag", testutil.BusyboxImage, data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + helpers.Ensure("--kube-hide-dupe", "rmi", "-f", testutil.BusyboxImage) + return helpers.Command("--kube-hide-dupe", "rmi", "-f", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("--kube-hide-dupe", "images").Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) == numTags, info) + }, + }) + helpers.Command("images").Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) == numNoTags, info) + }, + }) + }, + } + }, + }, + { + Description: "Test multiple IDs found with provided prefix and force with shortID", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.BusyboxImage) + helpers.Ensure("tag", testutil.BusyboxImage, data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("--kube-hide-dupe", "images", testutil.BusyboxImage, "-q") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + helpers.Command("--kube-hide-dupe", "rmi", stdout[0:12]).Run(&test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("multiple IDs found with provided prefix: ")}, + }) + helpers.Command("--kube-hide-dupe", "rmi", "--force", stdout[0:12]).Run(&test.Expected{ + ExitCode: 0, + }) + helpers.Command("images").Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) == numNoTags, info) + }, + }) + }, + } + }, + }, + { + Description: "Test remove image with digestID", + NoParallel: true, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", testutil.BusyboxImage) + helpers.Ensure("tag", testutil.BusyboxImage, data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("--kube-hide-dupe", "images", testutil.BusyboxImage, "-q", "--no-trunc") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + imgID := strings.Split(stdout, "\n") + helpers.Command("--kube-hide-dupe", "rmi", imgID[0]).Run(&test.Expected{ + ExitCode: 1, + Errors: []error{errors.New("multiple IDs found with provided prefix: ")}, + }) + helpers.Command("--kube-hide-dupe", "rmi", "--force", imgID[0]).Run(&test.Expected{ + ExitCode: 0, + }) + helpers.Command("images").Run(&test.Expected{ + Output: func(stdout string, info string, t *testing.T) { + lines := strings.Split(strings.TrimSpace(stdout), "\n") + assert.Assert(t, len(lines) == numNoTags, info) + }, + }) + }, + } + }, + }, + } + testCase.Run(t) +} diff --git a/cmd/nerdctl/main.go b/cmd/nerdctl/main.go index 50797e5b804..678fb5cf424 100644 --- a/cmd/nerdctl/main.go +++ b/cmd/nerdctl/main.go @@ -184,6 +184,7 @@ func initRootCmdFlags(rootCmd *cobra.Command, tomlPath string) (*pflag.FlagSet, helpers.AddPersistentBoolFlag(rootCmd, "experimental", nil, nil, cfg.Experimental, "NERDCTL_EXPERIMENTAL", "Control experimental: https://github.com/containerd/nerdctl/blob/main/docs/experimental.md") helpers.AddPersistentStringFlag(rootCmd, "host-gateway-ip", nil, nil, nil, aliasToBeInherited, cfg.HostGatewayIP, "NERDCTL_HOST_GATEWAY_IP", "IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the host. It has no effect without setting --add-host") helpers.AddPersistentStringFlag(rootCmd, "bridge-ip", nil, nil, nil, aliasToBeInherited, cfg.BridgeIP, "NERDCTL_BRIDGE_IP", "IP address for the default nerdctl bridge network") + rootCmd.PersistentFlags().Bool("kube-hide-dupe", cfg.KubeHideDupe, "Deduplicate images for Kubernetes with namespace k8s.io") return aliasToBeInherited, nil } diff --git a/docs/config.md b/docs/config.md index d31f404b205..1f0b4cd15e5 100644 --- a/docs/config.md +++ b/docs/config.md @@ -46,6 +46,7 @@ experimental = true | `experimental` | `--experimental` | `NERDCTL_EXPERIMENTAL` | Enable [experimental features](experimental.md) | Since 0.22.3 | | `host_gateway_ip` | `--host-gateway-ip` | `NERDCTL_HOST_GATEWAY_IP` | IP address that the special 'host-gateway' string in --add-host resolves to. Defaults to the IP address of the host. It has no effect without setting --add-host | Since 1.3.0 | | `bridge_ip` | `--bridge-ip` | `NERDCTL_BRIDGE_IP` | IP address for the default nerdctl bridge network, e.g., 10.1.100.1/24 | Since 2.0.1 | +| `kube-hide-dupe` | `--kube-hide-dupe` | | Deduplicate images for Kubernetes with namespace k8s.io, no more redundant ones are displayed | Since 2.0.3 | The properties are parsed in the following precedence: 1. CLI flag diff --git a/pkg/cmd/image/list.go b/pkg/cmd/image/list.go index 19905645c59..c7440b459fb 100644 --- a/pkg/cmd/image/list.go +++ b/pkg/cmd/image/list.go @@ -30,6 +30,7 @@ import ( "time" "github.com/docker/go-units" + "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/identity" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -44,6 +45,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/containerdutil" "github.com/containerd/nerdctl/v2/pkg/formatter" "github.com/containerd/nerdctl/v2/pkg/imgutil" + "github.com/containerd/nerdctl/v2/pkg/referenceutil" ) // ListCommandHandler `List` and print images matching filters in `options`. @@ -128,6 +130,46 @@ type imagePrintable struct { func printImages(ctx context.Context, client *containerd.Client, imageList []images.Image, options *types.ImageListOptions) error { w := options.Stdout + var finalImageList []images.Image + /* + the same imageId under k8s.io is showing multiple results: repo:tag, repo:digest, configID. + We expect to display only repo:tag, consistent with other namespaces and CRI + e.g. + nerdctl -n k8s.io images + REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE + centos 7 be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB + centos be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB + be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB + expect: + nerdctl --kube-hide-dupe -n k8s.io images + REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE + centos 7 be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB + */ + if options.GOptions.KubeHideDupe && options.GOptions.Namespace == "k8s.io" { + imageDigest := make(map[digest.Digest]bool) + var imageNoTag []images.Image + for _, img := range imageList { + parsed, err := referenceutil.Parse(img.Name) + if err != nil { + continue + } + if parsed.Tag != "" { + finalImageList = append(finalImageList, img) + imageDigest[img.Target.Digest] = true + continue + } + imageNoTag = append(imageNoTag, img) + } + //Ensure that dangling images without a repo:tag are displayed correctly. + for _, ima := range imageNoTag { + if !imageDigest[ima.Target.Digest] { + finalImageList = append(finalImageList, ima) + imageDigest[ima.Target.Digest] = true + } + } + } else { + finalImageList = imageList + } digestsFlag := options.Digests if options.Format == "wide" { digestsFlag = true @@ -174,7 +216,7 @@ func printImages(ctx context.Context, client *containerd.Client, imageList []ima snapshotter: containerdutil.SnapshotService(client, options.GOptions.Snapshotter), } - for _, img := range imageList { + for _, img := range finalImageList { if err := printer.printImage(ctx, img); err != nil { log.G(ctx).Warn(err) } diff --git a/pkg/cmd/image/remove.go b/pkg/cmd/image/remove.go index 8075a928659..6b9f78fd757 100644 --- a/pkg/cmd/image/remove.go +++ b/pkg/cmd/image/remove.go @@ -111,12 +111,64 @@ func Remove(ctx context.Context, client *containerd.Client, args []string, optio } return nil }, + OnFoundCriRm: func(ctx context.Context, found imagewalker.Found) (bool, error) { + if found.NameMatchIndex == -1 { + // if found multiple images, return error unless in force-mode and + // there is only 1 unique image. + if found.MatchCount > 1 && !(options.Force && found.UniqueImages == 1) { + return false, fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + } + } else if found.NameMatchIndex != found.MatchIndex { + // when there is an image with a name matching the argument but the argument is a digest short id, + // the deletion process is not performed. + return false, nil + } + + if cid, ok := runningImages[found.Image.Name]; ok { + if options.Force { + if err = is.Delete(ctx, found.Image.Name); err != nil { + return false, err + } + fmt.Fprintf(options.Stdout, "Untagged: %s\n", found.Image.Name) + fmt.Fprintf(options.Stdout, "Untagged: %s\n", found.Image.Target.Digest.String()) + + found.Image.Name = ":" + if _, err = is.Create(ctx, found.Image); err != nil { + return false, err + } + return false, nil + } + return false, fmt.Errorf("conflict: unable to delete %s (cannot be forced) - image is being used by running container %s", found.Req, cid) + } + if cid, ok := usedImages[found.Image.Name]; ok && !options.Force { + return false, fmt.Errorf("conflict: unable to delete %s (must be forced) - image is being used by stopped container %s", found.Req, cid) + } + // digests is used only for emulating human-readable output of `docker rmi` + digests, err := found.Image.RootFS(ctx, cs, platforms.DefaultStrict()) + if err != nil { + log.G(ctx).WithError(err).Warning("failed to enumerate rootfs") + } + + if err := is.Delete(ctx, found.Image.Name, delOpts...); err != nil { + return false, err + } + fmt.Fprintf(options.Stdout, "Untagged: %s@%s\n", found.Image.Name, found.Image.Target.Digest) + for _, digest := range digests { + fmt.Fprintf(options.Stdout, "Deleted: %s\n", digest) + } + return true, nil + }, } var errs []string var fatalErr bool for _, req := range args { - n, err := walker.Walk(ctx, req) + var n int + if options.GOptions.KubeHideDupe && options.GOptions.Namespace == "k8s.io" { + n, err = walker.WalkCriRm(ctx, req) + } else { + n, err = walker.Walk(ctx, req) + } if err != nil { fatalErr = true } diff --git a/pkg/config/config.go b/pkg/config/config.go index e37e9e0134c..1666ab61a0e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -40,6 +40,7 @@ type Config struct { Experimental bool `toml:"experimental"` HostGatewayIP string `toml:"host_gateway_ip"` BridgeIP string `toml:"bridge_ip, omitempty"` + KubeHideDupe bool `toml:"kube_hide_dupe"` } // New creates a default Config object statically, @@ -59,5 +60,6 @@ func New() *Config { HostsDir: ncdefaults.HostsDirs(), Experimental: true, HostGatewayIP: ncdefaults.HostGatewayIP(), + KubeHideDupe: false, } } diff --git a/pkg/idutil/imagewalker/imagewalker.go b/pkg/idutil/imagewalker/imagewalker.go index 4103711ed91..c99cdb8b432 100644 --- a/pkg/idutil/imagewalker/imagewalker.go +++ b/pkg/idutil/imagewalker/imagewalker.go @@ -41,9 +41,28 @@ type Found struct { type OnFound func(ctx context.Context, found Found) error +/* +In order to resolve the issue with OnFoundCriRm, the same imageId under +k8s.io is showing multiple results: repo:tag, repo:digest, configID. We expect +to display only repo:tag, consistent with other namespaces and CRI. +e.g. + + nerdctl -n k8s.io images + REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE + centos 7 be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB + centos be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB + be65f488b776 3 hours ago linux/amd64 211.5 MiB 72.6 MiB + +The boolean value will return true only when the repo:tag is successfully +deleted for each image. Once all repo:tag entries are deleted, it is necessary +to clean up the remaining repo:digest and configID. +*/ +type OnFoundCriRm func(ctx context.Context, found Found) (bool, error) + type ImageWalker struct { - Client *containerd.Client - OnFound OnFound + Client *containerd.Client + OnFound OnFound + OnFoundCriRm OnFoundCriRm } // Walk walks images and calls w.OnFound . @@ -98,6 +117,103 @@ func (w *ImageWalker) Walk(ctx context.Context, req string) (int, error) { return matchCount, nil } +// WalkCriRm walks images and calls w.OnFoundCriRm . +// Only effective when in the k8s.io namespace and kube-hide-dupe is enabled. +// The WalkCriRm deletes non-repo:tag items such as repo:digest when in the no-other-repo:tag scenario. +func (w *ImageWalker) WalkCriRm(ctx context.Context, req string) (int, error) { + var filters []string + var parsedReferenceStr, repo string + var imageTag, imagesRepo []images.Image + var tagNum int + + parsedReference, err := referenceutil.Parse(req) + if err == nil { + parsedReferenceStr = parsedReference.String() + filters = append(filters, fmt.Sprintf("name==%s", parsedReferenceStr)) + } + //Get the image ID , if reg == imageTag use + image, err := w.Client.GetImage(ctx, parsedReferenceStr) + if err != nil { + repo = req + } else { + repo = strings.Split(image.Target().Digest.String(), ":")[1][:12] + } + + filters = append(filters, + fmt.Sprintf("name==%s", req), + fmt.Sprintf("target.digest~=^sha256:%s.*$", regexp.QuoteMeta(repo)), + fmt.Sprintf("target.digest~=^%s.*$", regexp.QuoteMeta(repo)), + ) + + images, err := w.Client.ImageService().List(ctx, filters...) + if err != nil { + return -1, err + } + + // to handle the `rmi -f` case where returned images are different but + // have the same short prefix. + uniqueImages := make(map[digest.Digest]bool) + nameMatchIndex := -1 + + //Distinguish between tag and non-tag + for _, img := range images { + ref := img.Name + parsed, err := referenceutil.Parse(ref) + if err != nil { + continue + } + if parsed.Tag != "" { + imageTag = append(imageTag, img) + tagNum++ + uniqueImages[img.Target.Digest] = true + // to get target image index for `nerdctl rmi `. + if (parsedReferenceStr != "" && img.Name == parsedReferenceStr) || img.Name == req { + nameMatchIndex = len(imageTag) - 1 + } + } else { + imagesRepo = append(imagesRepo, img) + } + } + + matchCount := len(imageTag) + if matchCount < 1 && len(imagesRepo) > 0 { + matchCount = 1 + } + + for i, img := range imageTag { + f := Found{ + Image: img, + Req: req, + MatchIndex: i, + MatchCount: matchCount, + UniqueImages: len(uniqueImages), + NameMatchIndex: nameMatchIndex, + } + if ok, e := w.OnFoundCriRm(ctx, f); e != nil { + return -1, e + } else if ok { + tagNum = tagNum - 1 + } + } + //If the corresponding imageTag does not exist, delete the repoDigests + if tagNum == 0 { + for i, img := range imagesRepo { + f := Found{ + Image: img, + Req: req, + MatchIndex: i, + MatchCount: 1, + UniqueImages: 1, + NameMatchIndex: -1, + } + if _, e := w.OnFoundCriRm(ctx, f); e != nil { + return -1, e + } + } + } + return matchCount, nil +} + // WalkAll calls `Walk` for each req in `reqs`. // // It can be used when the matchCount is not important (e.g., only care if there From 75c8066343a11001377ddfcd003fe796f87c7b94 Mon Sep 17 00:00:00 2001 From: ningmingxiao Date: Thu, 19 Dec 2024 20:03:49 +0800 Subject: [PATCH 1006/1066] update:fix update pids-limit=0 error Signed-off-by: ningmingxiao --- .../container_run_cgroup_linux_test.go | 51 +++++++++++++++++++ cmd/nerdctl/container/container_update.go | 24 +++++---- 2 files changed, 65 insertions(+), 10 deletions(-) diff --git a/cmd/nerdctl/container/container_run_cgroup_linux_test.go b/cmd/nerdctl/container/container_run_cgroup_linux_test.go index 8b423d970ba..c4b5c77de7c 100644 --- a/cmd/nerdctl/container/container_run_cgroup_linux_test.go +++ b/cmd/nerdctl/container/container_run_cgroup_linux_test.go @@ -18,6 +18,7 @@ package container import ( "bytes" + "context" "fmt" "os" "path/filepath" @@ -27,11 +28,14 @@ import ( "gotest.tools/v3/assert" "github.com/containerd/cgroups/v3" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/continuity/testutil/loopback" "github.com/containerd/nerdctl/v2/pkg/cmd/container" + "github.com/containerd/nerdctl/v2/pkg/idutil/containerwalker" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func TestRunCgroupV2(t *testing.T) { @@ -170,6 +174,53 @@ func TestRunCgroupV1(t *testing.T) { base.Cmd("run", "--rm", "--cpu-quota", "42000", "--cpu-period", "100000", "--cpuset-mems", "0", "--memory", "42m", "--memory-reservation", "6m", "--memory-swap", "100m", "--memory-swappiness", "0", "--pids-limit", "42", "--cpu-shares", "2000", "--cpuset-cpus", "0-1", testutil.AlpineImage, "cat", quota, period, cpusetMems, memoryLimit, memoryReservation, memorySwap, memorySwappiness, pidsLimit, cpuShare, cpusetCpus).AssertOutExactly(expected) } +// TestIssue3781 tests https://github.com/containerd/nerdctl/issues/3781 +func TestIssue3781(t *testing.T) { + t.Parallel() + testCase := nerdtest.Setup() + testCase.Require = test.Not(nerdtest.Docker) + + base := testutil.NewBase(t) + info := base.Info() + switch info.CgroupDriver { + case "none", "": + t.Skip("test requires cgroup driver") + } + containerName := testutil.Identifier(t) + base.Cmd("run", "-d", "--name", containerName, testutil.AlpineImage, "sleep", "infinity").AssertOK() + defer func() { + base.Cmd("rm", "-f", containerName) + }() + base.Cmd("update", "--cpuset-cpus", "0-1", containerName).AssertOK() + addr := base.ContainerdAddress() + client, err := containerd.New(addr, containerd.WithDefaultNamespace(testutil.Namespace)) + assert.NilError(base.T, err) + ctx := context.Background() + + // get container id by container name. + var cid string + var args []string + args = append(args, containerName) + walker := &containerwalker.ContainerWalker{ + Client: client, + OnFound: func(ctx context.Context, found containerwalker.Found) error { + if found.MatchCount > 1 { + return fmt.Errorf("multiple IDs found with provided prefix: %s", found.Req) + } + cid = found.Container.ID() + return nil + }, + } + err = walker.WalkAll(ctx, args, true) + assert.NilError(base.T, err) + + container, err := client.LoadContainer(ctx, cid) + assert.NilError(base.T, err) + spec, err := container.Spec(ctx) + assert.NilError(base.T, err) + assert.Equal(t, spec.Linux.Resources.Pids == nil, true) +} + func TestRunDevice(t *testing.T) { if os.Geteuid() != 0 || userns.RunningInUserNS() { t.Skip("test requires the root in the initial user namespace") diff --git a/cmd/nerdctl/container/container_update.go b/cmd/nerdctl/container/container_update.go index 15c8e6526ef..c1805608b7a 100644 --- a/cmd/nerdctl/container/container_update.go +++ b/cmd/nerdctl/container/container_update.go @@ -266,16 +266,18 @@ func updateContainer(ctx context.Context, client *containerd.Client, id string, if spec.Linux.Resources == nil { spec.Linux.Resources = &runtimespec.LinuxResources{} } - if spec.Linux.Resources.BlockIO == nil { - spec.Linux.Resources.BlockIO = &runtimespec.LinuxBlockIO{} - } if cmd.Flags().Changed("blkio-weight") { + if spec.Linux.Resources.BlockIO == nil { + spec.Linux.Resources.BlockIO = &runtimespec.LinuxBlockIO{} + } if spec.Linux.Resources.BlockIO.Weight != &opts.BlkioWeight { spec.Linux.Resources.BlockIO.Weight = &opts.BlkioWeight } } - if spec.Linux.Resources.CPU == nil { - spec.Linux.Resources.CPU = &runtimespec.LinuxCPU{} + if cmd.Flags().Changed("cpu-shares") || cmd.Flags().Changed("cpu-quota") || cmd.Flags().Changed("cpu-period") || cmd.Flags().Changed("cpus") || cmd.Flags().Changed("cpuset-mems") || cmd.Flags().Changed("cpuset-cpus") { + if spec.Linux.Resources.CPU == nil { + spec.Linux.Resources.CPU = &runtimespec.LinuxCPU{} + } } if cmd.Flags().Changed("cpu-shares") { if spec.Linux.Resources.CPU.Shares != &opts.CPUShares { @@ -308,8 +310,10 @@ func updateContainer(ctx context.Context, client *containerd.Client, id string, spec.Linux.Resources.CPU.Cpus = opts.CpusetCpus } } - if spec.Linux.Resources.Memory == nil { - spec.Linux.Resources.Memory = &runtimespec.LinuxMemory{} + if cmd.Flags().Changed("memory") || cmd.Flags().Changed("memory-reservation") { + if spec.Linux.Resources.Memory == nil { + spec.Linux.Resources.Memory = &runtimespec.LinuxMemory{} + } } if cmd.Flags().Changed("memory") { if spec.Linux.Resources.Memory.Limit != &opts.MemoryLimitInBytes { @@ -324,10 +328,10 @@ func updateContainer(ctx context.Context, client *containerd.Client, id string, spec.Linux.Resources.Memory.Reservation = &opts.MemoryReservation } } - if spec.Linux.Resources.Pids == nil { - spec.Linux.Resources.Pids = &runtimespec.LinuxPids{} - } if cmd.Flags().Changed("pids-limit") { + if spec.Linux.Resources.Pids == nil { + spec.Linux.Resources.Pids = &runtimespec.LinuxPids{} + } if spec.Linux.Resources.Pids.Limit != opts.PidsLimit { spec.Linux.Resources.Pids.Limit = opts.PidsLimit } From aa5eb28ade74afcd6ff1cd29ae3b937d5fd62652 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Thu, 26 Dec 2024 22:40:31 -0700 Subject: [PATCH 1007/1066] Fix image inspect exit code on image not found error This change fixes image inspect command to error when image is not found. Signed-off-by: Austin Vazquez --- cmd/nerdctl/image/image_inspect_test.go | 16 ++++++++++++++-- cmd/nerdctl/ipfs/ipfs_simple_linux_test.go | 6 ++++-- pkg/cmd/image/inspect.go | 10 +++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/cmd/nerdctl/image/image_inspect_test.go b/cmd/nerdctl/image/image_inspect_test.go index 4ac86996bd8..808fd199d46 100644 --- a/cmd/nerdctl/image/image_inspect_test.go +++ b/cmd/nerdctl/image/image_inspect_test.go @@ -18,6 +18,8 @@ package image import ( "encoding/json" + "errors" + "fmt" "runtime" "strings" "testing" @@ -61,6 +63,14 @@ func TestImageInspectSimpleCases(t *testing.T) { Command: test.Command("image", "inspect", testutil.CommonImage, "--format", "{{.ID}}"), Expected: test.Expects(0, nil, nil), }, + { + Description: "Error for image not found", + Command: test.Command("image", "inspect", "dne:latest", "dne2:latest"), + Expected: test.Expects(1, []error{ + errors.New("no such image: dne:latest"), + errors.New("no such image: dne2:latest"), + }, nil), + }, }, } @@ -171,7 +181,8 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { for _, id := range []string{"doesnotexist", "doesnotexist:either", "busybox:bogustag"} { cmd := helpers.Command("image", "inspect", id+"@sha256:"+sha) cmd.Run(&test.Expected{ - Output: test.Equals(""), + ExitCode: 1, + Errors: []error{fmt.Errorf("no such image: %s@sha256:%s", id, sha)}, }) } }, @@ -192,7 +203,8 @@ func TestImageInspectDifferentValidReferencesForTheSameImage(t *testing.T) { for _, id := range []string{"∞∞∞∞∞∞∞∞∞∞", "busybox:∞∞∞∞∞∞∞∞∞∞"} { cmd := helpers.Command("image", "inspect", id) cmd.Run(&test.Expected{ - Output: test.Equals(""), + ExitCode: 1, + Errors: []error{fmt.Errorf("invalid reference format: %s", id)}, }) } }, diff --git a/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go b/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go index f2d59a15618..48bc874049b 100644 --- a/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go +++ b/cmd/nerdctl/ipfs/ipfs_simple_linux_test.go @@ -175,11 +175,13 @@ func TestIPFSSimple(t *testing.T) { helpers.Ensure("image", "encrypt", "--recipient=jwe:"+keyPair.Pub, data.Get(mainImageCIDKey), data.Identifier("encrypted")) cmd := helpers.Command("image", "inspect", "--mode=native", "--format={{len .Index.Manifests}}", data.Identifier("encrypted")) cmd.Run(&test.Expected{ - Output: test.Equals("1\n"), + ExitCode: 1, + Output: test.Equals("1\n"), }) cmd = helpers.Command("image", "inspect", "--mode=native", "--format={{json (index .Manifest.Layers 0) }}", data.Identifier("encrypted")) cmd.Run(&test.Expected{ - Output: test.Contains("org.opencontainers.image.enc.keys.jwe"), + ExitCode: 1, + Output: test.Contains("org.opencontainers.image.enc.keys.jwe"), }) // Push the encrypted image and save the CID diff --git a/pkg/cmd/image/inspect.go b/pkg/cmd/image/inspect.go index 1627cc4b14d..ec96ddb7cba 100644 --- a/pkg/cmd/image/inspect.go +++ b/pkg/cmd/image/inspect.go @@ -18,6 +18,7 @@ package image import ( "context" + "errors" "fmt" "regexp" "strings" @@ -97,6 +98,7 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin defer cancel() // Will hold the final answers + var errs []error var entries []interface{} snapshotter := containerdutil.SnapshotService(client, options.GOptions.Snapshotter) @@ -104,7 +106,7 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin for _, identifier := range identifiers { candidateImageList, requestedName, requestedTag, err := inspectIdentifier(ctx, client, identifier) if err != nil { - log.G(ctx).WithError(err).WithField("identifier", identifier).Error("failure calling inspect") + errs = append(errs, fmt.Errorf("%w: %s", err, identifier)) continue } @@ -185,6 +187,8 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin // Store our image // foundImages[validatedDigest] = validatedImage entries = append(entries, validatedImage) + } else { + errs = append(errs, fmt.Errorf("no such image: %s", identifier)) } } @@ -195,5 +199,9 @@ func Inspect(ctx context.Context, client *containerd.Client, identifiers []strin } } + if len(errs) > 0 { + return fmt.Errorf("%d errors:\n%w", len(errs), errors.Join(errs...)) + } + return nil } From 842be9a2576325270b8eadc6fb8656bb65891513 Mon Sep 17 00:00:00 2001 From: Pedro Aibar <75799784+motinsa@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:27:23 +0100 Subject: [PATCH 1008/1066] Refactor: Encapsulate net opts loading in internalLabels Signed-off-by: Pedro Aibar <75799784+motinsa@users.noreply.github.com> --- pkg/cmd/container/create.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 37d625b1da5..1829d6681df 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -248,13 +248,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa envs = append(envs, "HOSTNAME="+netLabelOpts.Hostname) opts = append(opts, oci.WithEnv(envs)) - // TODO(aznashwan): more formal way to load net opts into internalLabels: - internalLabels.hostname = netLabelOpts.Hostname - internalLabels.ports = netLabelOpts.PortMappings - internalLabels.ipAddress = netLabelOpts.IPAddress - internalLabels.ip6Address = netLabelOpts.IP6Address - internalLabels.networks = netLabelOpts.NetworkSlice - internalLabels.macAddress = netLabelOpts.MACAddress + internalLabels.LoadNetOpts(netLabelOpts) // NOTE: OCI hooks are currently not supported on Windows so we skip setting them altogether. // The OCI hooks we define (whose logic can be found in pkg/ocihook) primarily @@ -732,6 +726,16 @@ func withInternalLabels(internalLabels internalLabels) (containerd.NewContainerO return containerd.WithAdditionalContainerLabels(m), nil } +// LoadNetOpts loads network options into InternalLabels. +func (il *internalLabels) LoadNetOpts(opts types.NetworkOptions) { + il.hostname = opts.Hostname + il.ports = opts.PortMappings + il.ipAddress = opts.IPAddress + il.ip6Address = opts.IP6Address + il.networks = opts.NetworkSlice + il.macAddress = opts.MACAddress +} + func dockercompatMounts(mountPoints []*mountutil.Processed) []dockercompat.MountPoint { result := make([]dockercompat.MountPoint, len(mountPoints)) for i := range mountPoints { From d6248ac109cde6dd057e66d7d3268d3d94353c56 Mon Sep 17 00:00:00 2001 From: Pedro Aibar <75799784+motinsa@users.noreply.github.com> Date: Thu, 2 Jan 2025 08:12:53 +0000 Subject: [PATCH 1009/1066] Refactor: Change function loadNetOpts from public to private Signed-off-by: Pedro Aibar --- pkg/cmd/container/create.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 1829d6681df..77b5656e098 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -248,7 +248,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa envs = append(envs, "HOSTNAME="+netLabelOpts.Hostname) opts = append(opts, oci.WithEnv(envs)) - internalLabels.LoadNetOpts(netLabelOpts) + internalLabels.loadNetOpts(netLabelOpts) // NOTE: OCI hooks are currently not supported on Windows so we skip setting them altogether. // The OCI hooks we define (whose logic can be found in pkg/ocihook) primarily @@ -726,8 +726,8 @@ func withInternalLabels(internalLabels internalLabels) (containerd.NewContainerO return containerd.WithAdditionalContainerLabels(m), nil } -// LoadNetOpts loads network options into InternalLabels. -func (il *internalLabels) LoadNetOpts(opts types.NetworkOptions) { +// loadNetOpts loads network options into InternalLabels. +func (il *internalLabels) loadNetOpts(opts types.NetworkOptions) { il.hostname = opts.Hostname il.ports = opts.PortMappings il.ipAddress = opts.IPAddress From 1a79790b8004d42882a4fc7e1922430ba7fb4cbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 22:56:38 +0000 Subject: [PATCH 1010/1066] build(deps): bump github.com/moby/term from 0.5.0 to 0.5.2 Bumps [github.com/moby/term](https://github.com/moby/term) from 0.5.0 to 0.5.2. - [Commits](https://github.com/moby/term/compare/v0.5.0...v0.5.2) --- updated-dependencies: - dependency-name: github.com/moby/term dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 27f7b595d20..268a010c304 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/moby/sys/mountinfo v0.7.2 github.com/moby/sys/signal v0.7.1 github.com/moby/sys/userns v0.1.0 - github.com/moby/term v0.5.0 + github.com/moby/term v0.5.2 github.com/muesli/cancelreader v0.2.2 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.0 @@ -78,7 +78,7 @@ require ( require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/cilium/ebpf v0.16.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect diff --git a/go.sum b/go.sum index 113975c346f..1827f922e60 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8af github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= +github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -220,8 +220,8 @@ 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/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= +github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= From b0e78eeeca2ff0ca8d35457d409075657ef2c597 Mon Sep 17 00:00:00 2001 From: Jin Dong Date: Tue, 7 Jan 2025 03:10:55 +0000 Subject: [PATCH 1011/1066] update CNI plugins (1.6.2) Signed-off-by: Jin Dong --- Dockerfile | 42 ++++++++++---------- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.2 | 2 + 2 files changed, 23 insertions(+), 21 deletions(-) create mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.2 diff --git a/Dockerfile b/Dockerfile index e7870b673a2..f4d0dcc511c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ # Basic deps ARG CONTAINERD_VERSION=v2.0.1 ARG RUNC_VERSION=v1.2.3 -ARG CNI_PLUGINS_VERSION=v1.6.1 +ARG CNI_PLUGINS_VERSION=v1.6.2 # Extra deps: Build ARG BUILDKIT_VERSION=v0.18.2 @@ -57,18 +57,18 @@ FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bookworm AS build-base-debia COPY --from=xx / / ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update -qq && apt-get install -qq --no-install-recommends \ - git \ - dpkg-dev + git \ + dpkg-dev ARG TARGETARCH # libbtrfs: for containerd # libseccomp: for runc and bypass4netns RUN xx-apt-get update -qq && xx-apt-get install -qq --no-install-recommends \ - binutils \ - gcc \ - libc6-dev \ - libbtrfs-dev \ - libseccomp-dev \ - pkg-config + binutils \ + gcc \ + libc6-dev \ + libbtrfs-dev \ + libseccomp-dev \ + pkg-config RUN git config --global advice.detachedHead false FROM build-base-debian AS build-containerd @@ -246,12 +246,12 @@ COPY --from=build-full /out / FROM ubuntu:${UBUNTU_VERSION} AS base # fuse3 is required by stargz snapshotter RUN apt-get update -qq && apt-get install -qq -y --no-install-recommends \ - apparmor \ - bash-completion \ - ca-certificates curl \ - iproute2 iptables \ - dbus dbus-user-session systemd systemd-sysv \ - fuse3 + apparmor \ + bash-completion \ + ca-certificates curl \ + iproute2 iptables \ + dbus dbus-user-session systemd systemd-sysv \ + fuse3 ARG CONTAINERIZED_SYSTEMD_VERSION RUN curl -o /docker-entrypoint.sh -fsSL --proto '=https' --tlsv1.2 https://raw.githubusercontent.com/AkihiroSuda/containerized-systemd/${CONTAINERIZED_SYSTEMD_VERSION}/docker-entrypoint.sh && \ chmod +x /docker-entrypoint.sh @@ -278,9 +278,9 @@ FROM base AS test-integration ARG DEBIAN_FRONTEND=noninteractive # `expect` package contains `unbuffer(1)`, which is used for emulating TTY for testing RUN apt-get update -qq && apt-get install -qq --no-install-recommends \ - expect \ - git \ - make + expect \ + git \ + make COPY --from=goversion /GOVERSION /GOVERSION ARG TARGETARCH RUN curl -fsSL --proto '=https' --tlsv1.2 https://golang.org/dl/$(cat /GOVERSION).linux-${TARGETARCH:-amd64}.tar.gz | tar xzvC /usr/local @@ -325,9 +325,9 @@ FROM test-integration AS test-integration-rootless # (`sudo` does not work for this purpose, # OTOH `machinectl shell` can create the session but does not propagate exit code) RUN apt-get update -qq && apt-get install -qq --no-install-recommends \ - uidmap \ - openssh-server \ - openssh-client + uidmap \ + openssh-server \ + openssh-client # 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 && \ diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.2 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.2 new file mode 100644 index 00000000000..109168fb84f --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.2 @@ -0,0 +1,2 @@ +b8e811578fb66023f90d2e238d80cec3bdfca4b44049af74c374d4fae0f9c090 cni-plugins-linux-amd64-v1.6.2.tgz +01e0e22acc7f7004e4588c1fe1871cc86d7ab562cd858e1761c4641d89ebfaa4 cni-plugins-linux-arm64-v1.6.2.tgz From 8a1fd9ebec78df9ff066cc2da01c7c82d5d5d290 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Jan 2025 12:48:06 +0000 Subject: [PATCH 1012/1066] build(deps): bump the golang-x group with 4 updates Bumps the golang-x group with 4 updates: [golang.org/x/crypto](https://github.com/golang/crypto), [golang.org/x/net](https://github.com/golang/net), [golang.org/x/sys](https://github.com/golang/sys) and [golang.org/x/term](https://github.com/golang/term). Updates `golang.org/x/crypto` from 0.31.0 to 0.32.0 - [Commits](https://github.com/golang/crypto/compare/v0.31.0...v0.32.0) Updates `golang.org/x/net` from 0.33.0 to 0.34.0 - [Commits](https://github.com/golang/net/compare/v0.33.0...v0.34.0) Updates `golang.org/x/sys` from 0.28.0 to 0.29.0 - [Commits](https://github.com/golang/sys/compare/v0.28.0...v0.29.0) Updates `golang.org/x/term` from 0.27.0 to 0.28.0 - [Commits](https://github.com/golang/term/compare/v0.27.0...v0.28.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 14 ++++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 268a010c304..2f84431a5bf 100644 --- a/go.mod +++ b/go.mod @@ -65,11 +65,11 @@ require ( github.com/vishvananda/netns v0.0.5 github.com/yuchanns/srslog v1.1.0 go.uber.org/mock v0.5.0 - golang.org/x/crypto v0.31.0 - golang.org/x/net v0.33.0 + golang.org/x/crypto v0.32.0 + golang.org/x/net v0.34.0 golang.org/x/sync v0.10.0 - golang.org/x/sys v0.28.0 - golang.org/x/term v0.27.0 + golang.org/x/sys v0.29.0 + golang.org/x/term v0.28.0 golang.org/x/text v0.21.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 diff --git a/go.sum b/go.sum index 1827f922e60..da5dea24f80 100644 --- a/go.sum +++ b/go.sum @@ -345,8 +345,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= @@ -378,8 +378,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -416,8 +416,9 @@ golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -426,8 +427,9 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= +golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= From fa3a4fa5e529c537dcbe1dad9429e4dddebf4565 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Tue, 7 Jan 2025 16:58:40 +0000 Subject: [PATCH 1013/1066] update runc (1.2.4) Signed-off-by: Austin Vazquez --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f4d0dcc511c..c2afffcecc1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ # Basic deps ARG CONTAINERD_VERSION=v2.0.1 -ARG RUNC_VERSION=v1.2.3 +ARG RUNC_VERSION=v1.2.4 ARG CNI_PLUGINS_VERSION=v1.6.2 # Extra deps: Build From 9ef95396f52c03a87c824f6ae63f3033d1a7797c Mon Sep 17 00:00:00 2001 From: Jin Dong Date: Tue, 7 Jan 2025 17:22:34 +0000 Subject: [PATCH 1014/1066] remove old cni 1.6.1 checksum file Signed-off-by: Jin Dong --- Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.1 | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.1 diff --git a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.1 b/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.1 deleted file mode 100644 index 30c484f29a2..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/cni-plugins-v1.6.1 +++ /dev/null @@ -1,2 +0,0 @@ -2503ce29ac445715ebe146073f45468153f9e28f45fa173cb060cfd9e735f563 cni-plugins-linux-amd64-v1.6.1.tgz -f0f440b968ab50ad13d9d42d993ba98ec30b2ec666846f4ef1bddc7646a701cc cni-plugins-linux-arm64-v1.6.1.tgz From 25ca6680091ed9394a9e068a6da39f8a6b1324b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Jan 2025 22:48:49 +0000 Subject: [PATCH 1015/1066] build(deps): bump github.com/compose-spec/compose-go/v2 Bumps [github.com/compose-spec/compose-go/v2](https://github.com/compose-spec/compose-go) from 2.4.6 to 2.4.7. - [Release notes](https://github.com/compose-spec/compose-go/releases) - [Commits](https://github.com/compose-spec/compose-go/compare/v2.4.6...v2.4.7) --- updated-dependencies: - dependency-name: github.com/compose-spec/compose-go/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2f84431a5bf..162bae8724f 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/Masterminds/semver/v3 v3.3.1 github.com/Microsoft/go-winio v0.6.2 github.com/Microsoft/hcsshim v0.12.9 - github.com/compose-spec/compose-go/v2 v2.4.6 + github.com/compose-spec/compose-go/v2 v2.4.7 github.com/containerd/accelerated-container-image v1.2.3 github.com/containerd/cgroups/v3 v3.0.5 github.com/containerd/console v1.0.4 diff --git a/go.sum b/go.sum index da5dea24f80..191ee58a82f 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok= github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/compose-spec/compose-go/v2 v2.4.6 h1:QiqXQ2L/f0OCbAl41bPpeiGAWVRIQ+GEDrYxO+dRPhQ= -github.com/compose-spec/compose-go/v2 v2.4.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= +github.com/compose-spec/compose-go/v2 v2.4.7 h1:WNpz5bIbKG+G+w9pfu72B1ZXr+Og9jez8TMEo8ecXPk= +github.com/compose-spec/compose-go/v2 v2.4.7/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/accelerated-container-image v1.2.3 h1:tAIoP7Z7b2xGhb7QCM5Fa+2xqWfPqRmyi5lodbsGGRA= github.com/containerd/accelerated-container-image v1.2.3/go.mod h1:EvKVWor6ZQNUyYp0MZm5hw4k21ropuz7EegM+m/Jb/Q= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= From 690bbbfeecf8dac856c91af8708688f7fb33d1ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Jan 2025 22:38:29 +0000 Subject: [PATCH 1016/1066] build(deps): bump docker/setup-qemu-action from 3.2.0 to 3.3.0 Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/49b3bc8e6bdd4a60e6116a5414239cba5943d3cf...53851d14592bedcffcf25ea515637cff71ef929a) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 0eb8331875f..57475d3bfe6 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -34,7 +34,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up QEMU - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 + uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3.3.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0 From 6ea730678bfc8238ec73beda2e7f7f4600195eb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Jan 2025 22:38:32 +0000 Subject: [PATCH 1017/1066] build(deps): bump docker/build-push-action from 6.10.0 to 6.11.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.10.0 to 6.11.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/48aba3b46d1b1fec4febb7c5d0c644b249a11355...b32b51a8eda65d6793cd0494a773d4f6bcef32dc) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 0eb8331875f..9603e903af6 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -60,7 +60,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 + uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0 with: context: . platforms: linux/amd64,linux/arm64 From 74e00af48f3eeff1aa51194a0e27ee1d519c91bc Mon Sep 17 00:00:00 2001 From: Jin Dong Date: Sat, 11 Jan 2025 19:50:30 +0000 Subject: [PATCH 1018/1066] bump up github.com/containerd/go-cni to 1.1.12 Signed-off-by: Jin Dong --- go.mod | 4 +++- go.sum | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 162bae8724f..4a4c0c83174 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/containerd/continuity v0.4.5 github.com/containerd/errdefs v1.0.0 github.com/containerd/fifo v1.1.0 - github.com/containerd/go-cni v1.1.11 + github.com/containerd/go-cni v1.1.12 github.com/containerd/imgcrypt/v2 v2.0.0 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.15.0 @@ -118,8 +118,10 @@ require ( github.com/multiformats/go-varint v0.0.7 // indirect github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect github.com/opencontainers/selinux v1.11.1 // indirect + github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/sasha-s/go-deadlock v0.3.5 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smallstep/pkcs7 v0.1.1 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect diff --git a/go.sum b/go.sum index 191ee58a82f..2aa344edf62 100644 --- a/go.sum +++ b/go.sum @@ -43,8 +43,8 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= 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.11 h1:fWt1K15AmSLsEfa57N+qYw4NeGPiQKYq1pjNGJwV9mc= -github.com/containerd/go-cni v1.1.11/go.mod h1:/Y/sL8yqYQn1ZG1om1OncJB1W4zN3YmjfP/ShCzG/OY= +github.com/containerd/go-cni v1.1.12 h1:wm/5VD/i255hjM4uIZjBRiEQ7y98W9ACy/mHeLi4+94= +github.com/containerd/go-cni v1.1.12/go.mod h1:+jaqRBdtW5faJxj2Qwg1Of7GsV66xcvnCx4mSJtUlxU= github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA= github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U= github.com/containerd/imgcrypt/v2 v2.0.0 h1:vd2ByN6cXeearzXCQljH1eYe77FgFO5/B9+dK14mng0= @@ -257,6 +257,8 @@ github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jD github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw= +github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -274,6 +276,8 @@ github.com/rootless-containers/bypass4netns v0.4.1/go.mod h1:slu3ygwy1x6ey78oBTN github.com/rootless-containers/rootlesskit/v2 v2.3.1 h1:wdYtdKxWFvVLby9ThMP6O6/v2q/GmOXbkRi+4m9nPW0= github.com/rootless-containers/rootlesskit/v2 v2.3.1/go.mod h1:tdtfS9ak4bGmwJRmcjsAzcHN5rJ3c5dB7yhSV10KTbk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= +github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= From 50dd735e04b56cd5d860007d56bfb250cca8fb62 Mon Sep 17 00:00:00 2001 From: Jin Dong Date: Sat, 11 Jan 2025 20:15:12 +0000 Subject: [PATCH 1019/1066] move vagrant CI to ubuntu 24.04 Signed-off-by: Jin Dong --- .github/workflows/test.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 29eb8273674..8be30236146 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -392,8 +392,7 @@ jobs: test-integration-freebsd: timeout-minutes: 30 name: FreeBSD - # ubuntu-24.04 lacks the vagrant package - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: @@ -404,9 +403,19 @@ jobs: key: vagrant-${{ matrix.box }} - name: Set up vagrant run: | + # from https://github.com/containerd/containerd/blob/v2.0.1/.github/workflows/ci.yml#L583-L596 + # which is based on https://github.com/opencontainers/runc/blob/v1.1.8/.cirrus.yml#L41-L49 + curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg + echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list + sudo sed -i 's/^Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/ubuntu.sources sudo apt-get update - sudo apt-get install -y libvirt-daemon libvirt-daemon-system vagrant vagrant-libvirt + sudo apt-get install -y libvirt-daemon libvirt-daemon-system vagrant ovmf + # https://github.com/vagrant-libvirt/vagrant-libvirt/issues/1725#issuecomment-1454058646 + sudo cp /usr/share/OVMF/OVMF_VARS_4M.fd /var/lib/libvirt/qemu/nvram/ sudo systemctl enable --now libvirtd + sudo apt-get build-dep -y ruby-libvirt + sudo apt-get install -y --no-install-recommends libxslt-dev libxml2-dev libvirt-dev ruby-bundler ruby-dev zlib1g-dev + sudo vagrant plugin install vagrant-libvirt - name: Boot VM run: | ln -sf Vagrantfile.freebsd Vagrantfile From 2ce9918b4183b25d19b19f60a90908bb8b7d6782 Mon Sep 17 00:00:00 2001 From: Yang Kaiyong Date: Mon, 13 Jan 2025 11:31:40 +0800 Subject: [PATCH 1020/1066] docs: Fix incorrect parameter description in documentation of nydus Signed-off-by: Yang Kaiyong --- docs/nydus.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/nydus.md b/docs/nydus.md index 338f09f1639..1019827a548 100644 --- a/docs/nydus.md +++ b/docs/nydus.md @@ -30,7 +30,7 @@ For the list of pre-converted Nydus images, see https://github.com/orgs/dragonfl Nerdctl supports to convert an OCI image or docker format v2 image to Nydus image by using the `nerdctl image convert` command. -Before the conversion, you should have the `nydus-image` binary installed, which is contained in the ["nydus static package"](https://github.com/dragonflyoss/image-service/releases). You can run the command like `nerdctl image convert --nydus --oci --nydus-image ` to convert the `` to a Nydus image whose tag is ``. +Before the conversion, you should have the `nydus-image` binary installed, which is contained in the ["nydus static package"](https://github.com/dragonflyoss/image-service/releases). You can run the command like `nerdctl image convert --nydus --oci --nydus-builder-path ` to convert the `` to a Nydus image whose tag is ``. By now, the converted Nydus image cannot be run directly. It shoud be unpacked to nydus snapshotter before `nerdctl run`, which is a part of the processing flow of `nerdctl image pull`. So you need to push the converted image to a registry after the conversion and use `nerdctl --snapshotter nydus image pull` to unpack it to the nydus snapshotter before running the image. From 6ab1907a0db170392c64ce6a541f656be75d9b01 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Fri, 10 Jan 2025 16:03:54 +0000 Subject: [PATCH 1021/1066] Update containerd (1.7.25) in CI Signed-off-by: Austin Vazquez --- .github/workflows/test-canary.yml | 2 +- .github/workflows/test.yml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index b222ad2120e..c178b907df4 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -81,7 +81,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: containerd/containerd - ref: "v1.7.24" + ref: "v1.7.25" path: containerd fetch-depth: 1 - name: "Set up CNI" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8be30236146..e13366fcaa4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: containerd: v1.6.36 arch: amd64 - runner: ubuntu-24.04 - containerd: v1.7.24 + containerd: v1.7.25 arch: amd64 - runner: ubuntu-24.04 containerd: v2.0.1 @@ -84,7 +84,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: containerd/containerd - ref: v1.7.24 + ref: v1.7.25 path: containerd fetch-depth: 1 - if: ${{ matrix.goos=='windows' }} @@ -109,7 +109,7 @@ jobs: runner: "ubuntu-20.04" arch: amd64 - ubuntu: 22.04 - containerd: v1.7.24 + containerd: v1.7.25 runner: "ubuntu-22.04" arch: amd64 - ubuntu: 24.04 @@ -234,7 +234,7 @@ jobs: target: rootless arch: amd64 - ubuntu: 22.04 - containerd: v1.7.24 + containerd: v1.7.25 rootlesskit: v2.3.1 target: rootless arch: amd64 @@ -244,7 +244,7 @@ jobs: target: rootless arch: amd64 - ubuntu: 24.04 - containerd: v1.7.24 + containerd: v1.7.25 rootlesskit: v2.3.1 target: rootless-port-slirp4netns arch: amd64 @@ -374,7 +374,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: containerd/containerd - ref: v1.7.24 + ref: v1.7.25 path: containerd fetch-depth: 1 - name: "Set up CNI" @@ -382,7 +382,7 @@ jobs: run: GOPATH=$(go env GOPATH) script/setup/install-cni-windows - name: "Set up containerd" env: - ctrdVersion: 1.7.24 + ctrdVersion: 1.7.25 run: powershell hack/configure-windows-ci.ps1 - name: "Run integration tests" run: ./hack/test-integration.sh -test.only-flaky=false From 5844e84f1460018990fdf3a37080607e24bc0936 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 22:38:19 +0000 Subject: [PATCH 1022/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.3.6 to 0.4.0. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Changelog](https://github.com/cyphar/filepath-securejoin/blob/main/CHANGELOG.md) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.3.6...v0.4.0) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4a4c0c83174..3bc2da5bff5 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.8.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.3.6 + github.com/cyphar/filepath-securejoin v0.4.0 github.com/distribution/reference v0.6.0 github.com/docker/cli v27.4.1+incompatible github.com/docker/docker v27.4.1+incompatible diff --git a/go.sum b/go.sum index 2aa344edf62..06dfe7693b3 100644 --- a/go.sum +++ b/go.sum @@ -80,8 +80,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= -github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/cyphar/filepath-securejoin v0.4.0 h1:PioTG9TBRSApBpYGnDU8HC+miIsX8vitBH9LGNNMoLQ= +github.com/cyphar/filepath-securejoin v0.4.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= From dfea78c98ede97ee17addee85221645142b75207 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 22:38:27 +0000 Subject: [PATCH 1023/1066] build(deps): bump github.com/containerd/platforms Bumps [github.com/containerd/platforms](https://github.com/containerd/platforms) from 1.0.0-rc.0 to 1.0.0-rc.1. - [Release notes](https://github.com/containerd/platforms/releases) - [Commits](https://github.com/containerd/platforms/compare/v1.0.0-rc.0...v1.0.0-rc.1) --- updated-dependencies: - dependency-name: github.com/containerd/platforms dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4a4c0c83174..db0430d857c 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/containerd/imgcrypt/v2 v2.0.0 github.com/containerd/log v0.1.0 github.com/containerd/nydus-snapshotter v0.15.0 - github.com/containerd/platforms v1.0.0-rc.0 + github.com/containerd/platforms v1.0.0-rc.1 github.com/containerd/stargz-snapshotter v0.16.3 github.com/containerd/stargz-snapshotter/estargz v0.16.3 github.com/containerd/stargz-snapshotter/ipfs v0.16.3 diff --git a/go.sum b/go.sum index 2aa344edf62..2267b6dbc42 100644 --- a/go.sum +++ b/go.sum @@ -53,8 +53,8 @@ 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.15.0 h1:RqZRs1GPeM6T3wmuxJV9u+2Rg4YETVMwTmiDeX+iWC8= github.com/containerd/nydus-snapshotter v0.15.0/go.mod h1:biq0ijpeZe0I5yZFSJyHzFSjjRZQ7P7y/OuHyd7hYOw= -github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA= -github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4= +github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E= +github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= github.com/containerd/stargz-snapshotter v0.16.3 h1:zbQMm8dRuPHEOD4OqAYGajJJUwCeUzt4j7w9Iaw58u4= From 251c56d406dfb1cb649530dea828b4919bb9e7df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 04:04:27 +0000 Subject: [PATCH 1024/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.4.1+incompatible to 27.5.0+incompatible - [Commits](https://github.com/docker/cli/compare/v27.4.1...v27.5.0) Updates `github.com/docker/docker` from 27.4.1+incompatible to 27.5.0+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.4.1...v27.5.0) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3bc2da5bff5..dc77262824b 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.4.0 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.4.1+incompatible - github.com/docker/docker v27.4.1+incompatible + github.com/docker/cli v27.5.0+incompatible + github.com/docker/docker v27.5.0+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 06dfe7693b3..74b17c8ecf5 100644 --- a/go.sum +++ b/go.sum @@ -90,10 +90,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.4.1+incompatible h1:VzPiUlRJ/xh+otB75gva3r05isHMo5wXDfPRi5/b4hI= -github.com/docker/cli v27.4.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.4.1+incompatible h1:ZJvcY7gfwHn1JF48PfbyXg7Jyt9ZCWDW+GGXOIxEwp4= -github.com/docker/docker v27.4.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM= +github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.5.0+incompatible h1:um++2NcQtGRTz5eEgO6aJimo6/JxrTXC941hd05JO6U= +github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 70bed8df81f9defba1f02930413d314a196b0be3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 07:24:36 +0000 Subject: [PATCH 1025/1066] build(deps): bump github.com/containerd/containerd/v2 Bumps [github.com/containerd/containerd/v2](https://github.com/containerd/containerd) from 2.0.1 to 2.0.2. - [Release notes](https://github.com/containerd/containerd/releases) - [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md) - [Commits](https://github.com/containerd/containerd/compare/v2.0.1...v2.0.2) --- updated-dependencies: - dependency-name: github.com/containerd/containerd/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 8a680ba94e7..b8d7e9ace42 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/containerd/cgroups/v3 v3.0.5 github.com/containerd/console v1.0.4 github.com/containerd/containerd/api v1.8.0 - github.com/containerd/containerd/v2 v2.0.1 + github.com/containerd/containerd/v2 v2.0.2 github.com/containerd/continuity v0.4.5 github.com/containerd/errdefs v1.0.0 github.com/containerd/fifo v1.1.0 @@ -84,7 +84,7 @@ require ( github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/go-runc v1.1.0 // indirect github.com/containerd/plugin v1.0.0 // indirect - github.com/containerd/ttrpc v1.2.6 // indirect + github.com/containerd/ttrpc v1.2.7 // indirect github.com/containers/ocicrypt v1.2.1 // indirect github.com/djherbis/times v1.6.0 // indirect github.com/docker/docker-credential-helpers v0.8.2 // indirect diff --git a/go.sum b/go.sum index a9e4c928e49..1c03811fde6 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,8 @@ github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= -github.com/containerd/containerd/v2 v2.0.1 h1:xqSar9cjkGhfQ2YvanCu7FMLk6+pNCFMCAroM2ALPp0= -github.com/containerd/containerd/v2 v2.0.1/go.mod h1:A9DyAg+lXTiSBOsBTqQtJL4O3AGaM1aa4UHmVh4uFhM= +github.com/containerd/containerd/v2 v2.0.2 h1:GmH/tRBlTvrXOLwSpWE2vNAm8+MqI6nmxKpKBNKY8Wc= +github.com/containerd/containerd/v2 v2.0.2/go.mod h1:wIqEvQ/6cyPFUGJ5yMFanspPabMLor+bF865OHvNTTI= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -63,8 +63,8 @@ github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRcc github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= github.com/containerd/stargz-snapshotter/ipfs v0.16.3 h1:d6IBSzYo0vlFcujwTqJRwpI3cZgX3E2I6Ev7LtMaZ4M= github.com/containerd/stargz-snapshotter/ipfs v0.16.3/go.mod h1:d4EuGnC3RteInKAdddUbDOL88uw3vZySSLZ44pbriGM= -github.com/containerd/ttrpc v1.2.6 h1:zG+Kn5EZ6MUYCS1t2Hmt2J4tMVaLSFEJVOraDQwNPC4= -github.com/containerd/ttrpc v1.2.6/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= +github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ= +github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8FuJbEslXM= From e3d27107dee430949377ddfb51876931a0b2babb Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Wed, 15 Jan 2025 15:43:33 +0000 Subject: [PATCH 1026/1066] test: refactor TestRunWithInvalidPortThenCleanUp This commit refactors TestRunWithInvalidPortThenCleanUp in cmd/nerdctl/container/container_run_network_linux_test.go based on the principles in the following document. - https://github.com/containerd/nerdctl/tree/main/docs/testing#principles Signed-off-by: Hayato Kiwata --- .../container_run_network_linux_test.go | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/cmd/nerdctl/container/container_run_network_linux_test.go b/cmd/nerdctl/container/container_run_network_linux_test.go index b946947fc01..5e46c481cec 100644 --- a/cmd/nerdctl/container/container_run_network_linux_test.go +++ b/cmd/nerdctl/container/container_run_network_linux_test.go @@ -41,6 +41,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" + "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) func extractHostPort(portMapping string, port string) (string, error) { @@ -350,15 +351,29 @@ func TestRunPort(t *testing.T) { } func TestRunWithInvalidPortThenCleanUp(t *testing.T) { + testCase := nerdtest.Setup() // docker does not set label restriction to 4096 bytes - testutil.DockerIncompatible(t) - t.Parallel() - base := testutil.NewBase(t) - containerName := testutil.Identifier(t) - defer base.Cmd("rm", "-f", containerName).Run() - base.Cmd("run", "--rm", "--name", containerName, "-p", "22200-22299:22200-22299", testutil.CommonImage).AssertFail() - base.Cmd("run", "--rm", "--name", containerName, "-p", "22200-22299:22200-22299", testutil.CommonImage).AssertCombinedOutContains(errdefs.ErrInvalidArgument.Error()) - base.Cmd("run", "--rm", "--name", containerName, testutil.CommonImage).AssertOK() + testCase.Require = test.Not(nerdtest.Docker) + + testCase.SubTests = []*test.Case{ + { + Description: "Run a container with invalid ports, and then clean up.", + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "--data-root", data.TempDir(), "-f", data.Identifier()) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("run", "--data-root", data.TempDir(), "--rm", "--name", data.Identifier(), "-p", "22200-22299:22200-22299", testutil.CommonImage) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 1, + Errors: []error{errdefs.ErrInvalidArgument}, + } + }, + }, + } + + testCase.Run(t) } func TestRunContainerWithStaticIP(t *testing.T) { From 7bfbd31f489c6714c5ddb93f495614a1600e3f6a Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Wed, 15 Jan 2025 15:52:37 +0000 Subject: [PATCH 1027/1066] fix: Add the logic to clean up an orphaned etchosts directory This commit adds the logic to clean up an orphaned etchosts directory for the container that failed to create. Signed-off-by: Hayato Kiwata --- pkg/cmd/container/create.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 77b5656e098..72be3454299 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -888,6 +888,17 @@ func generateGcFunc(ctx context.Context, container containerd.Container, ns, id, if netGcErr != nil { log.G(ctx).WithError(netGcErr).Warnf("failed to revert container %q networking settings", id) } + } else { + hs, err := hostsstore.New(dataStore, internalLabels.namespace) + if err != nil { + log.G(ctx).WithError(err).Warnf("failed to instantiate hostsstore for %q", internalLabels.namespace) + } else { + if _, err := hs.HostsPath(id); err != nil { + log.G(ctx).WithError(err).Warnf("an etchosts directory for container %q dosen't exist", id) + } else if err = hs.Delete(id); err != nil { + log.G(ctx).WithError(err).Warnf("failed to remove an etchosts directory for container %q", id) + } + } } ipc, ipcErr := ipcutil.DecodeIPCLabel(internalLabels.ipc) From fcb900e9a3ec031cd66d40a91810f91be5a9db06 Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Wed, 15 Jan 2025 15:54:39 +0000 Subject: [PATCH 1028/1066] test: Add an test for added logic to TestRunWithInvalidPortThenCleanUp This commit adds an test for added logic to clean up an orphaned etchosts directory for the container that failed to create to TestRunWithInvalidPortThenCleanUp. Signed-off-by: Hayato Kiwata --- .../container_run_network_linux_test.go | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/cmd/nerdctl/container/container_run_network_linux_test.go b/cmd/nerdctl/container/container_run_network_linux_test.go index 5e46c481cec..8d020905eb8 100644 --- a/cmd/nerdctl/container/container_run_network_linux_test.go +++ b/cmd/nerdctl/container/container_run_network_linux_test.go @@ -22,6 +22,7 @@ import ( "net" "os" "os/exec" + "path/filepath" "regexp" "runtime" "strings" @@ -29,10 +30,12 @@ import ( "time" "github.com/containernetworking/plugins/pkg/ns" + "github.com/opencontainers/go-digest" "github.com/vishvananda/netlink" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" + "github.com/containerd/containerd/v2/defaults" "github.com/containerd/containerd/v2/pkg/netns" "github.com/containerd/errdefs" @@ -368,6 +371,27 @@ func TestRunWithInvalidPortThenCleanUp(t *testing.T) { return &test.Expected{ ExitCode: 1, Errors: []error{errdefs.ErrInvalidArgument}, + Output: func(stdout string, info string, t *testing.T) { + getAddrHash := func(addr string) string { + const addrHashLen = 8 + + d := digest.SHA256.FromString(addr) + h := d.Encoded()[0:addrHashLen] + + return h + } + + dataRoot := data.TempDir() + h := getAddrHash(defaults.DefaultAddress) + dataStore := filepath.Join(dataRoot, h) + namespace := string(helpers.Read(nerdtest.Namespace)) + etchostsPath := filepath.Join(dataStore, "etchosts", namespace) + + etchostsDirs, err := os.ReadDir(etchostsPath) + + assert.NilError(t, err) + assert.Equal(t, len(etchostsDirs), 0) + }, } }, }, From 7a4c25281eb8ba4f2d1b1f9fea1a89f5343794d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 22:14:14 +0000 Subject: [PATCH 1029/1066] build(deps): bump docker/build-push-action from 6.11.0 to 6.12.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.11.0 to 6.12.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/b32b51a8eda65d6793cd0494a773d4f6bcef32dc...67a2d409c0a876cbe6b11854e3e25193efe4e62d) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 283f6ebe30d..8cc17c5287d 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -60,7 +60,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0 + uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 with: context: . platforms: linux/amd64,linux/arm64 From ef26ad8fc39824a93cb9b02515904db546035d82 Mon Sep 17 00:00:00 2001 From: zzzzzzzzzy9 Date: Tue, 14 Jan 2025 16:52:42 +0800 Subject: [PATCH 1030/1066] reset spec if update returned error Signed-off-by: zzzzzzzzzy9 --- cmd/nerdctl/container/container_update.go | 19 +++++++---- .../container/container_update_linux_test.go | 33 +++++++++++++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 cmd/nerdctl/container/container_update_linux_test.go diff --git a/cmd/nerdctl/container/container_update.go b/cmd/nerdctl/container/container_update.go index c1805608b7a..0ce83e5a6c5 100644 --- a/cmd/nerdctl/container/container_update.go +++ b/cmd/nerdctl/container/container_update.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "runtime" + "time" "github.com/docker/go-units" runtimespec "github.com/opencontainers/runtime-spec/specs-go" @@ -241,7 +242,7 @@ func getUpdateOption(cmd *cobra.Command, globalOptions types.GlobalCommandOption return options, nil } -func updateContainer(ctx context.Context, client *containerd.Client, id string, opts updateResourceOptions, cmd *cobra.Command) error { +func updateContainer(ctx context.Context, client *containerd.Client, id string, opts updateResourceOptions, cmd *cobra.Command) (retErr error) { container, err := client.LoadContainer(ctx, id) if err != nil { return err @@ -339,12 +340,18 @@ func updateContainer(ctx context.Context, client *containerd.Client, id string, } if err := updateContainerSpec(ctx, container, spec); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to update spec %+v for container %q", spec, id) - // reset spec on error. - if err := updateContainerSpec(ctx, container, oldSpec); err != nil { - log.G(ctx).WithError(err).Errorf("Failed to update spec %+v for container %q", oldSpec, id) + return fmt.Errorf("failed to update spec %+v for container %q", spec, id) + } + defer func() { + if retErr != nil { + deferCtx, deferCancel := context.WithTimeout(ctx, 1*time.Minute) + defer deferCancel() + // Reset spec on error. + if err := updateContainerSpec(deferCtx, container, oldSpec); err != nil { + log.G(ctx).WithError(err).Errorf("Failed to update spec %+v for container %q", oldSpec, id) + } } - } + }() restart, err := cmd.Flags().GetString("restart") if err != nil { diff --git a/cmd/nerdctl/container/container_update_linux_test.go b/cmd/nerdctl/container/container_update_linux_test.go new file mode 100644 index 00000000000..a4091f4156a --- /dev/null +++ b/cmd/nerdctl/container/container_update_linux_test.go @@ -0,0 +1,33 @@ +/* + 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 container + +import ( + "testing" + + "github.com/containerd/nerdctl/v2/pkg/testutil" +) + +func TestUpdateContainer(t *testing.T) { + testutil.DockerIncompatible(t) + testContainerName := testutil.Identifier(t) + base := testutil.NewBase(t) + base.Cmd("run", "-d", "--name", testContainerName, testutil.CommonImage, "sleep", "infinity").AssertOK() + defer base.Cmd("rm", "-f", testContainerName).Run() + base.Cmd("update", "--memory", "999999999", "--restart", "123", testContainerName).AssertFail() + base.Cmd("inspect", "--mode=native", testContainerName).AssertOutNotContains(`"limit": 999999999,`) +} From ae9894e35afac3cd0ba86627dd44c796be139276 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Jan 2025 22:20:34 +0000 Subject: [PATCH 1031/1066] build(deps): bump golangci/golangci-lint-action from 6.1.1 to 6.2.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.1.1 to 6.2.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/971e284b6050e8a5849b72094c50ab08da042db8...ec5d18412c0aeab7936cb16880d708ba2a64e1ae) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 87ad6b3dcda..b98ddafac52 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -51,7 +51,7 @@ jobs: go-version: ${{ env.GO_VERSION }} check-latest: true - name: golangci-lint - uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1 + uses: golangci/golangci-lint-action@ec5d18412c0aeab7936cb16880d708ba2a64e1ae # v6.2.0 with: args: --verbose other: From 9a6426d86c70a989af54df5419b693f957453f65 Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Thu, 16 Jan 2025 14:21:54 +0000 Subject: [PATCH 1032/1066] fix: save multiple images for the same image id to a tar archive Suppose we try to save multiple container images with the same image ID but different image names into a tar archive using the nerdctl save command. When we then try to load container images from this tar archive using the nerdctl load command, not all container images will be loaded. This behavior is reported and the details are described in the following: - https://github.com/containerd/nerdctl/issues/3806 Therefore, this PR resolves this issue. Signed-off-by: Hayato Kiwata --- cmd/nerdctl/image/image_save_test.go | 57 ++++++++++++++++++++++++++++ pkg/cmd/image/save.go | 5 +-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/image/image_save_test.go b/cmd/nerdctl/image/image_save_test.go index 3fcb9b8ceef..9e2dae5cda0 100644 --- a/cmd/nerdctl/image/image_save_test.go +++ b/cmd/nerdctl/image/image_save_test.go @@ -138,3 +138,60 @@ func TestSave(t *testing.T) { testCase.Run(t) } + +// TestSaveMultipleImagesWithSameIDAndLoad tests https://github.com/containerd/nerdctl/issues/3806 +func TestSaveMultipleImagesWithSameIDAndLoad(t *testing.T) { + testCase := nerdtest.Setup() + + // This test relies on the fact that we can remove the common image, which definitely conflicts with others, + // hence the private mode. + // Further note though, that this will hide the fact this the save command could fail if some layers are missing. + // See https://github.com/containerd/nerdctl/issues/3425 and others for details. + testCase.Require = nerdtest.Private + + if runtime.GOOS == "windows" { + testCase.Require = nerdtest.IsFlaky("https://github.com/containerd/nerdctl/issues/3524") + } + + testCase.SubTests = []*test.Case{ + { + Description: "Issue #3568 - Save multiple container images with the same image ID but different image names", + NoParallel: true, + Cleanup: func(data test.Data, helpers test.Helpers) { + if data.Get("id") != "" { + helpers.Anyhow("rmi", "-f", data.Get("id")) + } + }, + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("pull", "--quiet", testutil.CommonImage) + img := nerdtest.InspectImage(helpers, testutil.CommonImage) + var id string + if nerdtest.IsDocker() { + id = img.ID + } else { + id = strings.Split(img.RepoDigests[0], ":")[1] + } + helpers.Ensure("tag", testutil.CommonImage, data.Identifier()) + tarPath := filepath.Join(data.TempDir(), "out.tar") + helpers.Ensure("save", "-o", tarPath, testutil.CommonImage, data.Identifier()) + helpers.Ensure("rmi", "-f", id) + helpers.Ensure("load", "-i", tarPath) + data.Set("id", id) + }, + Command: func(data test.Data, helpers test.Helpers) test.TestableCommand { + return helpers.Command("images", "--no-trunc") + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Errors: []error{}, + Output: func(stdout string, info string, t *testing.T) { + assert.Equal(t, strings.Count(stdout, data.Get("id")), 2) + }, + } + }, + }, + } + + testCase.Run(t) +} diff --git a/pkg/cmd/image/save.go b/pkg/cmd/image/save.go index 815305ee80c..2b5d6d125ae 100644 --- a/pkg/cmd/image/save.go +++ b/pkg/cmd/image/save.go @@ -56,9 +56,8 @@ func Save(ctx context.Context, client *containerd.Client, images []string, optio } imgName := found.Image.Name - imgDigest := found.Image.Target.Digest.String() - if _, ok := savedImages[imgDigest]; !ok { - savedImages[imgDigest] = struct{}{} + if _, ok := savedImages[imgName]; !ok { + savedImages[imgName] = struct{}{} exportOpts = append(exportOpts, archive.WithImage(imageStore, imgName)) } return nil From ab027adfab1965dfdc8c4288e5ed6803407b69f2 Mon Sep 17 00:00:00 2001 From: Jack Harper Date: Fri, 17 Jan 2025 16:08:59 +0000 Subject: [PATCH 1033/1066] Correct `compose logs` command reference Signed-off-by: Jack Harper --- docs/command-reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/command-reference.md b/docs/command-reference.md index 17ad5204f12..4284094d176 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1443,7 +1443,7 @@ Unimplemented `docker compose up` (V2) flags: `--environment` ### :whale: nerdctl compose logs -Create and start containers +Show logs of running containers Usage: `nerdctl compose logs [OPTIONS] [SERVICE...]` From 128e6a7cd79c380dfc64fdcbb0715d306a925ff5 Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Wed, 15 Jan 2025 18:13:42 +0100 Subject: [PATCH 1034/1066] [doc] AppArmor profile setup for rootlesskit Introduce documentation for AppArmor profile for rootlesskit. Signed-off-by: fahed dorgaa --- docs/rootless.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/rootless.md b/docs/rootless.md index 62709e50a27..1000bd50865 100644 --- a/docs/rootless.md +++ b/docs/rootless.md @@ -25,6 +25,10 @@ The usage of `containerd-rootless-setuptool.sh` is almost same as [`dockerd-root Resource limitation flags such as `nerdctl run --memory` require systemd and cgroup v2: https://rootlesscontaine.rs/getting-started/common/cgroup2/ +#### AppArmor Profile for Ubuntu 24.04+ + +Configuring AppArmor is needed only on Ubuntu 24.04+, with RootlessKit installed under a non-standard path: https://rootlesscontaine.rs/getting-started/common/apparmor/ + ## Client (nerdctl) Just execute `nerdctl`. No need to specify the socket address manually. From 08206c8e2ee8d2be7fa3fdf54c534e2629fd1853 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 22:16:10 +0000 Subject: [PATCH 1035/1066] build(deps): bump github.com/rootless-containers/rootlesskit/v2 Bumps [github.com/rootless-containers/rootlesskit/v2](https://github.com/rootless-containers/rootlesskit) from 2.3.1 to 2.3.2. - [Release notes](https://github.com/rootless-containers/rootlesskit/releases) - [Commits](https://github.com/rootless-containers/rootlesskit/compare/v2.3.1...v2.3.2) --- updated-dependencies: - dependency-name: github.com/rootless-containers/rootlesskit/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b8d7e9ace42..21cbb68321c 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,7 @@ require ( github.com/opencontainers/runtime-spec v1.2.0 github.com/pelletier/go-toml/v2 v2.2.3 github.com/rootless-containers/bypass4netns v0.4.1 - github.com/rootless-containers/rootlesskit/v2 v2.3.1 + github.com/rootless-containers/rootlesskit/v2 v2.3.2 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/vishvananda/netlink v1.3.0 diff --git a/go.sum b/go.sum index 1c03811fde6..d745e8ed159 100644 --- a/go.sum +++ b/go.sum @@ -273,8 +273,8 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rootless-containers/bypass4netns v0.4.1 h1:zyYM1uSG7/prAphD2vlJvx/MEKK91EjD2XaefGx5PKA= github.com/rootless-containers/bypass4netns v0.4.1/go.mod h1:slu3ygwy1x6ey78oBTNs7lpymyEimLBYoXOG76b+Q+Y= -github.com/rootless-containers/rootlesskit/v2 v2.3.1 h1:wdYtdKxWFvVLby9ThMP6O6/v2q/GmOXbkRi+4m9nPW0= -github.com/rootless-containers/rootlesskit/v2 v2.3.1/go.mod h1:tdtfS9ak4bGmwJRmcjsAzcHN5rJ3c5dB7yhSV10KTbk= +github.com/rootless-containers/rootlesskit/v2 v2.3.2 h1:QZk7sKU3+B8UHretEeIg6NSTTpj0o4iHGNhNbJBnHOU= +github.com/rootless-containers/rootlesskit/v2 v2.3.2/go.mod h1:RL7YzL02nA2d8HAzt5d1nZnuiAeudQ4oym+HF/7sk7U= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU= github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U= From 8af25af64f63d4234128a5ec50a8cda4810c334e Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 21 Jan 2025 09:52:07 +0900 Subject: [PATCH 1036/1066] update containerd (2.0.2) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 14 +++++++------- Dockerfile | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e13366fcaa4..e61e5d23e47 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,10 +31,10 @@ jobs: containerd: v1.7.25 arch: amd64 - runner: ubuntu-24.04 - containerd: v2.0.1 + containerd: v2.0.2 arch: amd64 - runner: arm64-8core-32gb - containerd: v2.0.1 + containerd: v2.0.2 arch: arm64 env: CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -113,11 +113,11 @@ jobs: runner: "ubuntu-22.04" arch: amd64 - ubuntu: 24.04 - containerd: v2.0.1 + containerd: v2.0.2 runner: "ubuntu-24.04" arch: amd64 - ubuntu: 24.04 - containerd: v2.0.1 + containerd: v2.0.2 runner: arm64-8core-32gb arch: arm64 env: @@ -167,7 +167,7 @@ jobs: matrix: include: - ubuntu: 24.04 - containerd: v2.0.1 + containerd: v2.0.2 arch: amd64 env: CONTAINERD_VERSION: "${{ matrix.containerd }}" @@ -239,7 +239,7 @@ jobs: target: rootless arch: amd64 - ubuntu: 24.04 - containerd: v2.0.1 + containerd: v2.0.2 rootlesskit: v2.3.1 target: rootless arch: amd64 @@ -403,7 +403,7 @@ jobs: key: vagrant-${{ matrix.box }} - name: Set up vagrant run: | - # from https://github.com/containerd/containerd/blob/v2.0.1/.github/workflows/ci.yml#L583-L596 + # from https://github.com/containerd/containerd/blob/v2.0.2/.github/workflows/ci.yml#L583-L596 # which is based on https://github.com/opencontainers/runc/blob/v1.1.8/.cirrus.yml#L41-L49 curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list diff --git a/Dockerfile b/Dockerfile index c2afffcecc1..99c488b1d14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ # TODO: verify commit hash # Basic deps -ARG CONTAINERD_VERSION=v2.0.1 +ARG CONTAINERD_VERSION=v2.0.2 ARG RUNC_VERSION=v1.2.4 ARG CNI_PLUGINS_VERSION=v1.6.2 From f17df13e38d690a2576b3436fbf6f6f536bed436 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 21 Jan 2025 09:59:43 +0900 Subject: [PATCH 1037/1066] update Kubo (0.32.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c2afffcecc1..99d507e193a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -48,7 +48,7 @@ ARG CONTAINERIZED_SYSTEMD_VERSION=v0.1.1 ARG GOTESTSUM_VERSION=v1.12.0 ARG NYDUS_VERSION=v2.3.0 ARG SOCI_SNAPSHOTTER_VERSION=0.8.0 -ARG KUBO_VERSION=v0.31.0 +ARG KUBO_VERSION=v0.32.1 FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.6.1 AS xx From d786133a085416a923b4802e323b6c02cab0c080 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 21 Jan 2025 09:53:16 +0900 Subject: [PATCH 1038/1066] update RootlessKit (2.3.2) Signed-off-by: Akihiro Suda --- .github/workflows/test.yml | 6 +++--- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.1 | 6 ------ Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.2 | 6 ++++++ 4 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.1 create mode 100644 Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.2 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e61e5d23e47..8f634ee93d3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -235,17 +235,17 @@ jobs: arch: amd64 - ubuntu: 22.04 containerd: v1.7.25 - rootlesskit: v2.3.1 + rootlesskit: v2.3.2 target: rootless arch: amd64 - ubuntu: 24.04 containerd: v2.0.2 - rootlesskit: v2.3.1 + rootlesskit: v2.3.2 target: rootless arch: amd64 - ubuntu: 24.04 containerd: v1.7.25 - rootlesskit: v2.3.1 + rootlesskit: v2.3.2 target: rootless-port-slirp4netns arch: amd64 env: diff --git a/Dockerfile b/Dockerfile index 99c488b1d14..9906e659557 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ ARG STARGZ_SNAPSHOTTER_VERSION=v0.16.3 # Extra deps: Encryption ARG IMGCRYPT_VERSION=v2.0.0 # Extra deps: Rootless -ARG ROOTLESSKIT_VERSION=v2.3.1 +ARG ROOTLESSKIT_VERSION=v2.3.2 ARG SLIRP4NETNS_VERSION=v1.3.1 # Extra deps: bypass4netns ARG BYPASS4NETNS_VERSION=v0.4.1 diff --git a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.1 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.1 deleted file mode 100644 index b624de1f641..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.1 +++ /dev/null @@ -1,6 +0,0 @@ -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/rootlesskit-v2.3.2 b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.2 new file mode 100644 index 00000000000..9c7f6e338d0 --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/rootlesskit-v2.3.2 @@ -0,0 +1,6 @@ +0a4ed18c6794bfe5821cc6548f52b26b3b2296170f05df194c2073545200d968 rootlesskit-aarch64.tar.gz +f9faaf3b91e02764eb8308c7a7da7de55311de9fea665ca1b2632421b9286bcc rootlesskit-armv7l.tar.gz +fc1120af52071dc2a6984eec8dfc74f5d973fb28fa6c6d7ec77523a636ebf641 rootlesskit-ppc64le.tar.gz +acc1d39483df101bfa204c8dbf61d2e7ac85b246b3e9c606dabeaaeededd0130 rootlesskit-riscv64.tar.gz +9e1c29b1b82162a71d435edf80898adcb5a41c0ec51202c36856276689eb7b52 rootlesskit-s390x.tar.gz +5d402d7995f1e2c369240de3c6f8eb4cc2a3d1f0f4877ac5362044b2e83962e9 rootlesskit-x86_64.tar.gz From 00e21f75b46b217b07bbe8614cce85989334851b Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 21 Jan 2025 09:54:44 +0900 Subject: [PATCH 1039/1066] update bypass4netns (0.4.2) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9906e659557..e632d30e8b1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,7 +32,7 @@ ARG IMGCRYPT_VERSION=v2.0.0 ARG ROOTLESSKIT_VERSION=v2.3.2 ARG SLIRP4NETNS_VERSION=v1.3.1 # Extra deps: bypass4netns -ARG BYPASS4NETNS_VERSION=v0.4.1 +ARG BYPASS4NETNS_VERSION=v0.4.2 # Extra deps: FUSE-OverlayFS ARG FUSE_OVERLAYFS_VERSION=v1.14 ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v2.1.0 From e7e27f6266c731f46b11888d111a32027c244641 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 21 Jan 2025 09:55:42 +0900 Subject: [PATCH 1040/1066] update containerd-fuse-overlayfs (2.1.1) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.0 | 6 ------ Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.1 | 6 ++++++ 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.0 create mode 100644 Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.1 diff --git a/Dockerfile b/Dockerfile index e632d30e8b1..25d7c2f7585 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ ARG SLIRP4NETNS_VERSION=v1.3.1 ARG BYPASS4NETNS_VERSION=v0.4.2 # Extra deps: FUSE-OverlayFS ARG FUSE_OVERLAYFS_VERSION=v1.14 -ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v2.1.0 +ARG CONTAINERD_FUSE_OVERLAYFS_VERSION=v2.1.1 # Extra deps: Init ARG TINI_VERSION=v0.19.0 # Extra deps: Debug diff --git a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.0 b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.0 deleted file mode 100644 index 60d31bb1113..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.0 +++ /dev/null @@ -1,6 +0,0 @@ -d8629e40e64f16b3b00ee17e393d48e495468d4397437a0a2982e86aaf3e7680 containerd-fuse-overlayfs-2.1.0-linux-amd64.tar.gz -9edbab1e93b2f87efb9532d84e20c67f58af3743adc3626b95fa74272bb0ebc7 containerd-fuse-overlayfs-2.1.0-linux-arm-v7.tar.gz -79d7e94350a4871320e3bca76a6a02860e70872d1ae4a4b8ecc2c655f0e62cb0 containerd-fuse-overlayfs-2.1.0-linux-arm64.tar.gz -fdec57ed7b3effbcb7aa34c6c65604ee94691c791fb6dec29a5055815dfc8816 containerd-fuse-overlayfs-2.1.0-linux-ppc64le.tar.gz -fe7ad1b516ccc87ab53f97de76008aff49d1523ea64c67f2f9da070d5fb3e0c1 containerd-fuse-overlayfs-2.1.0-linux-riscv64.tar.gz -c19b2d544ac4cd304df58baa7e68a1a1a3f93a80299c830f742379f21dd354c8 containerd-fuse-overlayfs-2.1.0-linux-s390x.tar.gz diff --git a/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.1 b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.1 new file mode 100644 index 00000000000..6596447644d --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/containerd-fuse-overlayfs-v2.1.1 @@ -0,0 +1,6 @@ +2061a4064d163544f69e36fe56d008ab90f791906d5a96bddf87d3151fdde836 containerd-fuse-overlayfs-2.1.1-linux-amd64.tar.gz +99d08b0f41ede108f36efb9b5d8e0613be69336785cf97a73074487b52d9e71e containerd-fuse-overlayfs-2.1.1-linux-arm-v7.tar.gz +2219bf91d943480ce7021d6fce956379050757a500d36540b4372d45616c74eb containerd-fuse-overlayfs-2.1.1-linux-arm64.tar.gz +a2515f00553334b23470d52b088e49c3aa69aa9d66163dc14f188684bc8c774d containerd-fuse-overlayfs-2.1.1-linux-ppc64le.tar.gz +ae0fc07af2d34fb4c599364f82570ec43fed07f1892e493726f5414ecf8c8908 containerd-fuse-overlayfs-2.1.1-linux-riscv64.tar.gz +1200244a100b2433cc98a7ec8a0138073e9ad1c5e11ed503f5d2b3063dd40197 containerd-fuse-overlayfs-2.1.1-linux-s390x.tar.gz From cb7fc0d4beeceace9df8caa34c8c0c0a2fb52c1d Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 21 Jan 2025 09:57:24 +0900 Subject: [PATCH 1041/1066] update BuildKit (0.19.0) Signed-off-by: Akihiro Suda --- Dockerfile | 2 +- Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.2 | 2 -- Dockerfile.d/SHA256SUMS.d/buildkit-v0.19.0 | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.2 create mode 100644 Dockerfile.d/SHA256SUMS.d/buildkit-v0.19.0 diff --git a/Dockerfile b/Dockerfile index 25d7c2f7585..5023b3f21bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ ARG RUNC_VERSION=v1.2.4 ARG CNI_PLUGINS_VERSION=v1.6.2 # Extra deps: Build -ARG BUILDKIT_VERSION=v0.18.2 +ARG BUILDKIT_VERSION=v0.19.0 # Extra deps: Lazy-pulling ARG STARGZ_SNAPSHOTTER_VERSION=v0.16.3 # Extra deps: Encryption diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.2 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.2 deleted file mode 100644 index 5a2660e6c67..00000000000 --- a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.18.2 +++ /dev/null @@ -1,2 +0,0 @@ -5662f23cfa5e475ff50932dd2b71d2c5812928fad631d1e8c9f8f5592a4c1568 buildkit-v0.18.2.linux-amd64.tar.gz -de0ae01abc689102de6a765f8f40a30e86203897d3a7b44511a3aa66824bbc48 buildkit-v0.18.2.linux-arm64.tar.gz \ No newline at end of file diff --git a/Dockerfile.d/SHA256SUMS.d/buildkit-v0.19.0 b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.19.0 new file mode 100644 index 00000000000..440c6b431ea --- /dev/null +++ b/Dockerfile.d/SHA256SUMS.d/buildkit-v0.19.0 @@ -0,0 +1,2 @@ +9993fdd8b454e541ac14a1adf4bf53d271dbc8f3aafde45894bf689604a0a5cf buildkit-v0.19.0.linux-amd64.tar.gz +be7f7922d8f5eea02704cd707fb62b5a18e272452243804601b523ae6bef0ef5 buildkit-v0.19.0.linux-arm64.tar.gz From a4fa4faafdc88d7b1f4968d57c4cff6eaca550dc Mon Sep 17 00:00:00 2001 From: Kohei Tokunaga Date: Tue, 21 Jan 2025 16:34:34 +0900 Subject: [PATCH 1042/1066] integration test: specify IPFS_PATH for IPFS service Signed-off-by: Kohei Tokunaga --- Dockerfile.d/test-integration-ipfs-offline.service | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile.d/test-integration-ipfs-offline.service b/Dockerfile.d/test-integration-ipfs-offline.service index cd16bdcbadf..af0662250c5 100644 --- a/Dockerfile.d/test-integration-ipfs-offline.service +++ b/Dockerfile.d/test-integration-ipfs-offline.service @@ -3,6 +3,7 @@ Description=ipfs daemon for integration test (offline) [Service] ExecStart=ipfs daemon --init --offline +Environment=IPFS_PATH="%h/.ipfs" [Install] WantedBy=docker-entrypoint.target From 84caccfcbb99f05af1a459116f9971a4c97c0a9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 22:11:50 +0000 Subject: [PATCH 1043/1066] build(deps): bump actions/setup-go from 5.2.0 to 5.3.0 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5.2.0 to 5.3.0. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/3041bf56c941b39c61721a86cd11f3bb1338122a...f111f3307d8850f501ac008e886eec1fd1932a34) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yml | 4 ++-- .github/workflows/project.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test-canary.yml | 2 +- .github/workflows/test.yml | 8 ++++---- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b98ddafac52..4af31aaf325 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -46,7 +46,7 @@ jobs: . ./hack/build-integration-canary.sh canary::golang::latest fi - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: ${{ env.GO_VERSION }} check-latest: true @@ -62,7 +62,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: ${{ env.GO_VERSION }} check-latest: true diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml index bdb34f52d5f..0330137c885 100644 --- a/.github/workflows/project.yml +++ b/.github/workflows/project.yml @@ -17,7 +17,7 @@ jobs: with: path: src/github.com/containerd/nerdctl fetch-depth: 100 - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: ${{ env.GO_VERSION }} cache-dependency-path: src/github.com/containerd/nerdctl diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b3a17aa0813..8439f9a12d1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 40 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: 1.23.x - name: "Compile binaries" diff --git a/.github/workflows/test-canary.yml b/.github/workflows/test-canary.yml index c178b907df4..f746a54548d 100644 --- a/.github/workflows/test-canary.yml +++ b/.github/workflows/test-canary.yml @@ -70,7 +70,7 @@ jobs: . ./hack/build-integration-canary.sh canary::golang::latest - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: ${{ env.GO_VERSION }} check-latest: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8f634ee93d3..5e76c9b911d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -76,7 +76,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: ${{ env.GO_VERSION }} check-latest: true @@ -315,7 +315,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: ${{ matrix.go-version }} check-latest: true @@ -330,7 +330,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: ${{ env.GO_VERSION }} check-latest: true @@ -365,7 +365,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 1 - - uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0 with: go-version: ${{ env.GO_VERSION }} check-latest: true From af3bb9995a63888158ad2485afc80c3c9a1ec2f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 22:54:27 +0000 Subject: [PATCH 1044/1066] build(deps): bump github.com/rootless-containers/bypass4netns Bumps [github.com/rootless-containers/bypass4netns](https://github.com/rootless-containers/bypass4netns) from 0.4.1 to 0.4.2. - [Commits](https://github.com/rootless-containers/bypass4netns/compare/v0.4.1...v0.4.2) --- updated-dependencies: - dependency-name: github.com/rootless-containers/bypass4netns dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 22 ++++++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 21cbb68321c..c27a14d845a 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,7 @@ require ( github.com/opencontainers/image-spec v1.1.0 github.com/opencontainers/runtime-spec v1.2.0 github.com/pelletier/go-toml/v2 v2.2.3 - github.com/rootless-containers/bypass4netns v0.4.1 + github.com/rootless-containers/bypass4netns v0.4.2 github.com/rootless-containers/rootlesskit/v2 v2.3.2 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 @@ -139,9 +139,9 @@ require ( go.opentelemetry.io/otel/trace v1.31.0 // indirect golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/mod v0.22.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/grpc v1.68.1 // indirect - google.golang.org/protobuf v1.35.2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 // indirect + google.golang.org/grpc v1.69.4 // indirect + google.golang.org/protobuf v1.36.2 // indirect lukechampine.com/blake3 v1.3.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect tags.cncf.io/container-device-interface v0.8.0 // indirect diff --git a/go.sum b/go.sum index d745e8ed159..39fe1cf07b5 100644 --- a/go.sum +++ b/go.sum @@ -161,6 +161,8 @@ github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQN github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.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= @@ -271,8 +273,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rootless-containers/bypass4netns v0.4.1 h1:zyYM1uSG7/prAphD2vlJvx/MEKK91EjD2XaefGx5PKA= -github.com/rootless-containers/bypass4netns v0.4.1/go.mod h1:slu3ygwy1x6ey78oBTNs7lpymyEimLBYoXOG76b+Q+Y= +github.com/rootless-containers/bypass4netns v0.4.2 h1:JUZcpX7VLRfDkLxBPC6fyNalJGv9MjnjECOilZIvKRc= +github.com/rootless-containers/bypass4netns v0.4.2/go.mod h1:iOY28IeFVqFHnK0qkBCQ3eKzKQgSW5DtlXFQJyJMAQk= github.com/rootless-containers/rootlesskit/v2 v2.3.2 h1:QZk7sKU3+B8UHretEeIg6NSTTpj0o4iHGNhNbJBnHOU= github.com/rootless-containers/rootlesskit/v2 v2.3.2/go.mod h1:RL7YzL02nA2d8HAzt5d1nZnuiAeudQ4oym+HF/7sk7U= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -335,6 +337,10 @@ go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= @@ -467,15 +473,15 @@ 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/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 h1:3UsHvIr4Wc2aW4brOaSCmcxh9ksica6fHEr8P1XhkYw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4= 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= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0= -google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -485,8 +491,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= -google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU= +google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= From 8a0c16c08cf0f47d79c159d4658418b075614df3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 22:59:46 +0000 Subject: [PATCH 1045/1066] build(deps): bump the docker group with 2 updates Bumps the docker group with 2 updates: [github.com/docker/cli](https://github.com/docker/cli) and [github.com/docker/docker](https://github.com/docker/docker). Updates `github.com/docker/cli` from 27.5.0+incompatible to 27.5.1+incompatible - [Commits](https://github.com/docker/cli/compare/v27.5.0...v27.5.1) Updates `github.com/docker/docker` from 27.5.0+incompatible to 27.5.1+incompatible - [Release notes](https://github.com/docker/docker/releases) - [Commits](https://github.com/docker/docker/compare/v27.5.0...v27.5.1) --- updated-dependencies: - dependency-name: github.com/docker/cli dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker - dependency-name: github.com/docker/docker dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c27a14d845a..f60e9943e75 100644 --- a/go.mod +++ b/go.mod @@ -35,8 +35,8 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 github.com/cyphar/filepath-securejoin v0.4.0 github.com/distribution/reference v0.6.0 - github.com/docker/cli v27.5.0+incompatible - github.com/docker/docker v27.5.0+incompatible + github.com/docker/cli v27.5.1+incompatible + github.com/docker/docker v27.5.1+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/fahedouch/go-logrotate v0.2.1 diff --git a/go.sum b/go.sum index 39fe1cf07b5..894e353d59b 100644 --- a/go.sum +++ b/go.sum @@ -90,10 +90,10 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v27.5.0+incompatible h1:aMphQkcGtpHixwwhAXJT1rrK/detk2JIvDaFkLctbGM= -github.com/docker/cli v27.5.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v27.5.0+incompatible h1:um++2NcQtGRTz5eEgO6aJimo6/JxrTXC941hd05JO6U= -github.com/docker/docker v27.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/cli v27.5.1+incompatible h1:JB9cieUT9YNiMITtIsguaN55PLOHhBSz3LKVc6cqWaY= +github.com/docker/cli v27.5.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/docker v27.5.1+incompatible h1:4PYU5dnBYqRQi0294d1FBECqT9ECWeQAIfE8q4YnPY8= +github.com/docker/docker v27.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= From 26c03224a052804053646bc614ba4ffd3b352f62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Jan 2025 23:00:00 +0000 Subject: [PATCH 1046/1066] build(deps): bump github.com/ipfs/go-cid from 0.4.1 to 0.5.0 Bumps [github.com/ipfs/go-cid](https://github.com/ipfs/go-cid) from 0.4.1 to 0.5.0. - [Release notes](https://github.com/ipfs/go-cid/releases) - [Commits](https://github.com/ipfs/go-cid/compare/v0.4.1...v0.5.0) --- updated-dependencies: - dependency-name: github.com/ipfs/go-cid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c27a14d845a..390c14bf9aa 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( github.com/fluent/fluent-logger-golang v1.9.0 github.com/fsnotify/fsnotify v1.8.0 github.com/go-viper/mapstructure/v2 v2.2.1 - github.com/ipfs/go-cid v0.4.1 + github.com/ipfs/go-cid v0.5.0 github.com/klauspost/compress v1.17.11 github.com/mattn/go-isatty v0.0.20 github.com/moby/sys/mount v0.3.4 diff --git a/go.sum b/go.sum index 39fe1cf07b5..324384ba5af 100644 --- a/go.sum +++ b/go.sum @@ -170,8 +170,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= -github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= +github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM= From ec6a6abd715676b7ee32006aec0a883bf8f2139c Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 16 Dec 2024 15:32:42 -0800 Subject: [PATCH 1047/1066] Relax error on annotations read failure Signed-off-by: apostasie --- pkg/cmd/container/kill.go | 3 ++- pkg/cmd/container/remove.go | 23 +++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/cmd/container/kill.go b/pkg/cmd/container/kill.go index ceb4ef9ac88..4f750d54784 100644 --- a/pkg/cmd/container/kill.go +++ b/pkg/cmd/container/kill.go @@ -143,7 +143,8 @@ func cleanupNetwork(ctx context.Context, container containerd.Container, globalO networksJSON := spec.Annotations[labels.Networks] var networks []string if err := json.Unmarshal([]byte(networksJSON), &networks); err != nil { - return err + log.G(ctx).WithError(err).WithField("container", container.ID()).Infof("unable to retrieve networking information for that container") + return nil } netType, err := nettype.Detect(networks) if err != nil { diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index d425b718972..827471189bd 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -191,19 +191,18 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions } netOpts, err := containerutil.NetworkOptionsFromSpec(spec) - if err != nil { - retErr = fmt.Errorf("failed to load container networking options from specs: %s", err) - return - } - - networkManager, err := containerutil.NewNetworkingOptionsManager(globalOptions, netOpts, client) - if err != nil { - retErr = fmt.Errorf("failed to instantiate network options manager: %s", err) - return - } + if err == nil { + networkManager, err := containerutil.NewNetworkingOptionsManager(globalOptions, netOpts, client) + if err != nil { + retErr = fmt.Errorf("failed to instantiate network options manager: %s", err) + return + } - if err := networkManager.CleanupNetworking(ctx, c); err != nil { - log.G(ctx).WithError(err).Warnf("failed to clean up container networking: %q", id) + if err := networkManager.CleanupNetworking(ctx, c); err != nil { + log.G(ctx).WithError(err).Warnf("failed to clean up container networking: %q", id) + } + } else { + log.G(ctx).WithError(err).WithField("container", id).Infof("unable to retrieve networking information for that container") } // Delete the container now. If it fails, try again without snapshot cleanup From a6fe6c1555cc1d4244de4f00063f1cc3b3deb821 Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 23 Jan 2025 18:15:34 -0800 Subject: [PATCH 1048/1066] Fix wrong error comparison Signed-off-by: apostasie --- pkg/logging/json_logger.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index 988e847d5e9..1066f0ad5f3 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -31,7 +31,6 @@ import ( "github.com/fsnotify/fsnotify" "github.com/containerd/containerd/v2/core/runtime/v2/logging" - "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/nerdctl/v2/pkg/logging/jsonfile" @@ -135,7 +134,7 @@ func viewLogsJSONFile(lvopts LogViewOptions, stdout, stderr io.Writer, stopChann if _, err := os.Stat(logFilePath); err != nil { // FIXME: this is a workaround for the actual issue, not a real solution // https://github.com/containerd/nerdctl/issues/3187 - if errors.Is(err, errdefs.ErrNotFound) { + if errors.Is(err, os.ErrNotExist) { log.L.Warnf("Racing log file creation. Pausing briefly.") time.Sleep(200 * time.Millisecond) _, err = os.Stat(logFilePath) From 735203367a3588b24a423dff2d347d4a946e618e Mon Sep 17 00:00:00 2001 From: apostasie Date: Thu, 23 Jan 2025 22:56:45 -0800 Subject: [PATCH 1049/1066] Skip TestRunBindMountPropagation Signed-off-by: apostasie --- cmd/nerdctl/container/container_run_mount_linux_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/nerdctl/container/container_run_mount_linux_test.go b/cmd/nerdctl/container/container_run_mount_linux_test.go index 1b3f651cef2..0e810551191 100644 --- a/cmd/nerdctl/container/container_run_mount_linux_test.go +++ b/cmd/nerdctl/container/container_run_mount_linux_test.go @@ -500,6 +500,8 @@ func TestRunVolumeBindMode(t *testing.T) { } func TestRunBindMountPropagation(t *testing.T) { + t.Skip("This test is currently broken. See https://github.com/containerd/nerdctl/issues/3404") + tID := testutil.Identifier(t) if !isRootfsShareableMount() { From 99bd7728840e802f08466973755083d6d220b1b9 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 24 Jan 2025 00:54:36 -0800 Subject: [PATCH 1050/1066] Fix test time to use UTC Signed-off-by: apostasie --- cmd/nerdctl/container/container_logs_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/nerdctl/container/container_logs_test.go b/cmd/nerdctl/container/container_logs_test.go index 71debda52e9..9a74af9d80c 100644 --- a/cmd/nerdctl/container/container_logs_test.go +++ b/cmd/nerdctl/container/container_logs_test.go @@ -51,7 +51,7 @@ bar` base.Cmd("logs", "-f", containerName).AssertOutContains("foo") //test timestamps flag - base.Cmd("logs", "-t", containerName).AssertOutContains(time.Now().Format("2006-01-02")) + base.Cmd("logs", "-t", containerName).AssertOutContains(time.Now().UTC().Format("2006-01-02")) //test tail flag base.Cmd("logs", "-n", "all", containerName).AssertOutContains(expected) From fe59974dcb72801ad74cb6c3dcb6c06af3242935 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 22:03:44 +0000 Subject: [PATCH 1051/1066] build(deps): bump docker/build-push-action from 6.12.0 to 6.13.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.12.0 to 6.13.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/67a2d409c0a876cbe6b11854e3e25193efe4e62d...ca877d9245402d1537745e0e356eab47c3520991) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ghcr-image-build-and-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ghcr-image-build-and-publish.yml b/.github/workflows/ghcr-image-build-and-publish.yml index 8cc17c5287d..d1615ad515d 100644 --- a/.github/workflows/ghcr-image-build-and-publish.yml +++ b/.github/workflows/ghcr-image-build-and-publish.yml @@ -60,7 +60,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 + uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6.13.0 with: context: . platforms: linux/amd64,linux/arm64 From 7c9d25adc16316783e6ceab7ae3e5f71f127a823 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 24 Jan 2025 14:40:56 -0800 Subject: [PATCH 1052/1066] Disable systemd test on arm64 Signed-off-by: apostasie --- .../container_run_systemd_linux_test.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cmd/nerdctl/container/container_run_systemd_linux_test.go b/cmd/nerdctl/container/container_run_systemd_linux_test.go index 065e450873c..e1a459eaf61 100644 --- a/cmd/nerdctl/container/container_run_systemd_linux_test.go +++ b/cmd/nerdctl/container/container_run_systemd_linux_test.go @@ -17,6 +17,7 @@ package container import ( + "runtime" "testing" "github.com/containerd/nerdctl/v2/pkg/testutil" @@ -36,6 +37,10 @@ func TestRunWithSystemdAlways(t *testing.T) { } func TestRunWithSystemdTrueEnabled(t *testing.T) { + if runtime.GOARCH != "amd64" { + t.Skip("This test is currently broken on arm with no emulation, as the Systemd image being used is amd64 only") + } + testutil.DockerIncompatible(t) t.Parallel() base := testutil.NewBase(t) @@ -60,6 +65,10 @@ systemctl list-jobs`).AssertOutContains("jobs") } func TestRunWithSystemdTrueDisabled(t *testing.T) { + if runtime.GOARCH != "amd64" { + t.Skip("This test is currently broken on arm with no emulation, as the Systemd image being used is amd64 only") + } + testutil.DockerIncompatible(t) t.Parallel() base := testutil.NewBase(t) @@ -94,6 +103,10 @@ func TestRunWithNoSystemd(t *testing.T) { } func TestRunWithSystemdPrivilegedError(t *testing.T) { + if runtime.GOARCH != "amd64" { + t.Skip("This test is currently broken on arm with no emulation, as the Systemd image being used is amd64 only") + } + testutil.DockerIncompatible(t) t.Parallel() base := testutil.NewBase(t) @@ -102,6 +115,10 @@ func TestRunWithSystemdPrivilegedError(t *testing.T) { } func TestRunWithSystemdPrivilegedSuccess(t *testing.T) { + if runtime.GOARCH != "amd64" { + t.Skip("This test is currently broken on arm with no emulation, as the Systemd image being used is amd64 only") + } + testutil.DockerIncompatible(t) t.Parallel() base := testutil.NewBase(t) From 10e4cda35b2af2cfbea08eb0a41922f0d8f09831 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 24 Jan 2025 15:14:40 -0800 Subject: [PATCH 1053/1066] Test portability fix: ensure tini-custom is here Signed-off-by: apostasie --- cmd/nerdctl/container/container_run_linux_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/nerdctl/container/container_run_linux_test.go b/cmd/nerdctl/container/container_run_linux_test.go index dc33702e1bd..1a67ac791e1 100644 --- a/cmd/nerdctl/container/container_run_linux_test.go +++ b/cmd/nerdctl/container/container_run_linux_test.go @@ -277,6 +277,7 @@ func TestRunUlimit(t *testing.T) { func TestRunWithInit(t *testing.T) { t.Parallel() testutil.DockerIncompatible(t) + testutil.RequireExecutable(t, "tini-custom") base := testutil.NewBase(t) container := testutil.Identifier(t) From 7f433aaa6fcd6e19ce1b2fb4ce46906908fc5f1a Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 24 Jan 2025 17:14:55 -0800 Subject: [PATCH 1054/1066] Fix socket address not being updated properly Signed-off-by: apostasie --- cmd/nerdctl/compose/compose_cp.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/compose/compose_cp.go b/cmd/nerdctl/compose/compose_cp.go index a35078bc405..aafc6b0bcb2 100644 --- a/cmd/nerdctl/compose/compose_cp.go +++ b/cmd/nerdctl/compose/compose_cp.go @@ -71,15 +71,15 @@ func composeCopyAction(cmd *cobra.Command, args []string) error { if err != nil { return err } - address := globalOptions.Address + // rootless cp runs in the host namespaces, so the address is different if rootlessutil.IsRootless() { - address, err = rootlessutil.RootlessContainredSockAddress() + globalOptions.Address, err = rootlessutil.RootlessContainredSockAddress() if err != nil { return err } } - client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, address) + client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address) if err != nil { return err } From 6e5e943bd3627fd432677b413b179b1d8e1b4bdc Mon Sep 17 00:00:00 2001 From: Ruihua Wen Date: Fri, 24 Jan 2025 01:02:56 +0900 Subject: [PATCH 1055/1066] fix: prevent panic in nydus snapshotter inspect Signed-off-by: Ruihua Wen --- pkg/inspecttypes/dockercompat/dockercompat.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index aceec3bca3d..cd3b76ac24f 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -340,7 +340,9 @@ func ImageFromNative(nativeImage *native.Image) (*Image, error) { if len(imgOCI.History) > 0 { image.Comment = imgOCI.History[len(imgOCI.History)-1].Comment - image.Created = imgOCI.History[len(imgOCI.History)-1].Created.Format(time.RFC3339Nano) + if !imgOCI.History[len(imgOCI.History)-1].Created.IsZero() { + image.Created = imgOCI.History[len(imgOCI.History)-1].Created.Format(time.RFC3339Nano) + } image.Author = imgOCI.History[len(imgOCI.History)-1].Author } From 17bbdffd862b5f173f483f50d620255d7f8165a7 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 22 Jan 2025 13:32:35 -0800 Subject: [PATCH 1056/1066] Consistently use %w instead of %s or %v when wrapping errors Signed-off-by: apostasie --- cmd/nerdctl/container/container_create.go | 2 +- cmd/nerdctl/container/container_logs.go | 2 +- cmd/nerdctl/container/container_run.go | 2 +- .../container_run_network_windows_test.go | 2 +- pkg/cmd/builder/build.go | 4 ++-- pkg/cmd/container/create.go | 6 +++--- pkg/cmd/container/logs.go | 2 +- pkg/cmd/container/remove.go | 2 +- pkg/cmd/container/top_unix.go | 2 +- pkg/composer/create.go | 4 ++-- pkg/composer/down.go | 4 ++-- pkg/composer/exec.go | 2 +- pkg/composer/orphans.go | 2 +- pkg/composer/port.go | 2 +- pkg/composer/run.go | 6 +++--- pkg/composer/up.go | 4 ++-- pkg/composer/up_service.go | 4 ++-- .../container_network_manager_windows.go | 8 ++++---- pkg/logging/fluentd_logger.go | 16 ++++++++-------- pkg/logging/journald_logger.go | 4 ++-- pkg/logging/json_logger.go | 4 ++-- pkg/logging/log_viewer.go | 4 ++-- pkg/logging/logging.go | 4 ++-- pkg/mountutil/mountutil_windows.go | 2 +- pkg/netutil/netutil.go | 6 +++--- pkg/ocihook/ocihook.go | 4 ++-- 26 files changed, 52 insertions(+), 52 deletions(-) diff --git a/cmd/nerdctl/container/container_create.go b/cmd/nerdctl/container/container_create.go index 45726e7f323..97d1b2f8a4b 100644 --- a/cmd/nerdctl/container/container_create.go +++ b/cmd/nerdctl/container/container_create.go @@ -443,7 +443,7 @@ func createAction(cmd *cobra.Command, args []string) error { netFlags, err := loadNetworkFlags(cmd) if err != nil { - return fmt.Errorf("failed to load networking flags: %s", err) + return fmt.Errorf("failed to load networking flags: %w", err) } netManager, err := containerutil.NewNetworkingOptionsManager(createOpt.GOptions, netFlags, client) diff --git a/cmd/nerdctl/container/container_logs.go b/cmd/nerdctl/container/container_logs.go index 910cbeffa03..005d4b19065 100644 --- a/cmd/nerdctl/container/container_logs.go +++ b/cmd/nerdctl/container/container_logs.go @@ -127,7 +127,7 @@ func getTailArgAsUint(arg string) (uint, error) { } num, err := strconv.Atoi(arg) if err != nil { - return 0, fmt.Errorf("failed to parse `-n/--tail` argument %q: %s", arg, err) + return 0, fmt.Errorf("failed to parse `-n/--tail` argument %q: %w", arg, err) } if num < 0 { return 0, fmt.Errorf("`-n/--tail` argument must be positive, got: %d", num) diff --git a/cmd/nerdctl/container/container_run.go b/cmd/nerdctl/container/container_run.go index 855d1512cdf..1a0639749c9 100644 --- a/cmd/nerdctl/container/container_run.go +++ b/cmd/nerdctl/container/container_run.go @@ -357,7 +357,7 @@ func runAction(cmd *cobra.Command, args []string) error { netFlags, err := loadNetworkFlags(cmd) if err != nil { - return fmt.Errorf("failed to load networking flags: %s", err) + return fmt.Errorf("failed to load networking flags: %w", err) } netManager, err := containerutil.NewNetworkingOptionsManager(createOpt.GOptions, netFlags, client) diff --git a/cmd/nerdctl/container/container_run_network_windows_test.go b/cmd/nerdctl/container/container_run_network_windows_test.go index 53e9dd73bfc..a727978eed5 100644 --- a/cmd/nerdctl/container/container_run_network_windows_test.go +++ b/cmd/nerdctl/container/container_run_network_windows_test.go @@ -73,7 +73,7 @@ func listHnsEndpointsRegex(hnsEndpointNameRegex string) ([]hcsshim.HNSEndpoint, } hnsEndpoints, err := hcsshim.HNSListEndpointRequest() if err != nil { - return nil, fmt.Errorf("failed to list HNS endpoints for request: %s", err) + return nil, fmt.Errorf("failed to list HNS endpoints for request: %w", err) } res := []hcsshim.HNSEndpoint{} diff --git a/pkg/cmd/builder/build.go b/pkg/cmd/builder/build.go index 2ab6df0e8cb..4fb69ccd1fb 100644 --- a/pkg/cmd/builder/build.go +++ b/pkg/cmd/builder/build.go @@ -120,7 +120,7 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder imageService := client.ImageService() image, err := imageService.Get(ctx, tags[0]) if err != nil { - return fmt.Errorf("unable to tag image: %s", err) + return fmt.Errorf("unable to tag image: %w", err) } for _, targetRef := range tags[1:] { image.Name = targetRef @@ -135,7 +135,7 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder } continue } - return fmt.Errorf("unable to tag image: %s", err) + return fmt.Errorf("unable to tag image: %w", err) } } } diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 72be3454299..c7f58409225 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -230,19 +230,19 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa cOpts = append(cOpts, restartOpts...) if err = netManager.VerifyNetworkOptions(ctx); err != nil { - return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), fmt.Errorf("failed to verify networking settings: %s", err) + return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), fmt.Errorf("failed to verify networking settings: %w", err) } netOpts, netNewContainerOpts, err := netManager.ContainerNetworkingOpts(ctx, id) if err != nil { - return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), fmt.Errorf("failed to generate networking spec options: %s", err) + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), fmt.Errorf("failed to generate networking spec options: %w", err) } opts = append(opts, netOpts...) cOpts = append(cOpts, netNewContainerOpts...) netLabelOpts, err := netManager.InternalNetworkingOptionLabels(ctx) if err != nil { - return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), fmt.Errorf("failed to generate internal networking labels: %s", err) + return nil, generateRemoveOrphanedDirsFunc(ctx, id, dataStore, internalLabels), fmt.Errorf("failed to generate internal networking labels: %w", err) } envs = append(envs, "HOSTNAME="+netLabelOpts.Hostname) diff --git a/pkg/cmd/container/logs.go b/pkg/cmd/container/logs.go index 2deb143e6bc..dd523ed1774 100644 --- a/pkg/cmd/container/logs.go +++ b/pkg/cmd/container/logs.go @@ -85,7 +85,7 @@ func Logs(ctx context.Context, client *containerd.Client, container string, opti } else { waitCh, err := task.Wait(ctx) if err != nil { - return fmt.Errorf("failed to get wait channel for task %#v: %s", task, err) + return fmt.Errorf("failed to get wait channel for task %#v: %w", task, err) } // Setup goroutine to send stop event if container task finishes: diff --git a/pkg/cmd/container/remove.go b/pkg/cmd/container/remove.go index 827471189bd..1fedcc50432 100644 --- a/pkg/cmd/container/remove.go +++ b/pkg/cmd/container/remove.go @@ -194,7 +194,7 @@ func RemoveContainer(ctx context.Context, c containerd.Container, globalOptions if err == nil { networkManager, err := containerutil.NewNetworkingOptionsManager(globalOptions, netOpts, client) if err != nil { - retErr = fmt.Errorf("failed to instantiate network options manager: %s", err) + retErr = fmt.Errorf("failed to instantiate network options manager: %w", err) return } diff --git a/pkg/cmd/container/top_unix.go b/pkg/cmd/container/top_unix.go index 606e6c5772d..92141a4c77a 100644 --- a/pkg/cmd/container/top_unix.go +++ b/pkg/cmd/container/top_unix.go @@ -232,7 +232,7 @@ func parsePSOutput(output []byte, procs []uint32) (*ContainerTopOKBody, error) { } p, err = strconv.Atoi(fields[pidIndex]) if err != nil { - return nil, fmt.Errorf("unexpected pid '%s': %s", fields[pidIndex], err) + return nil, fmt.Errorf("unexpected pid '%s': %w", fields[pidIndex], err) } if hasPid(procs, p) { diff --git a/pkg/composer/create.go b/pkg/composer/create.go index a2ae9180160..8b15c4823f6 100644 --- a/pkg/composer/create.go +++ b/pkg/composer/create.go @@ -159,7 +159,7 @@ func (c *Composer) createServiceContainer(ctx context.Context, service *servicep // check if container already exists exists, err := c.containerExists(ctx, container.Name, service.Unparsed.Name) if err != nil { - return "", fmt.Errorf("error while checking for containers with name %q: %s", container.Name, err) + return "", fmt.Errorf("error while checking for containers with name %q: %w", container.Name, err) } // delete container if it already exists and force-recreate is enabled @@ -172,7 +172,7 @@ func (c *Composer) createServiceContainer(ctx context.Context, service *servicep log.G(ctx).Debugf("Container %q already exists and force-created is enabled, deleting", container.Name) delCmd := c.createNerdctlCmd(ctx, "rm", "-f", container.Name) if err = delCmd.Run(); err != nil { - return "", fmt.Errorf("could not delete container %q: %s", container.Name, err) + return "", fmt.Errorf("could not delete container %q: %w", container.Name, err) } log.G(ctx).Infof("Re-creating container %s", container.Name) } else { diff --git a/pkg/composer/down.go b/pkg/composer/down.go index d02cf613082..6996f1bda33 100644 --- a/pkg/composer/down.go +++ b/pkg/composer/down.go @@ -57,12 +57,12 @@ func (c *Composer) Down(ctx context.Context, downOptions DownOptions) error { } orphans, err := c.getOrphanContainers(ctx, parsedServices) if err != nil && downOptions.RemoveOrphans { - return fmt.Errorf("error getting orphaned containers: %s", err) + return fmt.Errorf("error getting orphaned containers: %w", err) } if len(orphans) > 0 { if downOptions.RemoveOrphans { if err := c.removeContainers(ctx, orphans, RemoveOptions{Stop: true, Volumes: downOptions.RemoveVolumes}); err != nil { - return fmt.Errorf("error removeing orphaned containers: %s", err) + return fmt.Errorf("error removeing orphaned containers: %w", err) } } else { log.G(ctx).Warnf("found %d orphaned containers: %v, you can run this command with the --remove-orphans flag to clean it up", len(orphans), orphans) diff --git a/pkg/composer/exec.go b/pkg/composer/exec.go index 04c6e077614..4e34bfa2a86 100644 --- a/pkg/composer/exec.go +++ b/pkg/composer/exec.go @@ -51,7 +51,7 @@ type ExecOptions struct { func (c *Composer) Exec(ctx context.Context, eo ExecOptions) error { containers, err := c.Containers(ctx, eo.ServiceName) if err != nil { - return fmt.Errorf("fail to get containers for service %s: %s", eo.ServiceName, err) + return fmt.Errorf("fail to get containers for service %s: %w", eo.ServiceName, err) } if len(containers) == 0 { return fmt.Errorf("no running containers from service %s", eo.ServiceName) diff --git a/pkg/composer/orphans.go b/pkg/composer/orphans.go index eacac677fc3..cd45386fa0d 100644 --- a/pkg/composer/orphans.go +++ b/pkg/composer/orphans.go @@ -45,7 +45,7 @@ func (c *Composer) getOrphanContainers(ctx context.Context, parsedServices []*se // to any name of given services. containerLabels, err := container.Labels(ctx) if err != nil { - return nil, fmt.Errorf("error getting container labels: %s", err) + return nil, fmt.Errorf("error getting container labels: %w", err) } containerSvc := containerLabels[labels.ComposeService] if inServices := parsedSvcNames[containerSvc]; !inServices { diff --git a/pkg/composer/port.go b/pkg/composer/port.go index 750ee8ae970..f786b4a3923 100644 --- a/pkg/composer/port.go +++ b/pkg/composer/port.go @@ -38,7 +38,7 @@ type PortOptions struct { func (c *Composer) Port(ctx context.Context, writer io.Writer, po PortOptions) error { containers, err := c.Containers(ctx, po.ServiceName) if err != nil { - return fmt.Errorf("fail to get containers for service %s: %s", po.ServiceName, err) + return fmt.Errorf("fail to get containers for service %s: %w", po.ServiceName, err) } if len(containers) == 0 { return fmt.Errorf("no running containers from service %s", po.ServiceName) diff --git a/pkg/composer/run.go b/pkg/composer/run.go index 0b3c4c72342..9928fbd8d5d 100644 --- a/pkg/composer/run.go +++ b/pkg/composer/run.go @@ -167,7 +167,7 @@ func (c *Composer) Run(ctx context.Context, ro RunOptions) error { for _, p := range ro.Publish { pc, err := types.ParsePortConfig(p) if err != nil { - return fmt.Errorf("error parse --publish: %s", err) + return fmt.Errorf("error parse --publish: %w", err) } targetSvc.Ports = append(targetSvc.Ports, pc...) } @@ -193,12 +193,12 @@ func (c *Composer) Run(ctx context.Context, ro RunOptions) error { // FYI: https://github.com/docker/compose/blob/v2.3.4/pkg/compose/create.go#L91-L112 orphans, err := c.getOrphanContainers(ctx, parsedServices) if err != nil && ro.RemoveOrphans { - return fmt.Errorf("error getting orphaned containers: %s", err) + return fmt.Errorf("error getting orphaned containers: %w", err) } if len(orphans) > 0 { if ro.RemoveOrphans { if err := c.removeContainers(ctx, orphans, RemoveOptions{Stop: true, Volumes: true}); err != nil { - return fmt.Errorf("error removing orphaned containers: %s", err) + return fmt.Errorf("error removing orphaned containers: %w", err) } } else { log.G(ctx).Warnf("found %d orphaned containers: %v, you can run this command with the --remove-orphans flag to clean it up", len(orphans), orphans) diff --git a/pkg/composer/up.go b/pkg/composer/up.go index 98106c81ae4..84da4535c0f 100644 --- a/pkg/composer/up.go +++ b/pkg/composer/up.go @@ -106,12 +106,12 @@ func (c *Composer) Up(ctx context.Context, uo UpOptions, services []string) erro // FYI: https://github.com/docker/compose/blob/v2.3.4/pkg/compose/create.go#L91-L112 orphans, err := c.getOrphanContainers(ctx, parsedServices) if err != nil && uo.RemoveOrphans { - return fmt.Errorf("error getting orphaned containers: %s", err) + return fmt.Errorf("error getting orphaned containers: %w", err) } if len(orphans) > 0 { if uo.RemoveOrphans { if err := c.removeContainers(ctx, orphans, RemoveOptions{Stop: true, Volumes: true}); err != nil { - return fmt.Errorf("error removing orphaned containers: %s", err) + return fmt.Errorf("error removing orphaned containers: %w", err) } } else { log.G(ctx).Warnf("found %d orphaned containers: %v, you can run this command with the --remove-orphans flag to clean it up", len(orphans), orphans) diff --git a/pkg/composer/up_service.go b/pkg/composer/up_service.go index f0da7c9b72a..7f6adf9fac5 100644 --- a/pkg/composer/up_service.go +++ b/pkg/composer/up_service.go @@ -129,7 +129,7 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse // check if container already exists existingCid, err := c.containerID(ctx, container.Name, service.Unparsed.Name) if err != nil { - return "", fmt.Errorf("error while checking for containers with name %q: %s", container.Name, err) + return "", fmt.Errorf("error while checking for containers with name %q: %w", container.Name, err) } // FIXME @@ -157,7 +157,7 @@ func (c *Composer) upServiceContainer(ctx context.Context, service *serviceparse log.G(ctx).Debugf("Container %q already exists, deleting", container.Name) delCmd := c.createNerdctlCmd(ctx, "rm", "-f", container.Name) if err = delCmd.Run(); err != nil { - return "", fmt.Errorf("could not delete container %q: %s", container.Name, err) + return "", fmt.Errorf("could not delete container %q: %w", container.Name, err) } log.G(ctx).Infof("Re-creating container %s", container.Name) } else { diff --git a/pkg/containerutil/container_network_manager_windows.go b/pkg/containerutil/container_network_manager_windows.go index 6cde2b351d8..54c771f6774 100644 --- a/pkg/containerutil/container_network_manager_windows.go +++ b/pkg/containerutil/container_network_manager_windows.go @@ -69,7 +69,7 @@ func (m *cniNetworkManager) VerifyNetworkOptions(_ context.Context) error { func (m *cniNetworkManager) getCNI() (cni.CNI, error) { e, err := netutil.NewCNIEnv(m.globalOptions.CNIPath, m.globalOptions.CNINetConfPath, netutil.WithNamespace(m.globalOptions.Namespace), netutil.WithDefaultNetwork(m.globalOptions.BridgeIP)) if err != nil { - return nil, fmt.Errorf("failed to instantiate CNI env: %s", err) + return nil, fmt.Errorf("failed to instantiate CNI env: %w", err) } cniOpts := []cni.Opt{ @@ -92,7 +92,7 @@ func (m *cniNetworkManager) getCNI() (cni.CNI, error) { func (m *cniNetworkManager) SetupNetworking(ctx context.Context, containerID string) error { cni, err := m.getCNI() if err != nil { - return fmt.Errorf("failed to get container networking for setup: %s", err) + return fmt.Errorf("failed to get container networking for setup: %w", err) } netNs, err := m.setupNetNs() @@ -110,12 +110,12 @@ func (m *cniNetworkManager) CleanupNetworking(ctx context.Context, container con containerID := container.ID() cni, err := m.getCNI() if err != nil { - return fmt.Errorf("failed to get container networking for cleanup: %s", err) + return fmt.Errorf("failed to get container networking for cleanup: %w", err) } spec, err := container.Spec(ctx) if err != nil { - return fmt.Errorf("failed to get container specs for networking cleanup: %s", err) + return fmt.Errorf("failed to get container specs for networking cleanup: %w", err) } netNsID, found := spec.Annotations[ocihook.NetworkNamespace] diff --git a/pkg/logging/fluentd_logger.go b/pkg/logging/fluentd_logger.go index c0a7d579fdb..7dc4c308c11 100644 --- a/pkg/logging/fluentd_logger.go +++ b/pkg/logging/fluentd_logger.go @@ -219,20 +219,20 @@ func parseFluentdConfig(config map[string]string) (fluent.Config, error) { result := fluent.Config{} location, err := parseAddress(config[fluentAddress]) if err != nil { - return result, fmt.Errorf("error occurs %v,invalid fluentd address (%s)", err, config[fluentAddress]) + return result, fmt.Errorf("error occurs %w,invalid fluentd address (%s)", err, config[fluentAddress]) } bufferLimit := defaultBufferLimit if config[fluentdBufferLimit] != "" { bufferLimit, err = strconv.Atoi(config[fluentdBufferLimit]) if err != nil { - return result, fmt.Errorf("error occurs %v,invalid buffer limit (%s)", err, config[fluentdBufferLimit]) + return result, fmt.Errorf("error occurs %w,invalid buffer limit (%s)", err, config[fluentdBufferLimit]) } } retryWait := int(defaultRetryWait) if config[fluentdRetryWait] != "" { temp, err := time.ParseDuration(config[fluentdRetryWait]) if err != nil { - return result, fmt.Errorf("error occurs %v,invalid retry wait (%s)", err, config[fluentdRetryWait]) + return result, fmt.Errorf("error occurs %w,invalid retry wait (%s)", err, config[fluentdRetryWait]) } retryWait = int(temp.Milliseconds()) } @@ -240,21 +240,21 @@ func parseFluentdConfig(config map[string]string) (fluent.Config, error) { if config[fluentdMaxRetries] != "" { maxRetries, err = strconv.Atoi(config[fluentdMaxRetries]) if err != nil { - return result, fmt.Errorf("error occurs %v,invalid max retries (%s)", err, config[fluentdMaxRetries]) + return result, fmt.Errorf("error occurs %w,invalid max retries (%s)", err, config[fluentdMaxRetries]) } } async := false if config[fluentdAsync] != "" { async, err = strconv.ParseBool(config[fluentdAsync]) if err != nil { - return result, fmt.Errorf("error occurs %v,invalid async (%s)", err, config[fluentdAsync]) + return result, fmt.Errorf("error occurs %w,invalid async (%s)", err, config[fluentdAsync]) } } asyncReconnectInterval := 0 if config[fluentdAsyncReconnectInterval] != "" { tempDuration, err := time.ParseDuration(config[fluentdAsyncReconnectInterval]) if err != nil { - return result, fmt.Errorf("error occurs %v,invalid async connect interval (%s)", err, config[fluentdAsyncReconnectInterval]) + return result, fmt.Errorf("error occurs %w,invalid async connect interval (%s)", err, config[fluentdAsyncReconnectInterval]) } if tempDuration != 0 && (tempDuration < minReconnectInterval || tempDuration > maxReconnectInterval) { return result, fmt.Errorf("invalid async connect interval (%s), must be between %d and %d", config[fluentdAsyncReconnectInterval], minReconnectInterval.Milliseconds(), maxReconnectInterval.Milliseconds()) @@ -265,14 +265,14 @@ func parseFluentdConfig(config map[string]string) (fluent.Config, error) { if config[fluentdSubSecondPrecision] != "" { subSecondPrecision, err = strconv.ParseBool(config[fluentdSubSecondPrecision]) if err != nil { - return result, fmt.Errorf("error occurs %v,invalid sub second precision (%s)", err, config[fluentdSubSecondPrecision]) + return result, fmt.Errorf("error occurs %w,invalid sub second precision (%s)", err, config[fluentdSubSecondPrecision]) } } requestAck := false if config[fluentRequestAck] != "" { requestAck, err = strconv.ParseBool(config[fluentRequestAck]) if err != nil { - return result, fmt.Errorf("error occurs %v,invalid request ack (%s)", err, config[fluentRequestAck]) + return result, fmt.Errorf("error occurs %w,invalid request ack (%s)", err, config[fluentRequestAck]) } } result = fluent.Config{ diff --git a/pkg/logging/journald_logger.go b/pkg/logging/journald_logger.go index 404d4abd02f..4c7acda37d1 100644 --- a/pkg/logging/journald_logger.go +++ b/pkg/logging/journald_logger.go @@ -161,7 +161,7 @@ func (journaldLogger *JournaldLogger) PostProcess() error { func FetchLogs(stdout, stderr io.Writer, journalctlArgs []string, stopChannel chan os.Signal) error { journalctl, err := exec.LookPath("journalctl") if err != nil { - return fmt.Errorf("could not find `journalctl` executable in PATH: %s", err) + return fmt.Errorf("could not find `journalctl` executable in PATH: %w", err) } cmd := exec.Command(journalctl, journalctlArgs...) @@ -169,7 +169,7 @@ func FetchLogs(stdout, stderr io.Writer, journalctlArgs []string, stopChannel ch cmd.Stderr = stderr if err := cmd.Start(); err != nil { - return fmt.Errorf("failed to start journalctl command with args %#v: %s", journalctlArgs, err) + return fmt.Errorf("failed to start journalctl command with args %#v: %w", journalctlArgs, err) } // Setup killing goroutine: diff --git a/pkg/logging/json_logger.go b/pkg/logging/json_logger.go index 1066f0ad5f3..a5297e755ce 100644 --- a/pkg/logging/json_logger.go +++ b/pkg/logging/json_logger.go @@ -192,12 +192,12 @@ func viewLogsJSONFileDirect(lvopts LogViewOptions, jsonLogFilePath string, stdou time.Sleep(5 * time.Millisecond) if retryTimes == 0 { log.L.Infof("finished parsing log JSON filefile, path: %s, line: %s", jsonLogFilePath, string(line)) - return fmt.Errorf("error occurred while doing read of JSON logfile %q: %s, retryTimes: %d", jsonLogFilePath, err, retryTimes) + return fmt.Errorf("error occurred while doing read of JSON logfile %q: %w, retryTimes: %d", jsonLogFilePath, err, retryTimes) } retryTimes-- backBytes = len(line) } else { - return fmt.Errorf("error occurred while doing read of JSON logfile %q: %s", jsonLogFilePath, err) + return fmt.Errorf("error occurred while doing read of JSON logfile %q: %w", jsonLogFilePath, err) } } else { retryTimes = 2 diff --git a/pkg/logging/log_viewer.go b/pkg/logging/log_viewer.go index 7cbc0292edf..e8eec8bd8cc 100644 --- a/pkg/logging/log_viewer.go +++ b/pkg/logging/log_viewer.go @@ -122,12 +122,12 @@ func InitContainerLogViewer(containerLabels map[string]string, lvopts LogViewOpt lcfg.Driver = "cri" } else { if err := lvopts.Validate(); err != nil { - return nil, fmt.Errorf("invalid LogViewOptions provided (%#v): %s", lvopts, err) + return nil, fmt.Errorf("invalid LogViewOptions provided (%#v): %w", lvopts, err) } lcfg, err = LoadLogConfig(lvopts.DatastoreRootPath, lvopts.Namespace, lvopts.ContainerID) if err != nil { - return nil, fmt.Errorf("failed to load logging config: %s", err) + return nil, fmt.Errorf("failed to load logging config: %w", err) } } diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index 0a5e57d5524..c16cbcd3986 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -139,12 +139,12 @@ func LoadLogConfig(dataStore, ns, id string) (LogConfig, error) { logConfigFilePath := LogConfigFilePath(dataStore, ns, id) logConfigData, err := os.ReadFile(logConfigFilePath) if err != nil { - return logConfig, fmt.Errorf("failed to read log config file %q: %s", logConfigFilePath, err) + return logConfig, fmt.Errorf("failed to read log config file %q: %w", logConfigFilePath, err) } err = json.Unmarshal(logConfigData, &logConfig) if err != nil { - return logConfig, fmt.Errorf("failed to load JSON logging config file %q: %s", logConfigFilePath, err) + return logConfig, fmt.Errorf("failed to load JSON logging config file %q: %w", logConfigFilePath, err) } return logConfig, nil } diff --git a/pkg/mountutil/mountutil_windows.go b/pkg/mountutil/mountutil_windows.go index e81c072f39d..98fe6471a63 100644 --- a/pkg/mountutil/mountutil_windows.go +++ b/pkg/mountutil/mountutil_windows.go @@ -139,7 +139,7 @@ func splitVolumeSpec(raw string) ([]string, error) { compiledRegex, err := regexp.Compile(rxWindows) if err != nil { - return nil, fmt.Errorf("error compiling regex: %s", err) + return nil, fmt.Errorf("error compiling regex: %w", err) } return splitRawSpec(raw, compiledRegex) } diff --git a/pkg/netutil/netutil.go b/pkg/netutil/netutil.go index 5708cbc9487..d4db0a0b1b9 100644 --- a/pkg/netutil/netutil.go +++ b/pkg/netutil/netutil.go @@ -408,11 +408,11 @@ func (e *CNIEnv) GetDefaultNetworkConfig() (*NetworkConfig, error) { func (e *CNIEnv) ensureDefaultNetworkConfig(bridgeIP string) error { defaultNet, err := e.GetDefaultNetworkConfig() if err != nil { - return fmt.Errorf("failed to check for default network: %s", err) + return fmt.Errorf("failed to check for default network: %w", err) } if defaultNet == nil { if err := e.createDefaultNetworkConfig(bridgeIP); err != nil { - return fmt.Errorf("failed to create default network: %s", err) + return fmt.Errorf("failed to create default network: %w", err) } } return nil @@ -429,7 +429,7 @@ func (e *CNIEnv) createDefaultNetworkConfig(bridgeIP string) error { if bridgeIP != "" { bIP, bCIDR, err := net.ParseCIDR(bridgeIP) if err != nil { - return fmt.Errorf("invalid bridge ip %s: %s", bridgeIP, err) + return fmt.Errorf("invalid bridge ip %s: %w", bridgeIP, err) } bridgeGatewayIP = bIP.String() bridgeCIDR = bCIDR.String() diff --git a/pkg/ocihook/ocihook.go b/pkg/ocihook/ocihook.go index bcebedca18c..69cb10aa098 100644 --- a/pkg/ocihook/ocihook.go +++ b/pkg/ocihook/ocihook.go @@ -503,7 +503,7 @@ func applyNetworkSettings(opts *handlerOpts) error { } if !b4nnBindEnabled && len(opts.ports) > 0 { if err := exposePortsRootless(ctx, opts.rootlessKitClient, opts.ports); err != nil { - return fmt.Errorf("failed to expose ports in rootless mode: %s", err) + return fmt.Errorf("failed to expose ports in rootless mode: %w", err) } } } @@ -590,7 +590,7 @@ func onPostStop(opts *handlerOpts) error { } if !b4nnBindEnabled && len(opts.ports) > 0 { if err := unexposePortsRootless(ctx, opts.rootlessKitClient, opts.ports); err != nil { - return fmt.Errorf("failed to unexpose ports in rootless mode: %s", err) + return fmt.Errorf("failed to unexpose ports in rootless mode: %w", err) } } } From 2a750939d360da5556d89c192e336b680a816875 Mon Sep 17 00:00:00 2001 From: apostasie Date: Wed, 22 Jan 2025 13:35:31 -0800 Subject: [PATCH 1057/1066] Consistently use WithError when logging errors instead of %s Signed-off-by: apostasie --- cmd/nerdctl/container/container_run.go | 2 +- pkg/infoutil/infoutil.go | 6 +++--- pkg/logging/jsonfile/jsonfile.go | 2 +- pkg/logging/logging.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/nerdctl/container/container_run.go b/cmd/nerdctl/container/container_run.go index 1a0639749c9..31a9dacb5b1 100644 --- a/cmd/nerdctl/container/container_run.go +++ b/cmd/nerdctl/container/container_run.go @@ -386,7 +386,7 @@ func runAction(cmd *cobra.Command, args []string) error { return } if err := netManager.CleanupNetworking(ctx, c); err != nil { - log.L.Warnf("failed to clean up container networking: %s", err) + log.L.WithError(err).Warnf("failed to clean up container networking") } if err := container.RemoveContainer(ctx, c, createOpt.GOptions, true, true, client); err != nil { log.L.WithError(err).Warnf("failed to remove container %s", id) diff --git a/pkg/infoutil/infoutil.go b/pkg/infoutil/infoutil.go index 43041dd5d1b..2886c9fe049 100644 --- a/pkg/infoutil/infoutil.go +++ b/pkg/infoutil/infoutil.go @@ -160,13 +160,13 @@ func ServerSemVer(ctx context.Context, client *containerd.Client) (*semver.Versi func buildctlVersion() dockercompat.ComponentVersion { buildctlBinary, err := buildkitutil.BuildctlBinary() if err != nil { - log.L.Warnf("unable to determine buildctl version: %s", err.Error()) + log.L.WithError(err).Warnf("unable to determine buildctl version") return dockercompat.ComponentVersion{Name: "buildctl"} } stdout, err := exec.Command(buildctlBinary, "--version").Output() if err != nil { - log.L.Warnf("unable to determine buildctl version: %s", err.Error()) + log.L.WithError(err).Warnf("unable to determine buildctl version") return dockercompat.ComponentVersion{Name: "buildctl"} } @@ -205,7 +205,7 @@ func parseBuildctlVersion(buildctlVersionStdout []byte) (*dockercompat.Component func runcVersion() dockercompat.ComponentVersion { stdout, err := exec.Command("runc", "--version").Output() if err != nil { - log.L.Warnf("unable to determine runc version: %s", err.Error()) + log.L.WithError(err).Warnf("unable to determine runc version") return dockercompat.ComponentVersion{Name: "runc"} } v, err := parseRuncVersion(stdout) diff --git a/pkg/logging/jsonfile/jsonfile.go b/pkg/logging/jsonfile/jsonfile.go index 2e47b836819..a1693cda0d7 100644 --- a/pkg/logging/jsonfile/jsonfile.go +++ b/pkg/logging/jsonfile/jsonfile.go @@ -146,7 +146,7 @@ func Decode(stdout, stderr io.Writer, r io.Reader, timestamps bool, since string // Write out the entry directly err := writeEntry(&e, stdout, stderr, now, timestamps, since, until) if err != nil { - log.L.Errorf("error while writing log entry to output stream: %s", err) + log.L.WithError(err).Errorf("error while writing log entry to output stream") } } diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index c16cbcd3986..15663acc868 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -264,7 +264,7 @@ func startTail(ctx context.Context, logName string, w *fsnotify.Watcher) (bool, log.L.Debugf("Received unexpected fsnotify event: %v, retrying", e) } case err := <-w.Errors: - log.L.Debugf("Received fsnotify watch error, retrying unless no more retries left, retries: %d, error: %s", errRetry, err) + log.L.WithError(err).Debugf("Received fsnotify watch error, retrying unless no more retries left, retries: %d", errRetry) if errRetry == 0 { return false, err } From 82791bf62c688418af7f17e2b0ab9f22d341661d Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 24 Jan 2025 00:24:43 -0800 Subject: [PATCH 1058/1066] fix journald logger exit and wait behavior Signed-off-by: apostasie --- pkg/logging/journald_logger.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/logging/journald_logger.go b/pkg/logging/journald_logger.go index 404d4abd02f..e20601a5b52 100644 --- a/pkg/logging/journald_logger.go +++ b/pkg/logging/journald_logger.go @@ -173,12 +173,21 @@ func FetchLogs(stdout, stderr io.Writer, journalctlArgs []string, stopChannel ch } // Setup killing goroutine: + killed := false go func() { <-stopChannel + killed = true log.L.Debugf("killing journalctl logs process with PID: %#v", cmd.Process.Pid) cmd.Process.Kill() }() + err = cmd.Wait() + if exitError, ok := err.(*exec.ExitError); ok { + if !killed && exitError.ExitCode() != 0 { + return fmt.Errorf("journalctl command exited with non-zero exit code (%d): %w", exitError.ExitCode(), exitError) + } + } + return nil } From 653c6de0da9d8cd29246b2fc3dfdfa35b5920a38 Mon Sep 17 00:00:00 2001 From: Hayato Kiwata Date: Tue, 28 Jan 2025 14:44:42 +0000 Subject: [PATCH 1059/1066] test: Add a test for container access with 127.0.0.2 specified in -p in rootless mode When running a rootless container, specifying an address such as 127.0.0.2 for the -p option, we will not be able to access the published container through that address. This behavior is reported in the following issue: - https://github.com/containerd/nerdctl/issues/3539 This behavior is caused by the behavior in rootlesskit, and the following pull request has been made to improve the behavior. - https://github.com/rootless-containers/rootlesskit/pull/477 Therefore, this commit adds a test to ensure that the behavior of the issue has been improved. Signed-off-by: Hayato Kiwata --- .../container/container_run_linux_test.go | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/cmd/nerdctl/container/container_run_linux_test.go b/cmd/nerdctl/container/container_run_linux_test.go index dc33702e1bd..c928b3f4463 100644 --- a/cmd/nerdctl/container/container_run_linux_test.go +++ b/cmd/nerdctl/container/container_run_linux_test.go @@ -40,6 +40,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/strutil" "github.com/containerd/nerdctl/v2/pkg/testutil" "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" + "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil" "github.com/containerd/nerdctl/v2/pkg/testutil/test" ) @@ -567,3 +568,45 @@ func TestIssue3568(t *testing.T) { testCase.Run(t) } + +// TestPortBindingWithCustomHost tests https://github.com/containerd/nerdctl/issues/3539 +func TestPortBindingWithCustomHost(t *testing.T) { + testCase := nerdtest.Setup() + + const ( + host = "127.0.0.2" + hostPort = 8080 + ) + address := fmt.Sprintf("%s:%d", host, hostPort) + + testCase.SubTests = []*test.Case{ + { + Description: "Issue #3539 - Access to a container running when 127.0.0.2 is specified in -p in rootless mode.", + Setup: func(data test.Data, helpers test.Helpers) { + helpers.Ensure("run", "-d", "--name", data.Identifier(), "-p", fmt.Sprintf("%s:80", address), testutil.NginxAlpineImage) + nerdtest.EnsureContainerStarted(helpers, data.Identifier()) + }, + Cleanup: func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + }, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: 0, + Errors: []error{}, + Output: test.All( + func(stdout string, info string, t *testing.T) { + resp, err := nettestutil.HTTPGet(address, 30, false) + assert.NilError(t, err) + + respBody, err := io.ReadAll(resp.Body) + assert.NilError(t, err) + assert.Assert(t, strings.Contains(string(respBody), testutil.NginxAlpineIndexHTMLSnippet)) + }, + ), + } + }, + }, + } + + testCase.Run(t) +} From 7565cebb5b39023aa8f6c2fd79b736074dfa93be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2025 22:36:56 +0000 Subject: [PATCH 1060/1066] build(deps): bump github.com/cyphar/filepath-securejoin Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.4.0 to 0.4.1. - [Release notes](https://github.com/cyphar/filepath-securejoin/releases) - [Changelog](https://github.com/cyphar/filepath-securejoin/blob/main/CHANGELOG.md) - [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.4.0...v0.4.1) --- updated-dependencies: - dependency-name: github.com/cyphar/filepath-securejoin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f92e9703619..7e25677a4e6 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/containernetworking/plugins v1.5.1 github.com/coreos/go-iptables v0.8.0 github.com/coreos/go-systemd/v22 v22.5.0 - github.com/cyphar/filepath-securejoin v0.4.0 + github.com/cyphar/filepath-securejoin v0.4.1 github.com/distribution/reference v0.6.0 github.com/docker/cli v27.5.1+incompatible github.com/docker/docker v27.5.1+incompatible diff --git a/go.sum b/go.sum index 71eead0c3cb..8d69b44038d 100644 --- a/go.sum +++ b/go.sum @@ -80,8 +80,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.4.0 h1:PioTG9TBRSApBpYGnDU8HC+miIsX8vitBH9LGNNMoLQ= -github.com/cyphar/filepath-securejoin v0.4.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= +github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= From 8a80469c26e855492b4b2ab3ae5c383b397a8f6a Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 24 Jan 2025 13:40:26 -0800 Subject: [PATCH 1061/1066] Harden journald test Signed-off-by: apostasie --- cmd/nerdctl/container/container_logs_test.go | 10 +++++++++- cmd/nerdctl/container/container_run_test.go | 18 ++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/cmd/nerdctl/container/container_logs_test.go b/cmd/nerdctl/container/container_logs_test.go index 71debda52e9..2e6d4dbc44c 100644 --- a/cmd/nerdctl/container/container_logs_test.go +++ b/cmd/nerdctl/container/container_logs_test.go @@ -18,12 +18,14 @@ package container import ( "fmt" + "os/exec" "runtime" "strings" "testing" "time" "gotest.tools/v3/assert" + "gotest.tools/v3/icmd" "github.com/containerd/nerdctl/v2/pkg/testutil" ) @@ -109,8 +111,14 @@ func TestLogsWithInheritedFlags(t *testing.T) { } func TestLogsOfJournaldDriver(t *testing.T) { - t.Parallel() testutil.RequireExecutable(t, "journalctl") + journalctl, _ := exec.LookPath("journalctl") + res := icmd.RunCmd(icmd.Command(journalctl, "-xe")) + if res.ExitCode != 0 { + t.Skipf("current user is not allowed to access journal logs: %s", res.Combined()) + } + + t.Parallel() base := testutil.NewBase(t) containerName := testutil.Identifier(t) diff --git a/cmd/nerdctl/container/container_run_test.go b/cmd/nerdctl/container/container_run_test.go index 9a22aded3b0..0c2d57fc892 100644 --- a/cmd/nerdctl/container/container_run_test.go +++ b/cmd/nerdctl/container/container_run_test.go @@ -316,6 +316,13 @@ func TestRunWithJsonFileLogDriverAndLogPathOpt(t *testing.T) { } func TestRunWithJournaldLogDriver(t *testing.T) { + testutil.RequireExecutable(t, "journalctl") + journalctl, _ := exec.LookPath("journalctl") + res := icmd.RunCmd(icmd.Command(journalctl, "-xe")) + if res.ExitCode != 0 { + t.Skipf("current user is not allowed to access journal logs: %s", res.Combined()) + } + if runtime.GOOS == "windows" { t.Skip("journald log driver is not yet implemented on Windows") } @@ -327,8 +334,6 @@ func TestRunWithJournaldLogDriver(t *testing.T) { "sh", "-euxc", "echo foo; echo bar").AssertOK() time.Sleep(3 * time.Second) - journalctl, err := exec.LookPath("journalctl") - assert.NilError(t, err) inspectedContainer := base.InspectContainer(containerName) @@ -370,6 +375,13 @@ func TestRunWithJournaldLogDriver(t *testing.T) { } func TestRunWithJournaldLogDriverAndLogOpt(t *testing.T) { + testutil.RequireExecutable(t, "journalctl") + journalctl, _ := exec.LookPath("journalctl") + res := icmd.RunCmd(icmd.Command(journalctl, "-xe")) + if res.ExitCode != 0 { + t.Skipf("current user is not allowed to access journal logs: %s", res.Combined()) + } + if runtime.GOOS == "windows" { t.Skip("journald log driver is not yet implemented on Windows") } @@ -381,8 +393,6 @@ func TestRunWithJournaldLogDriverAndLogOpt(t *testing.T) { "sh", "-euxc", "echo foo; echo bar").AssertOK() time.Sleep(3 * time.Second) - journalctl, err := exec.LookPath("journalctl") - assert.NilError(t, err) inspectedContainer := base.InspectContainer(containerName) found := 0 check := func(log poll.LogT) poll.Result { From 2b07c18853286abcd8aca1e9f6531d5a88dbf92f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jan 2025 22:35:12 +0000 Subject: [PATCH 1062/1066] build(deps): bump github.com/spf13/pflag from 1.0.5 to 1.0.6 Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.5 to 1.0.6. - [Release notes](https://github.com/spf13/pflag/releases) - [Commits](https://github.com/spf13/pflag/compare/v1.0.5...v1.0.6) --- updated-dependencies: - dependency-name: github.com/spf13/pflag dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 7e25677a4e6..fe6eee4d481 100644 --- a/go.mod +++ b/go.mod @@ -60,7 +60,7 @@ require ( github.com/rootless-containers/bypass4netns v0.4.2 github.com/rootless-containers/rootlesskit/v2 v2.3.2 github.com/spf13/cobra v1.8.1 - github.com/spf13/pflag v1.0.5 + github.com/spf13/pflag v1.0.6 github.com/vishvananda/netlink v1.3.0 github.com/vishvananda/netns v0.0.5 github.com/yuchanns/srslog v1.1.0 diff --git a/go.sum b/go.sum index 8d69b44038d..121edca4277 100644 --- a/go.sum +++ b/go.sum @@ -289,8 +289,9 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -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/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 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= From 38636145149776363c5bb16535480fd49ff7372e Mon Sep 17 00:00:00 2001 From: apostasie Date: Mon, 27 Jan 2025 15:59:01 -0800 Subject: [PATCH 1063/1066] Prevent reference filter from failing on dangling images Signed-off-by: apostasie --- pkg/imgutil/filtering.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/imgutil/filtering.go b/pkg/imgutil/filtering.go index 5555380ba4c..26525d86cb2 100644 --- a/pkg/imgutil/filtering.go +++ b/pkg/imgutil/filtering.go @@ -325,6 +325,11 @@ func matchesAllLabels(imageCfgLabels map[string]string, filterLabels map[string] func matchesReferences(image images.Image, referencePatterns []string) (bool, error) { var matches int + // Containerd returns ":" for dangling untagged images - see https://github.com/containerd/nerdctl/issues/3852 + if image.Name == ":" { + return false, nil + } + parsedReference, err := referenceutil.Parse(image.Name) if err != nil { return false, err From 2ecc39445615cdafd8bb7b3cc5a6cad7e5563644 Mon Sep 17 00:00:00 2001 From: apostasie Date: Fri, 31 Jan 2025 14:32:26 -0800 Subject: [PATCH 1064/1066] Fix apparmor test not running Signed-off-by: apostasie --- Dockerfile.d/test-integration-rootless.sh | 4 ++++ hack/test-integration.sh | 7 +++++++ pkg/apparmorutil/apparmorutil_linux.go | 20 ++++++++++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Dockerfile.d/test-integration-rootless.sh b/Dockerfile.d/test-integration-rootless.sh index 4bdbf0fa4eb..481610eb1bc 100755 --- a/Dockerfile.d/test-integration-rootless.sh +++ b/Dockerfile.d/test-integration-rootless.sh @@ -16,6 +16,10 @@ set -eux -o pipefail if [[ "$(id -u)" = "0" ]]; then + # Ensure securityfs is mounted for apparmor to work + if ! mountpoint -q /sys/kernel/security; then + mount -tsecurityfs securityfs /sys/kernel/security + fi if [ -e /sys/kernel/security/apparmor/profiles ]; then # Load the "nerdctl-default" profile for TestRunApparmor nerdctl apparmor load diff --git a/hack/test-integration.sh b/hack/test-integration.sh index 73e2b4ebb19..7834216b463 100755 --- a/hack/test-integration.sh +++ b/hack/test-integration.sh @@ -19,6 +19,13 @@ 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 +if [[ "$(id -u)" = "0" ]]; then + # Ensure securityfs is mounted for apparmor to work + if ! mountpoint -q /sys/kernel/security; then + mount -tsecurityfs securityfs /sys/kernel/security + fi +fi + readonly timeout="60m" readonly retries="2" readonly needsudo="${WITH_SUDO:-}" diff --git a/pkg/apparmorutil/apparmorutil_linux.go b/pkg/apparmorutil/apparmorutil_linux.go index 600047a54da..cbf1100c125 100644 --- a/pkg/apparmorutil/apparmorutil_linux.go +++ b/pkg/apparmorutil/apparmorutil_linux.go @@ -25,10 +25,26 @@ import ( "github.com/moby/sys/userns" - "github.com/containerd/containerd/v2/pkg/apparmor" "github.com/containerd/log" ) +var ( + appArmorSupported bool + checkAppArmor sync.Once +) + +// hostSupports returns true if apparmor is enabled for the host +func hostSupports() bool { + checkAppArmor.Do(func() { + // see https://github.com/opencontainers/runc/blob/0d49470392206f40eaab3b2190a57fe7bb3df458/libcontainer/apparmor/apparmor_linux.go + if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil { + buf, err := os.ReadFile("/sys/module/apparmor/parameters/enabled") + appArmorSupported = err == nil && len(buf) > 1 && buf[0] == 'Y' + } + }) + return appArmorSupported +} + // CanLoadNewProfile returns whether the current process can load a new AppArmor profile. // // CanLoadNewProfile needs root. @@ -37,7 +53,7 @@ import ( // // Related: https://gitlab.com/apparmor/apparmor/-/blob/v3.0.3/libraries/libapparmor/src/kernel.c#L311 func CanLoadNewProfile() bool { - return !userns.RunningInUserNS() && os.Geteuid() == 0 && apparmor.HostSupports() + return !userns.RunningInUserNS() && os.Geteuid() == 0 && hostSupports() } var ( From fd0bcbe5f898cfd4e6ece194fd4abb095760da0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 22:36:54 +0000 Subject: [PATCH 1065/1066] build(deps): bump the golang-x group with 4 updates Bumps the golang-x group with 4 updates: [golang.org/x/sync](https://github.com/golang/sync), [golang.org/x/sys](https://github.com/golang/sys), [golang.org/x/term](https://github.com/golang/term) and [golang.org/x/text](https://github.com/golang/text). Updates `golang.org/x/sync` from 0.10.0 to 0.11.0 - [Commits](https://github.com/golang/sync/compare/v0.10.0...v0.11.0) Updates `golang.org/x/sys` from 0.29.0 to 0.30.0 - [Commits](https://github.com/golang/sys/compare/v0.29.0...v0.30.0) Updates `golang.org/x/term` from 0.28.0 to 0.29.0 - [Commits](https://github.com/golang/term/compare/v0.28.0...v0.29.0) Updates `golang.org/x/text` from 0.21.0 to 0.22.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.21.0...v0.22.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor dependency-group: golang-x ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 14 ++++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index fe6eee4d481..c8e76b8df9b 100644 --- a/go.mod +++ b/go.mod @@ -67,10 +67,10 @@ require ( go.uber.org/mock v0.5.0 golang.org/x/crypto v0.32.0 golang.org/x/net v0.34.0 - golang.org/x/sync v0.10.0 - golang.org/x/sys v0.29.0 - golang.org/x/term v0.28.0 - golang.org/x/text v0.21.0 + golang.org/x/sync v0.11.0 + golang.org/x/sys v0.30.0 + golang.org/x/term v0.29.0 + golang.org/x/text v0.22.0 gopkg.in/yaml.v3 v3.0.1 gotest.tools/v3 v3.5.1 ) diff --git a/go.sum b/go.sum index 121edca4277..70fc2630935 100644 --- a/go.sum +++ b/go.sum @@ -402,8 +402,9 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -428,8 +429,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -439,8 +440,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -449,8 +450,9 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From 5e36bef0ebcdfa3999c0ef358ede4448f4e94caf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 22:48:08 +0000 Subject: [PATCH 1066/1066] build(deps): bump golangci/golangci-lint-action from 6.2.0 to 6.3.0 Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6.2.0 to 6.3.0. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/ec5d18412c0aeab7936cb16880d708ba2a64e1ae...e60da84bfae8c7920a47be973d75e15710aa8bd7) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4af31aaf325..e2cae2e9c46 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -51,7 +51,7 @@ jobs: go-version: ${{ env.GO_VERSION }} check-latest: true - name: golangci-lint - uses: golangci/golangci-lint-action@ec5d18412c0aeab7936cb16880d708ba2a64e1ae # v6.2.0 + uses: golangci/golangci-lint-action@e60da84bfae8c7920a47be973d75e15710aa8bd7 # v6.3.0 with: args: --verbose other: